Container-Logging in Verbindung mit stdin und stdout

Status
Für weitere Antworten geschlossen.

geimist

Benutzer
Sehr erfahren
Maintainer
Mitglied seit
04. Jan 2012
Beiträge
5.371
Punkte für Reaktionen
1.188
Punkte
234
Hallo zusammen,

der jarbalow83/ocrmypdf Container hat Berechtigungsprobleme, sofern das gemountete Volumen nicht der home-Ordner ist. Abhilfe schafft der Parameter -i womit ich die Quelldatei als stdin und die Ausgabedatei als stdout über- und ausgeben lasse. Das funktioniert auch.

Mein Problem ist jetzt das Logging. Die Ausgabe von Docker kommt immer im Terminal / Screen an, auch wenn ich die Ausgabe meines Skriptes explizit in eine Datei umleite.

Mein Aufruf sieht so aus:
Rich (BBCode):
dockerlog=$( docker run --rm -i $dockercontainer $ocropt - - < "$input" > "$output" )
echo "$dockerlog"

So ein Skriptaufruf loggt alles andere, aber nicht die Zeile mit dem Dockeraufruf:
Rich (BBCode):
sh ./skript.sh >> logdatei.log 2>&1

Der Entwickler verwieß mich auf diesen Link, ich habe die Logik dahinter aber noch nicht verstanden und umsetzen können.

Wer hat einen guten Rat für mich, wie ich das Protokoll von docker abfangen kann?

Vielen Dank im Voraus :)
 

haydibe

Benutzer
Sehr erfahren
Mitglied seit
12. Apr 2016
Beiträge
1.468
Punkte für Reaktionen
356
Punkte
103
Per Default wird der Synology-DB-Logging Treiber verwendet. Ist das bei diesem Container nicht der Fall?
Nur dann würde Dein Workaround tatsächlich Sinn ergeben :)

Dein Wrapper-Skript kümmert sich ja eigneltich schon sauber um das Pipen der Log-Ausgaben in eine Datei.

Der Aufruf aus dem Links ist gedacht um Sachen in den Container zu pipen und die Ausgaben aus dem Contaienr weiter in einer Pipe verwenden zu können.
Ich denke, wenn Du die Syntax von dort verwendest wird es gehen. Bist Du sicher, dass bei dir "$output" nicht im Container erzeugt wird?
 

geimist

Benutzer
Sehr erfahren
Maintainer
Mitglied seit
04. Jan 2012
Beiträge
5.371
Punkte für Reaktionen
1.188
Punkte
234
Hallo haydibe,

ich habe gehofft, dass du dich meldest :cool:
… Bist Du sicher, dass bei dir "$output" nicht im Container erzeugt wird?
Ja, $output enthält den kompletten Zielpfad und wird wie gewünscht korrekt erstellt. Ich komme lediglich nicht an den Dockerlog heran.

Ich habe die Info aus dem Link ja auch schon versucht (offensichtlich nicht korrekt) umzusetzen. Da scheint aber Docker den Parameter -a nicht zu kennen, bzw. funktioniert auch die Ausgabe der Zieldatei nicht:
Rich (BBCode):
docker run --rm -i --log-driver=none $dockercontainer $ocropt -a $input -a $output -a 2>&1

… Dein Wrapper-Skript kümmert sich ja eigneltich schon sauber um das Pipen der Log-Ausgaben in eine Datei.…
Und das verstehe ich halt nicht, wie Docker das umgehen kann.

… Ich denke, wenn Du die Syntax von dort verwendest wird es gehen. …
Könntest du mir dabei bitte auf die Sprünge helfen? :rolleyes: Danke


P.S.:
achso: Ich dachte, dass mir evt. auch tee weiterhilft, aber das hat mich auch nicht weiter gebracht
 
Zuletzt bearbeitet:

haydibe

Benutzer
Sehr erfahren
Mitglied seit
12. Apr 2016
Beiträge
1.468
Punkte für Reaktionen
356
Punkte
103
Moin geimist!

Das Beispiel vom Link ist eigentlich ganz schick:
Code:
1. echo "This was piped into docker" |
2.  docker run -i --log-driver=none -a stdin -a stdout -a stderr \
3.    alpine cat - |
4.  xargs echo This is coming out of docker:

