[linux-l] Logik von "Syntax-Fehler" in Bash

Lutz Willek lutz.willek at belug.de
Sa Dez 28 22:58:08 CET 2013


Moinsen!

Am 27.12.2013 18:23, schrieb Hauke Laging:
> Am Fr 27.12.2013, 17:11:52 schrieb Lutz Willek:
>
>> Ein "sudo for i in 1 2 3 4 5 ; do befehl ;done" funktioniert deshalb
>> nicht, weil
>>
>> sudo befehl1; befehl2; befehl3
>>
>> nicht das ist was Du willst, aber Du es so geschrieben hast
>
> Diese Darstellung finde ich nun nicht besonders gelungen. Denn es ist ja
> gerade *nicht* ein Konstrukt der Art
>
> sudo befehl1; befehl2; befehl3
>
Doch, genau das ist es aus Sicht der shell. Du hast aber Recht wenn Du 
schreibst:

> Wäre es so, würde die Shell ja nicht meckern, sondern allen falls sudo.
> befehl2 ist eben kein gültiges Shellkommando. Und befehl1 ist nichts, was sudo
> starten könnte. Ein execve() auf for ist halt nicht drin. Treffender wäre:
>
> sudo befehl1; shellschrott

Daher einigen wir uns auf:

sudo <optionen_für sudo> ; shellschrott ; shellschrott

Jetzt ok so? (Es waren drei Semikolon in der Originalzeile, und aus 
Sicht der Shell war einfach alles bockmist)

> Und wenn man das nicht in eine Zeile schreibt, sondern erst mal nur
> sudo befehl1
> losballert, kriegt man von sudo auch gleich ein paar Takte gesagt.

jupp. Man könnte obiges auch so umschreiben:

sudo shellschrott ; shellschrott ; shellschrott

>> so nicht funktionierte: ...is  a sequence of optional variable
>> assignments followed by blank-separated words and redirections, and
>> terminated by a control operator. Mach Dir nix draus, den Wink hat
>> scheinbar nicht mal Hauke verstanden ;) Schade eigentlich.
>
> Mir ist zwar nicht klar, wer oder was mir gewunken haben soll, aber dafür,
> dass Newline ein control operator ist. Und damit, dass ich etwas *scheinbar*
> nicht verstanden haben soll, komme ich bestens zurecht... 8-)

Na eigentlich einfach: Wir haben hier erst mal eine valide Schleife:

for i in `seq 1 5` ; do befehl ; done

Mit einem sudo davor ist das ganze kaputt, weil sudo nun mal nach dem 
ersten Befehl beendet ist (Der wie richtig bemerkt dann auch Schrott 
ist). Wie auch immer, sudo "sieht" für sich folgendes:

sudo for i in `seq 1 5` ;

Also ein (für sich genommen nicht valides) Shellfragment. Dieses 
Shellfragment kommt aber nie zur Ausführung, da die bash vor Ausführung 
der kompletten Zeile die Syntax selbiger prüft, und als nächstes das 
hier findet:

do befehl;

Was zur Fehlermeldung und somit zum Abbruch führt. Ist ja auch klar, 
weil die dazu gehörende Zeile "for i in `seq 1 5`" ist ja schon als 
Argument an sudo übergeben worden und damit nicht mehr zum Rest 
zugehörig ist.

sudo "zerrupft" so quasi die for in do done Schleife. Das ist aber nicht 
die Schuld von sudo: Das arbeitet in dem Zusammenhang hier noch gar 
nicht. Dies wird deutlich, wenn man als User das Kommando sudo durch ein 
echo ersetzt, hier mal getestet:

> ~ $ echo for i in `seq 1 5` ; do befehl ; done
> -bash: syntax error near unexpected token `do'

Die Fehlermeldung bleibt genau die gleiche, weil das zugrunde liegende 
Problem gleich ist. Anders: sudo ist hier aus der Diskussion raus!

Das Problem ist einzig die fehlende Maskierung. Richtig erkannt: Die 
Lösung ist, dem Befehl sudo die komplette Zeile "for i in `seq 1 5` ; do 
befehl ; done" im ganzen als Argument zu übergeben, und nicht nur den 
Teil "for i in `seq 1 5`", wie es der Originalposter getan hat.

Wie das erreicht wird ist im Endeffekt egal, valide Lösung ist 
beispielsweise ein kleines shellskript, das die nötigen Befehlssequenzen 
enthält und dann über sudo aufgerufen wird, oder halt der direkte Weg 
ohne hilfsskript, also die Lösung von Hauke: sudo bash -c 
"befehlssequenz...")

Eine andere Lösung ist die Zeile so umzuschreiben, dass sudo innerhalb 
der schleife aufgerufen wird. Wie sinnig die zweite Lösung ist hängt 
natürlich davon ab was man auf dem System erreichen möchte, muss so 
nicht immer die beste Lösung sein. Das ist dann aber eine andere 
Geschichte und für den im OP angefragten Einsatzzweck ist das so auch 
machbar und ok.

> CU
>
> Hauke
>

lg Lutz




Mehr Informationen über die Mailingliste linux-l