Dieter_Ubuntu
Anmeldungsdatum: 4. Juli 2007
Beiträge: 422
|
Meine Bash-Datei sieht so aus:
1
2
3
4
5
6
7
8
9
10
11
12 | #!/bin/bash
# $1 = Password
# $2 = Programm
# $3 = if=...
# $4 = of=....
# $5 = bs=512
# $6 = count=1
echo "Programm" $2
echo "if=..." $3
echo "of=... " $4
echo $1 | sudo -S -b $2 $3 'of=/mnt/test test1/name.pbr' $5 $6
#echo $1 | sudo -S -b $2 $3 $4 $5 $6
|
Die Bash rufe ich so auf: | dateiname.sh password dd if=/dev/sda8 "'of=/mnt/test test1/name.pbr'"
|
Der PBR von /dev/sda8 wird geschrieben.
Die übergebene Variable $4, die ich mit echo ansehe ist korrekt 'of=/mnt/test test1/name.pbr'. Wenn ich nun in der Bash den echo befehl in Zeile 12 aktiviere und die Zeile 11 deaktiviere kommt von dd die Fehlermeldung dd: nicht erkannter Operand »'of=/mnt/test“. Die Befehlsübergabe wird also gesplittet, obwohl die Variable beim Anschauen so aussieht: 'of=/mnt/test test1/name.pbr'. Weiß jemand, wieso der vorletzte Befehl klappt und der letzte nicht? Mit dem \ für die Leerstellen Erkennung klappt es auch nicht. Ich verwende die obige bash_datei in einem größeren Programm (qt-fsarchiver) und funktioniert ohne die Leerstelle einwandfrei. dd wird verwendet für den MBR, PBR, Festplatten kopieren und Abbilder schreiben
Wäre schön, wenn auch die Leerstellen korrekt verarbeitet werden können. Grüße aus Südbaden
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
Du solltest Variablen, die Leerzeichen enthalten können, immer Quoten, wenn du auf ihren Wert zugreifst - also in deinem Fall:
| #!/bin/bash
# $1 = Password
# $2 = Programm
# $3 = if=...
# $4 = of=....
# $5 = bs=512
# $6 = count=1
echo "Programm" "$2"
echo "if=..." "$3"
echo "of=... " "$4"
echo "$1" | sudo -S -b "$2" "$3" "$4" "$5" "$6"
|
Dann kannst du statt "'of=/mnt/test test1/name.pbr'" einfach 'of=/mnt/test test1/name.pbr' oder "of=/mnt/test test1/name.pbr" als Argument verwenden.
|
sebix
Moderator, Webteam
Anmeldungsdatum: 14. April 2009
Beiträge: 5334
|
Du darfst nur den Parameter quoten, damit er vom Programm wie von dir erwartet interpretiert wird: | dateiname.sh password dd if=/dev/sda8 of="/mnt/test test1/name.pbr"
|
Oder escapen: | dateiname.sh password dd if=/dev/sda8 of=/mnt/test\ test1/name.pbr
|
|
Dieter_Ubuntu
(Themenstarter)
Anmeldungsdatum: 4. Juli 2007
Beiträge: 422
|
Danke für die Antworten. Das Problem hat natürlich nicht mit dd zu tun. Ich habe die bash so geändert, dass nicht mehr dd sondern eine weitere bash aufgerufen wird, die mir lediglich die übergebenen Paramater anzeigen. Ich probiere schon einige Tage und machte unter anderem dieses: $4 habe ich (teilweise unsinnig) so definiert: 'of=/mnt/test test1/name.pbr', "of=/mnt/test test1/name.pbr", "'of=/mnt/test test1/name.pbr'", ""'of=/mnt/test test1/name.pbr'"", '"of=/mnt/test test1/name.pbr"' . Nichts funktioniert.
Bei dem Aufrufbefehl ist somit egal, was ich bei off= reinschreibe. Das verrückte ist dies, wenn ich in der Bash die Zeile 11 ausführe funktioniert es, mit der Zeile 12 aber nicht. Wenn ich mit echo die Zeilen 11 und 12 anschaue sind sie identisch!! Trotzdem klappt es nicht. Merkwürdig. Das mit dem Escapen habe ich auch in zig-Varianten versucht. Auch da kein Erfolg. Grüße aus Südbaden
|
sebix
Moderator, Webteam
Anmeldungsdatum: 14. April 2009
Beiträge: 5334
|
Dieter_Ubuntu schrieb: Ich habe die bash so geändert,
Du meinst wahrscheinlich das Skipt ☺ dass nicht mehr dd sondern eine weitere bash aufgerufen wird, die mir lediglich die übergebenen Paramater anzeigen.
Was ist denn dein eigentliches Ziel?
|
Dieter_Ubuntu
(Themenstarter)
Anmeldungsdatum: 4. Juli 2007
Beiträge: 422
|
Das Script habe ich so geändert, dass nicht nicht mehr dd sondern eine weitere Script aufgerufen wird, das die übergebenen Variablen per echo anzeigt. Das ist nur für die Fehlersuche interessant.
Das eigentliche Problem ist dies, dass das Script mit dem String /mnt/test test1.... korrekt arbeitet (Zeile11) mit der Variablen $4 (Inhalt: /mnt/test test1... identisch mit dem String) Zeile 12 nicht arbeitet. Der Hintergrund: qt-fsarchiver, ein Programm mit grafischer Oberfläche, konnte ursprünglich nur mit root-Rechten gestartet werden. Um die Probleme mit gksudo, aber auch die von Wayland umgehen zu können, habe ich das Programm in zwei Teile aufgesplitted. Der Oberflächenteil wird nun ohne root-Rechte gestarted, Unterprogramme die root-Rechte erfordern werden in einem Terminal ausgeführt. Um beispielweise den MBR zu sichern wird dd benötigt. Das Oberflächenprogramm übergibt an das Script am Anfang dieses Forums die Aufforderung dd mit Passwort und weitere Angaben zu starten. Das funktioniert auch tadellos. In einem weiteren Forum wurde mir mitgeteilt, dass es Probleme beim Sichern von Partition gibt. Die Überprüfung führte auf die Leerstelle in einem Verzeichnis. Beim Sichern und Wiederherstellen konnte ich das Problem lösen. Bei dd suche ich die Lösung. Grüß aus Südbaden
|
sebix
Moderator, Webteam
Anmeldungsdatum: 14. April 2009
Beiträge: 5334
|
Dieter_Ubuntu schrieb: Das Script habe ich so geändert, dass nicht nicht mehr dd sondern eine weitere Script aufgerufen wird, das die übergebenen Variablen per echo anzeigt. Das ist nur für die Fehlersuche interessant.
Dann suchst du vielleicht set -x , das zeigt dir alle Befehle an, die ausgefuehrt werden.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12822
|
Auf meiner Nutzerseite steht ein Skript, mit dem man solche Parameterübergaben austesten kann (args.sh).
|
kB
Supporter, Wikiteam
Anmeldungsdatum: 4. Oktober 2007
Beiträge: 8616
Wohnort: Münster
|
Dein originäres Problem besteht in der Verwendung von Leerzeichen in Dateinamen und dem Wunsch, diese als Parameter an aufgerufene Programme weiterzugeben. Bei jedem Programmaufruf wird die Befehlszeile an Whitespace-Zeichen in einzelne Argumente zerlegt. Man muss also dafür sorgen, dass Leerzeichen im letztlich aufgerufenen Programm noch maskiert ankommen. In Deinem Fall
steht sudo als letztes Programm in einer Pipe und wird deshalb von bash in einer Subshell aufgerufen, wird das Programm sudo mit einer Befehlszeile gestartet, wird ein weiteres Programm von sudo gestartet.
Ein Leerzeichen muss daher i.d.F. 3-fach maskiert werden, wenn es beim eigentlichen Programm noch als Information ankommen soll und nicht als Trennzeichen für die Argumente verwendet wird. Du hast also folgende Alternative:
Entweder: Verwende keine Leerzeichen (allgemein: kein Whitespace) in Dateinamen, Oder: Lebe mit dem Schwindel in Deinem Kopf.
Auf jeden Fall solltest Du die Komplexität der Aufrufkette reduzieren.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
kB schrieb: Ein Leerzeichen muss daher i.d.F. 3-fach maskiert werden, wenn es beim eigentlichen Programm noch als Information ankommen soll und nicht als Trennzeichen für die Argumente verwendet wird.
Eigentlich muss man nur durchgehend korrekt quoten... $ cat layer1.sh
#!/bin/bash
sudo ./layer2.sh "$@"
$ cat layer2.sh
#!/bin/bash
printf "%s\n" "$@"
$ ./layer1.sh foo bar 'bar food' "\"ham spam\""
foo
bar
bar food
"ham spam"
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12822
|
kB schrieb: Dein originäres Problem besteht in der Verwendung von Leerzeichen in Dateinamen und dem Wunsch, diese als Parameter an aufgerufene Programme weiterzugeben. Bei jedem Programmaufruf wird die Befehlszeile an Whitespace-Zeichen in einzelne Argumente zerlegt. Man muss also dafür sorgen, dass Leerzeichen im letztlich aufgerufenen Programm noch maskiert ankommen. In Deinem Fall
steht sudo als letztes Programm in einer Pipe und wird deshalb von bash in einer Subshell aufgerufen, wird das Programm sudo mit einer Befehlszeile gestartet, wird ein weiteres Programm von sudo gestartet.
Ein Leerzeichen muss daher i.d.F. 3-fach maskiert werden, wenn es beim eigentlichen Programm noch als Information ankommen soll und nicht als Trennzeichen für die Argumente verwendet wird.
Kannst Du mal an einem Beispiel erläutern, wie Du auf "3-fach" kommst? Ich denke nämlich nicht, dass das als allgemeine Aussage stimmt. Im Regelfall wird es genügen, Variablen zu quoten. Erst, wenn solche Dinge ins Spiel kommen, dass man eine Shell mit einem Kommando via "-c" starten will, muss man anfangen darüber nachzudenken, wie man so maskiert, dass am Ende das Richtige dabei herauskommt.
Du hast also folgende Alternative:
Entweder: Verwende keine Leerzeichen (allgemein: kein Whitespace) in Dateinamen, Oder: Lebe mit dem Schwindel in Deinem Kopf.
😀
Auf jeden Fall solltest Du die Komplexität der Aufrufkette reduzieren.
+1
|
kB
Supporter, Wikiteam
Anmeldungsdatum: 4. Oktober 2007
Beiträge: 8616
Wohnort: Münster
|
seahawk1986 schrieb: kB schrieb: Ein Leerzeichen muss daher i.d.F. 3-fach maskiert werden, wenn es beim eigentlichen Programm noch als Information ankommen soll und nicht als Trennzeichen für die Argumente verwendet wird.
Eigentlich muss man nur durchgehend korrekt quoten...
Du sagst es: Quoten ist die angemessene Technik zum Maskieren bzw. Schützen von Leerzeichen. In Deinem Beispiel machst Du es für das Leerzeichen in »foo bar« 3 mal, danach kommt es im Programm noch als Datum an, ist aber nicht mehr geschützt:
$ cat layer1.sh
#!/bin/bash
sudo ./layer2.sh "$@"
$ cat layer2.sh
#!/bin/bash
printf "%s\n" "$@"
$ ./layer1.sh foo bar 'bar food' "\"ham spam\""
foo
bar
bar food
"ham spam"
Das Leerzeichen in »ham spam« schützt Du sogar 4 mal und somit kommt es noch als einfach geschütztes Datum im Programm an.
|
kB
Supporter, Wikiteam
Anmeldungsdatum: 4. Oktober 2007
Beiträge: 8616
Wohnort: Münster
|
rklm schrieb: kB schrieb: […]
Ein Leerzeichen muss daher i.d.F. 3-fach maskiert werden, wenn es beim eigentlichen Programm noch als Information ankommen soll und nicht als Trennzeichen für die Argumente verwendet wird.
Kannst Du mal an einem Beispiel erläutern, wie Du auf "3-fach" kommst? Ich denke nämlich nicht, dass das als allgemeine Aussage stimmt.
Du hast recht: Es stimmt nicht allgemein, sondern – wie ich schrieb – in diesem konkreten Fall (i.d.F) des OT. Je nach Situation kann es mehr oder weniger kompliziert sein. seahawk1988 hat ein konkretes Beispiel, siehe auch meinen Kommentar dazu.
|
Dieter_Ubuntu
(Themenstarter)
Anmeldungsdatum: 4. Juli 2007
Beiträge: 422
|
Ich glaube nicht, dass mein Problem mit dem maskieren oder quoten was zu tun hat.
Nochmals total vereinfacht meine Batch-Datei: | #!/bin/bash
$4="'of=/mnt/test test1/name.pbr'"
echo $1 | sudo -S -b $2 $3 'of=/mnt/test test1/name.pbr' $5 $6
#echo $1 | sudo -S -b $2 $3 $4 $5 $6
|
Das entscheidende ist: Bei diesem Script, Zeile 3 ist aktiv, funktioniert die Übergabe an dd (beispielweise). Das of= Argument wird nicht gesplittet. Beim nächsten Versuch hat $4 (mittels echo erkennbar) diesen Inhalt: 'of=/mnt/test test1/name.pbr'. Die Variable $4 ist somit identisch mit dem String in Zeile 3. Ich deaktiviere die Zeile 3 und aktiviere die Zeile 4. Jetzt wird bei der Ausführung das of= Argument gesplittet. Fazit: Das Script arbeitet korrekt mit der direkten Eingabe des of= Argumentes. Wird die Variable $4 benutzt, funktioniert es nicht. Ich habe mit verschiedenen Maskierungen bestimmt hundert Versuche gemacht, leider ohne Erfolg. Was ist der Unterschied zwischen der direkten Eingabe und der Benutzung der Variablen. Das ist, denke ich, der Knackpunkt. Grüße aus Südbaden
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12822
|
Dieter_Ubuntu schrieb: Ich glaube nicht, dass mein Problem mit dem maskieren oder quoten was zu tun hat.
Das mag so sein, aber damit liegst Du falsch.
Nochmals total vereinfacht meine Batch-Datei: [...]
Beim nächsten Versuch hat $4 (mittels echo erkennbar) diesen Inhalt: 'of=/mnt/test test1/name.pbr'. Die Variable $4 ist somit identisch mit dem String in Zeile 3. Ich deaktiviere die Zeile 3 und aktiviere die Zeile 4. Jetzt wird bei der Ausführung das of= Argument gesplittet.
Weil, wie Dir bereits mitgeteilt wurde, die Variable dort gequotet werden muss. Wenn Du das nicht machst, geht es nicht.
Fazit: Das Script arbeitet korrekt mit der direkten Eingabe des of= Argumentes. Wird die Variable $4 benutzt, funktioniert es nicht. Ich habe mit verschiedenen Maskierungen bestimmt hundert Versuche gemacht, leider ohne Erfolg.
In der ersten Antwort von seahawk1986 hast Du doch bereits die richtige Lösung bekommen. Wenn Du nicht ausprobierst, was Dir hier geraten wird, ist es etwas schwierig.
Was ist der Unterschied zwischen der direkten Eingabe und der Benutzung der Variablen. Das ist, denke ich, der Knackpunkt.
Das fehlende Quoting (s.o.).
|