Was das Beispiel tut:
1. erzeugt eine Ausgabestrom auf STDOUT und piped diesen an den Container
2. started einen Container, wobei das Image erst in Zeile #3 angegeben wird
- mit interactive Flag, so das Eingaben im Container getätigt werden können
- set den Logging-Driver auf leer => deaktivert ihn so
- Anbinden (attach) der Ströme für STDIN, STDOUT,STDER von Host and denen des Containers
3. verwendet alpine als Image und übergibt diesem den CMD 'cat -'. Der Bindestrich steht für gebe auf STDOUT aus, was auf STDIN reinkommt. Der Spiegelstrich piped die Ausgabe vom Container dann weiter
4. Xargs führt den darauf folgenden Befehl aus gefolgt von dem was über STDIN durch 3. reingekommen ist.


Als Einzeiler dargestellt sieht man ganz gut, dass der "Docker-Anteil" standardisiert aussieht:
Code:
 echo "This was piped into docker" | docker run -it--log-driver=none -a stdin -a stdout -a stderr alpine cat - | xargs echo This is coming out of docker:
vs.
Code:
 echo "This was piped into docker" | cat - |   xargs echo This is coming out of docker:


Die korrekte Syntax ist: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Die attach "-a"-Angaben gehören auch noch zu [OPTIONS]. Sind doch Optionen von 'docker run' und nicht vom Entypoint-Skript im Container.

Ich glaube nicht das die Reihenfolge, in denen die Streams deklariert werden, relevant ist, sondern eher die Schlüsselwörter (stdin, stdout, stderr).
Sprich: ich könnte mir vorstellen das 2>&1 nicht funktioniert

Code:
docker run --rm -i --log-driver=none -a stdin -a stdout -a stderr $docker-image $ocropt
wobei $ocropt dann der CMD darstellt, der an das Entrypoint-Skript im Container übergeben wird.

Was Du haben willst ist also soetwas wie:
Code:
#ocropt=$(cat meineDatei)
ocropt=meine tollen command line argumente
docker run --rm -i --log-driver=none -a stdin -a stdout -a stderr $docker-image $ocropt | cat - >> logfile 2>&1

hoffe es klappt!
Hatte ehrlich gesagt noch nie den Use-Case auf die Terminal-Ausgabe direkt angewiesen zu sein.

Update: irgendetwas fehlt da noch. Ich glaube Du musst die Skripte mal ganz pasten, damit man es genauer sehen kann. Bitte die vollen Skripte und keine zusammengekürzen Sachen oder speziell vorbereitet Sachen. Anonymisieren von Werten ist natürlich okay. Alles andere führte gerne mal zu fehlern und dann schießt man sich auf vermeintliche Probleme ein, die es im "wahren" Skript gar nicht erst gibt.
 
Zuletzt bearbeitet:

Tommi2day

Benutzer
Mitglied seit
24. Aug 2011
Beiträge
1.164
Punkte für Reaktionen
63
Punkte
68
was spricht dagegen, in einer 2. Shell docker logs zu verwenden?
 

geimist

Benutzer
Sehr erfahren
Maintainer
Mitglied seit
04. Jan 2012
Beiträge
5.371
Punkte für Reaktionen
1.188
Punkte
234
Hallo zusammen,

vielen Dank für eure Geduld. Ich bin nicht eher zum Antworten gekommen.

… Update: irgendetwas fehlt da noch. Ich glaube Du musst die Skripte mal ganz pasten, damit man es genauer sehen kann. Bitte die vollen Skripte und keine zusammengekürzen Sachen oder speziell vorbereitet Sachen.…

Ich habe es dennoch mal zusammengekürzt, da das Problem grundlegend ist und damit genauso nachzuvollziehen ist. Vielleicht müsste man noch etwas eher beginnen. Das grundlegende Problem ist ja nicht die problematische Logausgabe, sondern das fehlende Schreibrecht von Docker in einem beliebigen Pfad. Dafür der Workaround mit stdin und stdout. Vielleicht habt ihr ja auch ein Tipp, die Ursache zu beheben. (Link1 / Link 2)

Übrigens muss ich mich korrigieren: Wenn ich in das Log 2>&1 ausgeben lassen, funktioniert zwar die Ausgabe des Dockerlog, allerdings nicht mehr die Zieldateiausgabe.

Hier der Skriptaufbau (anbei auch nochmal als Zip): Anhang anzeigen ocrmypdf.zip

Startskript:
Rich (BBCode):
#!/bin/bash

APPDIR=$(cd $(dirname $0);pwd)
cd ${APPDIR}

logfile="${APPDIR}/test.log"

sleep 1

