Ausgabe von pg_ctl auslesen

Hallo zusammen,

Sorry, sollte ich hier im falschen Unterforum gelandet sein. Es geht um Folgendes:
Ich muss PostgreSQL aus einer Anwendung heraus starten, stoppen und verwalten. Die ersten Tests mit QProcess (Qt und C++ auf Windows 7 Enterprise SP 1. PostgreSQL Versionen: 9.3.5 und 9.5.0) waren auch an sich erfolgreich. Nur ist die Fehler-Ausgabe (StandardError) bei pg_ctl komplett leer, wenn ich sie auslese, obwohl sie es nicht sein sollte (ausgeführt in einer Kommandozeile gibt es Ausgabe). Um Fehler zu erkennen wäre das aber relativ hilfreich.

Ich habe dann mal versucht die Ausgabe von pg_ctl von einer Kommandozeile in eine Datei zu pipen:

pg_ctl status -D ... > D:\temp\log.txt

Funktioniert, für Standard-Meldungen. Aber Fehler pipen:

pg-ctl status 2> D:\temp\log.txt

…funktioniert nicht - die Datei wird angelegt, ist aber leer (pg_ctl sollte hier meckern, dass -D fehlt).

Hätte jemand eine Idee, woran das liegen könnte/wie ich trotzdem an die Fehlernachrichten komme? Wäre es möglich die Ausgabe in eine Log-Datei schreiben zu lassen und auf die dann zuzugreifen? pg_ctl status nimmt scheinbar keinen Parameter “-l”.

Verwirrt habe ich den Source runtergeladen. Prinzipiell kommt mir das hier ein bisschen komisch vor: (ab Z208, pg_ctl.c)

static void write_stderr(const char *fmt,...)
{
    // [...]
    if (!pgwin32_is_service())    /* Running as a service */
    {
        char        errbuf[2048];        /* Arbitrary size? */
        vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
        write_eventlog(EVENTLOG_ERROR_TYPE, errbuf);
    }
    else
        /* Not running as service, write to stderr */
        vfprintf(stderr, fmt, ap);
    // [...]
}

Und (ab Z1756 pg_ctl.c):

/*
 * We consider ourselves running as a service if one of the following is
 * true:
 *
 * 1) We are running as Local System (only used by services)
 * 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
 *      process token by the SCM when starting a service)
 *
 * Return values:
 *     0 = Not service
 *     1 = Service
 *    -1 = Error
 *
 * Note: we can't report errors via write_stderr (because that calls this)
 * We are therefore reduced to writing directly on stderr, which sucks, but
 * we have few alternatives.
 */
int pgwin32_is_service(void) { /*** [...] ***/ }

Wenn mich nicht alles täuscht macht die If das Gegenteil davon, was in den Kommentaren beschrieben steht? PostgreSQL kompilieren und testen ist auf der Arbeit für mich gerade leider keine Option.
Hat jemand eine Idee?
Kennt ansonsten jemand eine besser Variante aus C++ einen PostgreSQL-Server zu starten/stoppen/…?

Vielen Dank im Voraus schonmal!
Viele Grüße,
DoubleM

Hallo,

im Zweifelsfall könntest du die Ausgabe via -l/–log in eine temporäre Datei schreiben und dort dann die Informationen auslesen.
Hat auch den Vorteil, dass dort alles etwas genauer protokolliert wird.
Ist vielleicht nicht die coolste-Lösung, aber vielleicht die praktikabelste :slight_smile:

Hallo DaniloE,

Danke für deine Antwort!
Wie würde ich das denn anstellen? Scheinbar nimmt pg_ctl status keinen -l Parameter.

pg_ctl status [-D datadir]

vs

pg_ctl start [-w] [-t seconds] [-s] [-D datadir] [-l filename] [-o options] [-p path] [-c]

Kann ich noch anderswo eine Log-Datei festlegen?

Zuhause habe ich PostgreSQL mal kurz kompiliert und testweise die Code-Stelle aus dem ersten Post korrigiert. Also

 if (pgwin32_is_service())    /* Running as a service */

statt

 if (!pgwin32_is_service())    /* Running as a service */

So lässt sich die Fehlerausgabe dann korrekt umleiten. Auf meinem Windows 10 Rechner kommen ohne den Fix auch überhaupt keine Fehlermeldungen in der Kommandozeile sonst. Ich denke das dürfte recht sicher ein Bug sein, werde ich mal melden.

Hallo,

ich vergas…das ist ja Windows…ich hab hier nur unter Linux geschaut:

# pg_ctl --help
...
Options for start or restart:
  -c, --core-files       allow postgres to produce core files
  -l, --log=FILENAME     write (or append) server log to FILENAME
...

Und hier hab ich ehrlich gesagt auch gut überlesen, dass es nur bei start oder restart funktioniert.
Wenn das so unter Windows nicht funktioniert, ist das natürlich ärgerlich. Ich empfehle eine Migration auf Linux und deine Probleme, sowie viele andere sollten gelöst sein :smiley:

Wie genau rufst du das Ganze denn auf? Aus C++ bzw. Qt mittels so einer Art “Shellaufruf”(Vergleichbar vllt. Python und os.system(‘md testordner’)?

Hallo,

Linux ist keine Option :smiley:

Mithilfe von Qt’s QProcess. Im Prinzip setze ich die benötigten Umgebungsvariablen, definiere die Parameter und starte dann den Prozess. In der Callback-Funktion wenn der Prozess fertig ist lese ich dann mit readAllStandardOut/readAllStandardError die Ausgabe aus.
Ich weiß nicht 100%, was Qt da intern macht, aber es sollte eigentlich kein Shellaufruf sein, der Prozess sollte direkt gestartet werden. Theoretisch könnte ich auch mit QProcess eine Shell starten und dann darin pg_ctl ausführen. Das ist aber tendentiell ziemlich unschön und bei meinen Tests unter Windows 10 hat die Error-Ausgabe noch nichtmals in der Kommandezeile funktioniert. :frowning:

Hm ,ok. Damit wäre meine Idee auch schon weg.
Ich hab hier nochmal in http://www.postgresql.org/docs/9.3/static/app-pg-ctl.html geschaut:

On Windows, by default the server's standard output and standard error are sent to the terminal. These default behaviors can be changed by using -l to append the server's output to a log file. Use of either -l or output redirection is recommended.

Ich verstehe hier also gerade nicht, warum die Option bei dir nicht funktioniert. Wenn ich in der Doku ein wenig durch die Versionen blätter gibt es die Option seit 9.0.
Du hast hier nicht aus irgendwelchen Gründen eine total veraltete Version von pg_ctl (pg_ctl --version) ? :wink:

Ansonsten hab ich leider spontan auch keine Idee mehr…

Wenn ich das richtig in Erinnerung habe startet “pg_ctl start” den Server als separaten Prozess und terminiert dann. “-l” leitet dann die Ausgabe vom Server um, nicht aber von pg_ctl selber. Wenn also das Starten des Servers fehlschlägt gibt es kein Log - das wäre meine Vermutung.

Danke für deine Hilfe! Ich habe den Bug gemeldet und benutze bis die gefixte Version online geht eine von Hand gepatchte Version. So sollte es dann klappen :slight_smile:

Hm…das kann natürlich sein. Kannst ja mal das Bugticket hier verlinken, dann hat man das auch gleich zur Hand, falls da mal wieder was kommt :slight_smile:

OK, hier ist der Link: :slight_smile:
http://www.postgresql.org/message-id/20160305120021.2722.16982@wrigleys.postgresql.org