Hallo,
ich möchte ein Sript schreiben, in dem eine CF-Karte mit einem vorhandenen Image beschrieben wird. Leider funktioniert das Script nicht immer, von zehn Durchläufen funktionieren drei. Meist gibt es schon nach der zweiten Zeile des folgenden Ausschnitts einen Fehler. Später sollen übrigens die ganzen echo-Zeilen raus und die K_FORTSCHRITT-Variable mit kdialog in einer Progressbar ausgegeben werden.
`nice -n 19 sudo dd if=$FILENAME of=/dev/hdc > /home/bla/dd.txt 2>&1 &` PID=$(echo `ps ax | grep '[o]f /dev/hdc' | awk '{print $1}'`) echo $PID sudo kill -USR1 $PID FORTSCHRITT=$(echo `more /home/bla/dd.txt | grep 'transferred' | awk '{print $1}'`) echo $FORTSCHRITT K_FORTSCHRITT=$(echo "$FORTSCHRITT/1024" | bc) echo $K_FORTSCHRITT while [ "$K_FORTSCHRITT" -lt "$FILE_GROESSE" ] ; do rm -f /home/bla/dd.txt touch /home/bla/dd.txt sudo kill -USR1 $PID FORTSCHRITT=$(echo `more /home/bla/dd.txt | grep 'transferred' | awk '{print $1}'`) echo $FORTSCHRITT K_FORTSCHRITT=$(echo `"$FORTSCHRITT/1024" | bc`) echo $K_FORTSCHRITT done
In Zeile 3 soll die vorher erkannte PID vom Aufruf in Zeile 1 angezeigt werden, statt dessen bekomme ich schon eine Fehlermeldung bezüglich der vierten Zeile, als ob der kill-Befehl nicht richtig geschrieben wurde:
Usage: kill pid ... Send SIGTERM to every process listed. kill signal pid ... Send a signal to every process listed. kill -s signal pid ... Send a signal to every process listed. kill -l List all signal names. kill -L List all signal names in a nice table. kill -l signal Convert between signal numbers and names.
Manchmal wird aber eben auch die PID ausgegeben, und das Script läuft normal weiter. Woran kann das liegen?
Vielen Dank schonmal, Jens
PS: Ihr habt mir ja schon zu meinem letzten Posting geschrieben, daß man die PID auch einfacher bekommt, aber wohl nur wenn kein 'nice' und 'sudo' vor der eigentlichen Anweisung stehen (Zeile 1). Jedenfalls habe ich es mit $! nicht hinbekommen.
Jens Nixdorf schrieb:
Hallo,
ich möchte ein Sript schreiben, in dem eine CF-Karte mit einem vorhandenen Image beschrieben wird. Leider funktioniert das Script nicht immer, von zehn Durchläufen funktionieren drei. Meist gibt es schon nach der zweiten Zeile des folgenden Ausschnitts einen Fehler. Später sollen übrigens die ganzen echo-Zeilen raus und die K_FORTSCHRITT-Variable mit kdialog in einer Progressbar ausgegeben werden.
`nice -n 19 sudo dd if=$FILENAME of=/dev/hdc > /home/bla/dd.txt 2>&1 &`
Wozu die backticks?
PID=$(echo `ps ax | grep '[o]f /dev/hdc' | awk '{print $1}'`)
*Grusel* PID=$! Siehe Unten.
echo $PID sudo kill -USR1 $PID FORTSCHRITT=$(echo `more /home/bla/dd.txt | grep 'transferred' | awk '{print $1}'`)
nochmal *Grusel* ;)
Warum echo? Da grep sowieso eine Ausgabe auf stdout erzeugt, ist das echo überflüssig. warum more? more ist ein Pager, also zum seitenweisen Lesen einer Datei gedacht. Beliebt ist hier auch cat, was aber ebenso überflüssig ist, da grep von stdin liest. Also wäre:
FORTSCHRITT=$(grep 'transferred' /home/bla/dd.txt | \ awk '{print $1}'`)
schon besser, aber:
FORTSCHRITT=$( awk '/transferred/ {print $1}' /home/bla/dd.txt )
sollte es auch tun.
echo $FORTSCHRITT
Quotes magst Du wohl nicht ;) Auch wenns nur zu Testzwecken ist: echo "$FORTSCHRITT"
K_FORTSCHRITT=$(echo "$FORTSCHRITT/1024" | bc) echo $K_FORTSCHRITT while [ "$K_FORTSCHRITT" -lt "$FILE_GROESSE" ] ; do
1) Hier sind die Quotes nicht nötig, eine Zahl hat keine Leerzeichen oder Sonderzeichen. Eine Prüfung ob das tatsächlich Zahlen sind könntest Du aber zur Sicherheit noch einbauen. 2) Wo kommt $FILE_GROESSE her?
rm -f /home/bla/dd.txt touch /home/bla/dd.txt sudo kill -USR1 $PID FORTSCHRITT=$(echo `more /home/bla/dd.txt | grep 'transferred' |
awk '{print $1}'`)
1) /home/bla/dd.txt hast Du doch eben gelöscht, also ist die doch hier leer? 2) siehe oben, und wenn Du eine Befehlsfolge mehrmals brauchst, mach ne Function draus.
--------8<-------- progress() { awk '/transferred/ {print $1}' /home/bla/dd.txt } FORTSCHRITT=$(progress) --------8<--------
echo $FORTSCHRITT K_FORTSCHRITT=$(echo `"$FORTSCHRITT/1024" | bc`) echo $K_FORTSCHRITT
done
In Zeile 3 soll die vorher erkannte PID vom Aufruf in Zeile 1 angezeigt werden, statt dessen bekomme ich schon eine Fehlermeldung bezüglich der vierten Zeile, als ob der kill-Befehl nicht richtig geschrieben wurde:
Ich vermute, dass der sudo-Aufruf fehlerhaft ist und deswegen $PID nichts oder eine Fehlermeldung enthält.
Usage: kill pid ... Send SIGTERM to every process listed. kill signal pid ... Send a signal to every process listed. kill -s signal pid ... Send a signal to every process listed. kill -l List all signal names. kill -L List all signal names in a nice table. kill -l signal Convert between signal numbers and names.
Manchmal wird aber eben auch die PID ausgegeben, und das Script läuft normal weiter. Woran kann das liegen?
Vielen Dank schonmal, Jens
PS: Ihr habt mir ja schon zu meinem letzten Posting geschrieben, daß man die PID auch einfacher bekommt, aber wohl nur wenn kein 'nice' und 'sudo' vor der eigentlichen Anweisung stehen (Zeile 1). Jedenfalls habe ich es mit $! nicht hinbekommen.
Trotzdem:
PID=$(echo `ps ax | grep '[o]f /dev/hdc' | awk '{print $1}'`)
*Grusel*
PID=$(ps ax | awk '/of /dev/hdc/ {print $1}')
Und wenn Du den Aufruf von dd in ein Script schreibst? --------8<-------- #!/bin/bash # script mydd # Syntax: mydd FILENAME dd if=$1 of=/dev/hdc > /home/bla/dd.txt 2>&1 & echo $! --------8<--------
Dann PID=$( nice -n 19 sudo mydd $FILENAME )
mydd muss jetzt noch in /etc/sudoers eingetragen werden. Da die generelle Freigabe von dd via sudo sowieso nicht so toll ist, wäre das IMHO die bessere Lösung.
Gruss Bernd
Bernd Obermayr schrieb: [...]
rm -f /home/bla/dd.txt touch /home/bla/dd.txt sudo kill -USR1 $PID FORTSCHRITT=$(echo `more /home/bla/dd.txt | grep 'transferred' |
awk '{print $1}'`)
- /home/bla/dd.txt hast Du doch eben gelöscht, also ist die doch
hier leer?
Äh ja... *rot werd* schon kapiert ;)
Am Dienstag, 28. Dezember 2004 15:13 schrieb Bernd Obermayr:
`nice -n 19 sudo dd if=$FILENAME of=/dev/hdc > /home/bla/dd.txt 2>&1 &`
Wozu die backticks?
Was sind backticks? Wenn Du nice meinst, das ist deshalb drin weil dd auf dem Zielrechner alles blockiert, da kann man kaum noch die Maus bewegen (ist ein Via Epia 533 MHz).
PID=$(echo `ps ax | grep '[o]f /dev/hdc' | awk '{print $1}'`)
*Grusel*
Ja ja, macht Euch ruhig lustig über einen Scripting-Noob...;)
FORTSCHRITT=$(echo `more /home/bla/dd.txt | grep 'transferred' | awk '{print $1}'`)
nochmal *Grusel* ;)
Warum echo? Da grep sowieso eine Ausgabe auf stdout erzeugt, ist das echo überflüssig.
Weil ich noch nicht dahinter gekommen bin, wann ich was brauche. Und da nehme ich immer das, was zuerst funktioniert, bis mir jemand sagt wie es besser geht ;)
warum more? more ist ein Pager, also zum seitenweisen Lesen einer Datei gedacht.
Darauf zu kommen, daß grep direkt aus Dateien liest, ist mir wohl auch zu einfach gewesen.
- Wo kommt $FILE_GROESSE her?
Wird vorher im Script aus dem Image gelesen.
rm -f /home/bla/dd.txt touch /home/bla/dd.txt sudo kill -USR1 $PID FORTSCHRITT=$(echo `more /home/bla/dd.txt | grep
'transferred' | awk '{print $1}'`)
- /home/bla/dd.txt hast Du doch eben gelöscht, also ist die doch
hier leer?
Nein, mit dem kill-Befehl wird ja wieder was reingeschrieben. Ja, das ist wieder so eine Noob-Krücke... ;)
- siehe oben, und wenn Du eine Befehlsfolge mehrmals brauchst, mach
ne Function draus.
Das ist 'ne Idee.
Ich vermute, dass der sudo-Aufruf fehlerhaft ist und deswegen $PID nichts oder eine Fehlermeldung enthält.
Aber warum 'nur' in zwei Dritteln aller Durchläufe?
Und wenn Du den Aufruf von dd in ein Script schreibst? --------8<-------- #!/bin/bash # script mydd # Syntax: mydd FILENAME dd if=$1 of=/dev/hdc > /home/bla/dd.txt 2>&1 & echo $! --------8<--------
Dann PID=$( nice -n 19 sudo mydd $FILENAME )
Was ändert der Aufruf durch ein zweites Script statt dem Direkt-Aufruf? (Ernsthafte Frage)
mfG, Jens
Jens Nixdorf schrieb:
Am Dienstag, 28. Dezember 2004 15:13 schrieb Bernd Obermayr:
`nice -n 19 sudo dd if=$FILENAME of=/dev/hdc > /home/bla/dd.txt 2>&1 &`
Wozu die backticks?
Was sind backticks? Wenn Du nice meinst, das ist deshalb drin weil dd auf dem Zielrechner alles blockiert, da kann man kaum noch die Maus bewegen (ist ein Via Epia 533 MHz).
Die da: ``` Die brauchst Du nur, wenn die Ausgabe eines Befehls in einer Variablen gespeichert werden soll oder als Argument eines anderen Befehls dient. Ist äquivalent zu $()
PID=$(echo `ps ax | grep '[o]f /dev/hdc' | awk '{print $1}'`)
*Grusel*
Ja ja, macht Euch ruhig lustig über einen Scripting-Noob...;)
*g*
FORTSCHRITT=$(echo `more /home/bla/dd.txt | grep 'transferred' | awk '{print $1}'`)
nochmal *Grusel* ;)
Warum echo? Da grep sowieso eine Ausgabe auf stdout erzeugt, ist das echo überflüssig.
Weil ich noch nicht dahinter gekommen bin, wann ich was brauche. Und da nehme ich immer das, was zuerst funktioniert, bis mir jemand sagt wie es besser geht ;)
;)
warum more? more ist ein Pager, also zum seitenweisen Lesen einer Datei gedacht.
Darauf zu kommen, daß grep direkt aus Dateien liest, ist mir wohl auch zu einfach gewesen.
- Wo kommt $FILE_GROESSE her?
Wird vorher im Script aus dem Image gelesen.
Ok
rm -f /home/bla/dd.txt touch /home/bla/dd.txt sudo kill -USR1 $PID FORTSCHRITT=$(echo `more /home/bla/dd.txt | grep
'transferred' | awk '{print $1}'`)
- /home/bla/dd.txt hast Du doch eben gelöscht, also ist die doch
hier leer?
Nein, mit dem kill-Befehl wird ja wieder was reingeschrieben. Ja, das ist wieder so eine Noob-Krücke... ;)
Jaaaaa ist ja schon gut ;) siehe andere Mail
- siehe oben, und wenn Du eine Befehlsfolge mehrmals brauchst, mach
ne Function draus.
Das ist 'ne Idee.
Ich vermute, dass der sudo-Aufruf fehlerhaft ist und deswegen $PID nichts oder eine Fehlermeldung enthält.
Aber warum 'nur' in zwei Dritteln aller Durchläufe?
Das steht dann u.U in /home/bla/dd.txt Bau das Script mal wie vorgeschlagen um, dann sehen wir weiter.
Und wenn Du den Aufruf von dd in ein Script schreibst? --------8<-------- #!/bin/bash # script mydd # Syntax: mydd FILENAME dd if=$1 of=/dev/hdc > /home/bla/dd.txt 2>&1 & echo $! --------8<--------
Dann PID=$( nice -n 19 sudo mydd $FILENAME )
Was ändert der Aufruf durch ein zweites Script statt dem Direkt-Aufruf? (Ernsthafte Frage)
1) Nun, für mich sieht das so aus, als ob Du in /etc/sudoers dd generell freigegeben hast. Das ist ein Risiko, dd ist ein gefährlicher Befehl. 2) Es ist zwar unwahrscheinlich, dass das passiert, aber die Abfrage mittels ps liefert _alle_ Prozessezeilen die 'of /dev/hdc' enthalten. 3) Bei meinem Vorschlag erhältst Du genau die PID von dem aktuellen dd.
Wie Du richtig schreibst, liefert $! die PID von sudo, beim Aufruf mittels eines eigenen Scripts kann ich die PID explicit rausfischen. Es ist nötig sudo von dd zu trennen. Ich weiss keine andere Möglichkeit das zu erreichen.
Am Dienstag, 28. Dezember 2004 17:51 schrieb Bernd Obermayr:
Bau das Script mal wie vorgeschlagen um, dann sehen wir weiter.
Und wenn Du den Aufruf von dd in ein Script schreibst? --------8<-------- #!/bin/bash # script mydd # Syntax: mydd FILENAME dd if=$1 of=/dev/hdc > /home/bla/dd.txt 2>&1 & echo $! --------8<--------
Dann PID=$( nice -n 19 sudo mydd $FILENAME )
Ja, habe ich so gemacht, und es funktioniert. Zumindest, wenn ich zwischen den danach folgenden kill-Aufrufen wenigstens ein sleep 1 setze, sonst verschluckt sich das Script trotzdem. Aber so habe ich auf jeden Fall bisher bei bestimmt 50 Testläufen, auch mit hoher sonstiger Last des Rechners, keinen Fehler mehr gehabt. Danke.
mfG, Jens
Jens Nixdorf schrieb:
Ja, habe ich so gemacht, und es funktioniert. Zumindest, wenn ich
zwischen
den danach folgenden kill-Aufrufen wenigstens ein sleep 1 setze, sonst verschluckt sich das Script trotzdem. Aber so habe ich auf jeden Fall bisher bei bestimmt 50 Testläufen, auch mit hoher sonstiger Last des Rechners, keinen Fehler mehr gehabt. Danke.
mfG, Jens
Das ist fein :)