${APPDIR}/ocrmypdf.sh > $logfile #2>&1

exit 0

OCR-Skript:
Rich (BBCode):
#!/bin/bash

APPDIR=$(cd $(dirname $0);pwd)
cd ${APPDIR}
    
input="${APPDIR}/test_in.pdf"
output="${APPDIR}/test_out.pdf"
dockercontainer="jbarlow83/ocrmypdf"
ocropt="-srd -l deu"

# OCRen
/usr/local/bin/docker run --name OCR --rm -i "$dockercontainer" $ocropt - - < "$input" > "$output"

# Dateiattribute übertragen:
cp --attributes-only -p "$input" "$output"

sleep 5
echo "fertig"

exit 0



was spricht dagegen, in einer 2. Shell docker logs zu verwenden?
Ich lerne gerne dazu :eek:
Wie kann man ein 2. Shellskript parallel öffnen?
 

Tommi2day

Benutzer
Mitglied seit
24. Aug 2011
Beiträge
1.164
Punkte für Reaktionen
63
Punkte
68
Wie kann man ein 2. Shellskript parallel öffnen?
Das erste Script mit "docker run .-it --name <containername> &" in den Hintergrund schicker oder evtl. gleich als Daemon (run -d) starten
Dann docker logs <containername> aufrufen
 

haydibe

Benutzer
Sehr erfahren
Mitglied seit
12. Apr 2016
Beiträge
1.468
Punkte für Reaktionen
356
Punkte
103
OCR-Skript:
Rich (BBCode):
#!/bin/bash

APPDIR=$(cd $(dirname $0);pwd)
cd ${APPDIR}
    
input="${APPDIR}/test_in.pdf"
output="${APPDIR}/test_out.pdf"
dockercontainer="jbarlow83/ocrmypdf"
ocropt="-srd -l deu"

# OCRen
/usr/local/bin/docker run --name OCR --rm -i "$dockercontainer" $ocropt - - < "$input" > "$output"

# Dateiattribute übertragen:
cp --attributes-only -p "$input" "$output"

sleep 5
echo "fertig"

exit 0
Warum das nicht geht ist mir jetzt klar. Es geht überhaupt nicht um das "reinpipen" von Werten in den Container und das weiterarbeiten mit dem Wert aus dem Container.
Das vollständige Beispiel im Zip ist genau das richtige Art. So kann man ohne viel Aufwand gleich das Problem sehen und eine Lösung damit erarbeiten ohne groß die Rahmenbedinungen recherchieren zu können (da hätte ich dann auch wieder keine Lust zu gehabt...). Ich schau mal was zu machen ist :)
 
Zuletzt bearbeitet:

haydibe

Benutzer
Sehr erfahren
Mitglied seit
12. Apr 2016
Beiträge
1.468
Punkte für Reaktionen
356
Punkte
103
So funktionert es:
Code:
cat test_in.pdf | docker run --name OCR --rm -i -log-driver=none -a stdin -a stdout -a stderr jbarlow83/ocrmypdf -srd -l deu - - | cat - > test_out.pdf

ich hab mal dein Skript zum rumspielen in eine Zeile gequetscht. Ich denke Du kannst das aber Problemlos übernehmen.

update:

Hier mal Dein script angepasst. In Zeile 1 habe ich mal das überflüssige entfernt und die beiden Variablen mal in das Umbenannt, was sie aus Docker-Sicht sind.

Code:
#!/bin/bash
APPDIR=$(dirname $0)
cd ${APPDIR}
    
input="${APPDIR}/test_in.pdf"
output="${APPDIR}/test_out.pdf"
image="jbarlow83/ocrmypdf"
cmd="-srd -l deu"

# OCRen
cat "${input}" | /usr/local/bin/docker  run --name OCR --rm -i -log-driver=none -a stdin -a stdout -a stderr ${image} ${cmd} - - | cat - > "${output}"

# Dateiattriputer übertragen:
cp --attributes-only -p "${input}" "${output}"

sleep 5
echo "fertig"

exit 0

Update2: Wenn Du # wieder in dem start-Skript rausnimmst, dann klappt es auch mit den Logs.

Enjoy!
 
Zuletzt bearbeitet:

geimist

Benutzer
Sehr erfahren
Maintainer
Mitglied seit
04. Jan 2012
Beiträge
5.371
Punkte für Reaktionen
1.188
Punkte
234
Es bleibt bei mir beim gleichen Verhalten. Die Datei wird korrekt ausgegeben, aber Docker schreibt sein log weiter auf dem Screen und nicht in die Log-Datei. Oder habe ich etwas falsch verstanden?
 

