welche Shell wird sudo verwenden, um ein Shell-Skript ohne die Shebang-Zeile auszuführen

welche Shell wird sudo verwenden, um ein Shell-Skript ohne die Shebang-Zeile auszuführen

Meine Umgebung ist Ubuntu 12.04 LTS und die sudoVersion 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 „ bashweil“ /etc/passwdzeigen, 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.henvfind -exec

Es sollte auf keinen Fall die Login-Shell des Benutzers verwenden. Die Tatsache, die Sie oben sehen, bashliegt daran, dass bash(die Shell, in der Sie diese Befehlszeile eingeben) versucht, sie auszuführen, und wenn sie einen ENOEXECFehlercode erhält, execveentscheidet sie sich, ihn stattdessen mit sich selbst zu interpretieren (im shKompatibilitätsmodus).

Antwort2

Da Sie die Option nicht verwenden -s, sudoverwenden Sie _PATH_BSHELL(was in /usr/include/paths.hUbuntu 12.04 LTS definiert ist), um $SHELLes auszuführen. Blick in sudoden 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 -sdie Option verwenden, sudowird Ihr $SHELLanstelle 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_shebangin 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.

verwandte Informationen