
Meine Umgebung ist Ubuntu 12.04 LTS und die sudo
Version ist 1.8.3p1.
Zuerst melde ich mich als normaler Benutzer an:
$ whoami
fin
$ cat /etc/passwd | grep -i "root\|fin"
root:x:0:0:root:/root:/bin/bash
fin:x:1000:1000:This is a normal user:/home/fin:/bin/bash
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Mar 30 2012 /bin/sh -> dash
$ ls -l /bin/bash
-rwxr-xr-x 1 root root 920788 Apr 3 2012 /bin/bash
$ echo $SHELL
/bin/bash
$ ps | grep "$$" | awk '{ print $4 }'
bash
$ ls -l ./test.sh
-rwxr-xr-x 1 fin fin 37 Sep 27 16:46 test.sh
$ cat ./test.sh
ps | grep "$$" | awk '{ print $4 }'
$ ./test.sh
bash
$ sudo ./test.sh
sh
Ich nehme an, die letzte Ausgabe sollte auch „ bash
weil“ /etc/passwd
zeigen, dass Root verwendet bash
. Übersehe ich irgendwelche Punkte zu sudo
?
Antwort1
Es verwendet _PATH_BSHELL
„like “, was unter Linux wie in execvp()
definiert ist . Das sollte dasselbe sein wie bei der Ausführung mit oder zum Beispiel./bin/sh
/usr/include/paths.h
env
find -exec
Es sollte auf keinen Fall die Login-Shell des Benutzers verwenden. Die Tatsache, die Sie oben sehen, bash
liegt daran, dass bash
(die Shell, in der Sie diese Befehlszeile eingeben) versucht, sie auszuführen, und wenn sie einen ENOEXEC
Fehlercode erhält, execve
entscheidet sie sich, ihn stattdessen mit sich selbst zu interpretieren (im sh
Kompatibilitätsmodus).
Antwort2
Da Sie die Option nicht verwenden -s
, sudo
verwenden Sie _PATH_BSHELL
(was in /usr/include/paths.h
Ubuntu 12.04 LTS definiert ist), um $SHELL
es auszuführen. Blick in sudo
den Quellcode:
/* Stash user's shell for use with the -s flag; don't pass to plugin. */
if ((ud->shell = getenv("SHELL")) == NULL || ud->shell[0] == '\0') {
ud->shell = pw->pw_shell[0] ? pw->pw_shell : _PATH_BSHELL;
}
Wenn Sie -s
die Option verwenden, sudo
wird Ihr $SHELL
anstelle von verwendet _PATH_BSHELL
:
$ cat ./test.sh
ps | grep "$$" | awk '{ print $4 }'
$ ./test.sh
bash
$ sudo -s ./test.sh
bash
Antwort3
Der Kernel kann nur binäre ausführbare Images ausführen. Wie werden also Skripte ausgeführt? Schließlich kann ich my_script_without_shebang
in eine Shell-Eingabeaufforderung tippen und bekomme keine Fehlermeldung ENOEXEC
. Die Skriptausführung erfolgt nicht durch den Kernel, sondern durch die Shell. Der Exec-Code in der Shell sieht normalerweise ungefähr so aus:
/* try to run the program */
execl(program, basename(program), (char *)0);
/* the exec failed -- maybe it is a shell script without shebang? */
if (errno == ENOEXEC)
execl ("/bin/sh", "sh", "-c", program, (char *)0);
Sie können dies überprüfen, indem Sie ein Dummy-Shell-Skript ohne Shebang verfolgen:
cat > /tmp/foo.sh <<EOF
echo
EOF
chmod u+x /tmp/foo.sh
strace /tmp/foo.sh 2>&1 | grep exec
execve("/tmp/foo.sh", ["/tmp/foo.sh"], [/* 28 vars */]) = -1 ENOEXEC (Exec format error)
Anschließend erfolgt die Ausführung wie von Stephane beschrieben – es wird die Standard-Shell verwendet (im obigen Code-Ausschnitt ist dieser fest codiert).Diese nette UNIX-FAQkann mehr beantworten.