2009-08-26 3 views
0

Ich bin Batch einige Bilder mit einem quick and dirty Bash-Skript konvertieren:Warum ändert sich eine hart codierte Zeichenfolge var, wenn das Bash-Skript als root ausgeführt wird? mit ufraw

IFS=$'\n' 
PICS="/media/disk/kevin/Images/"; 
for pic in $(find $PICS -name "*CR2"); 
do 
    ufraw-batch $pic --out-type jpg --size=2048 --overwrite --out-path=$PICS; 
    rm -f $pic 
done; 
IFS=" "; 

Es läuft gut mit den üblichen Rechte, aber wenn ich es laufen mit:

sudo ./convert.sh

habe ich diesen seltsamen Fehler:

find: "/media/disk/kevi" : no such file or directory. 

ich es gemacht:

IFS=$'\n' 
PICS="/media/disk/kevin/Images/"; 
echo PICS; 

Dann bekam ich überraschend:

/media/disk/kevi /Images/ 

WTF?

Antwort

2

Wenn Sie keine explict #! Zeile in Ihrem Skript haben, stehen die Chancen, dass die sudo-ed-Befehl statt /bin/bash unter /bin/sh betrieben wird, und wenn Sie auf einer neuen Linux-System laufen lassen, Wahrscheinlichkeiten sind, dass /bin/shdash eher als bash ist. Die Erfüllungsgehilfen von Dash behaupten, dass IFS Escape-Sequenzen nicht interpretieren soll (siehe zum Beispiel here).

$ more convert.sh 
IFS=$'\n' 
PICS="/media/disk/kevin/Images/"; 
echo $PICS; 
ps 
$ ./convert.sh 
/media/disk/kevin/Images/ 
    PID TTY   TIME CMD 
30827 pts/0 00:00:01 bash 
32042 pts/0 00:00:00 bash 
32043 pts/0 00:00:00 ps 
$ sudo ./convert.sh 
/media/disk/kevi /Images/ 
    PID TTY   TIME CMD 
32044 pts/0 00:00:00 sh 
32045 pts/0 00:00:00 ps 
$ ls -l /bin/sh 
lrwxrwxrwx 1 root root 4 2009-08-06 19:10 /bin/sh -> dash 

Also das Verhalten, das Sie sehen, ist nur indirekt mit dem Ausführen unter root verbunden. Sie würden dasselbe sehen, wenn Sie explizit den Bindestrich verwenden. Und eine andere Möglichkeit, um das Problem zu umgehen, wäre eine Erweiterung #!/bin/bash in Ihrem Skript.

+0

Getestet und in der Tat, das scheint so zu sein. Ich schalte die angenommene Antwort um, danke, dass du nicht nur deinen Fehler akzeptierst, sondern auch danach noch einen Beitrag zu leisten versuchst. –

+0

Danke! Ich fand es schwer zu glauben, dass das Problem in Sudo lag und ich selbst etwas Neues gelernt habe. –

3

Sie wickeln mit $IFS ist "n"; Es interpretiert \n nicht als Newline, sondern als sinnlos entkommen n. Ich vermute vage, dass Sie in einen schlecht dokumentierten Schutz von $IFS für root geraten (da es ein bekannter Exploit-Vektor ist), aber Sie könnten versuchen, eine literale Newline anstelle einer symbolischen in Ihr Skript einzubetten, indem Sie ctrl verwenden - veingeben.

+0

Vielen Dank Chaos. In der Tat scheint IFS für root geschützt zu sein und eine wörtliche neue Zeile zu verwenden, die wie ein Zauber funktioniert. –

+0

Eigentlich hat das nichts mit root zu tun. Lesen Sie die Shell Command Language Beschreibung von Escape Character (http://www.opengroup.org/onlinepubs/009695399/). –

+0

Und diese Referenz ist nicht hilfreich, weil sie ANSI-C-Zitate ($ '..'), die Sie hier verwenden, nicht beschreibt. Entschuldigung, mein Fehler. –

0

Ihr Code scheint einen Tippfehler zu haben. Wenn der tatsächliche Code IFS = '\ n' oder IFS = "\ n" ist, haben Sie das Trennzeichen auf eine Liste von zwei Zeichen gesetzt, \ und n. Wenn IFS = \ n, dann interpretiert eine char POSIX-Shell \ n nicht als LF. Es hat nichts mit Root zu tun.

$ BLAH='\n' 
$ echo $BLAH 
\n 
$ BLAH="\n" 
$ echo $BLAH 
\n 
$ BLAH=\n 
$ echo $BLAH 
n 
$ BLAH="Both\n\and\aregone" 
$ echo $BLAH 
Both a d arego e 
+0

Wie ich geschrieben habe, läuft dieses Skript gut und der Pfad wird ohne Administratorrechte angezeigt. Wenn ich die IFS-Ersetzung streiche, funktioniert das Skript nicht, weil IFS ein Leerzeichen ist und meine Schleife mit der Arbeit an getonten Pfaden endet, wenn sie irgendeinen Platz enthalten. Übrigens ist das nicht IFS = '\ n', sondern FS = $ '\ n'. Das ist sehr anders. –

+0

Entschuldigung, ich habe die Verwendung von ANSI-C-Zitaten in Ihrem Beispiel missverstanden, daher ist diese Antwort irrelevant.Siehe die neuere Antwort für eine wahrscheinliche Erklärung. –

Verwandte Themen