haydibe

Benutzer
Sehr erfahren
Mitglied seit
12. Apr 2016
Beiträge
1.468
Punkte für Reaktionen
356
Punkte
103
Gerne!

Dank dem Zip ging es auch schnell das Problem zu rekonstruieren und die Lösung darauf anzuwenden.
Nur mit den Snipets hätte ich das allerdings nie verstanden - ich kenne die im Container gekapselte Anwendung und wie sie zu benutzen ist nicht.
In der Regel muss man das aber auch nicht, da man das oft aus dem Kontext ableiten kann - wenn er denn vollständig vorliegt ;)
 

geimist

Benutzer
Sehr erfahren
Maintainer
Mitglied seit
04. Jan 2012
Beiträge
5.371
Punkte für Reaktionen
1.188
Punkte
234
Noch eine kurze Zusatzfrage:

Kann ich das Log auch in eine Variable schreiben - wie in nachstehender Form. So stünde die Ausgabe zur weiteren Auswertung zur Verfügung. Auf die Schnelle getestet zerstört es wieder die Dateiausgabe.
Rich (BBCode):
dockerlog=$(cat "$input" | /usr/local/bin/docker run --name OCR --rm -i -log-driver=none -a stdin -a stdout -a stderr $dockercontainer $ocropt - - | cat - > "$output")
echo "$dockerlog"
 

haydibe

Benutzer
Sehr erfahren
Mitglied seit
12. Apr 2016
Beiträge
1.468
Punkte für Reaktionen
356
Punkte
103
Das geht zwar nicht, aber Du könntest Du das verwenden von Funktionen das Start-Skript einsparen...

Code:
#!/bin/bash
APPDIR=$(dirname $0)
cd ${APPDIR}


input="${APPDIR}/test_in.pdf"
output="${APPDIR}/test_out.pdf"
image="jbarlow83/ocrmypdf"
cmd="-srd -l deu"

logfile="${APPDIR}/logfile.log"

convert(){
  # OCRen
  cat "${input}" | /usr/local/bin/docker  run --name OCR --rm -i -log-driver=none -a stdin -a stdout -a stderr ${image} ${cmd} - - | cat - > "${output}"

  # Dateiattriputer übertragen: 
  cp --attributes-only -p "$input" "$output"
}
convert >> $logfile 2>&1
echo "fertig" >> $logfile
 

geimist

Benutzer
Sehr erfahren
Maintainer
Mitglied seit
04. Jan 2012
Beiträge
5.371
Punkte für Reaktionen
1.188
Punkte
234
So ähnlich hatte ich es jetzt auch schon gefunden. Die einzelne Zeile für Docker habe ich in separates Skript ausgelagert, welches ich wiederum mit Logausgabe aufrufen kann
Rich (BBCode):
dockerlog=$( ./ocrmypdf_worker.sh "$dockercontainer" "$ocropt" "$input" "$output" 2>&1)

Und ocrmypdf_worker.sh sieht lediglich so aus:
Rich (BBCode):
#!/bin/bash
cat "$3" | /usr/local/bin/docker run --name synOCR --rm -i -log-driver=none -a stdin -a stdout -a stderr $1 $2 - - | cat - > "$4"
Das Startskript brauche ich noch, weil es ggf. noch mehr zum loggen gibt.
 

haydibe

Benutzer
Sehr erfahren
Mitglied seit
12. Apr 2016
Beiträge
1.468
Punkte für Reaktionen
356
Punkte
103
ah, okay. Ich hatte Dich missverstanden. Ich dachte Du willst das direkt in dem einen Skript weiterverwenden.
Schön wenn jetzt alles tuti ist :)

Btw. es wäre mit einem oder zwei Volume (für Input/Output je ein Volume) mounts auch einfacher gegangen und man hätte sich das Ganze geraffel mit dem den Pipes sparen können und dann die Ausgabe des Docker Befehls wiederum in einer Variable "fangen" können.

Durch die Verwendung der Pipes in der Subshell funktioniert das eben nur mit tricksen.
 
Status
Für weitere Antworten geschlossen.
 

Kaffeautomat

Wenn du das Forum hilfreich findest oder uns unterstützen möchtest, dann gib uns doch einfach einen Kaffee aus.

Als Dankeschön schalten wir deinen Account werbefrei.

:coffee:

Hier gehts zum Kaffeeautomat