какую оболочку будет использовать sudo для выполнения скрипта оболочки без строки shebang

какую оболочку будет использовать sudo для выполнения скрипта оболочки без строки shebang

Моя среда — Ubuntu 12.04 LTS, sudoверсия — 1.8.3p1.

Сначала я вхожу как обычный пользователь:

$ 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

Я полагаю, что последний вывод также должен быть, bashпотому что /etc/passwdпоказывает, что root использует bash, я упускаю какие-либо моменты sudo?

решение1

Он использует _PATH_BSHELLlike execvp()which в Linux определяется как /bin/shв /usr/include/paths.h. Это должно быть то же самое, что и при выполнении с envили find -execнапример.

Он определенно не должен использовать оболочку входа пользователя. Тот факт, что вы видите bashвыше, заключается в том, что это bash(оболочка, в которой вы вводите эту командную строку) пытается выполнить ее, и когда она получает ENOEXECкод ошибки, execveона решает интерпретировать его вместо себя (в shрежиме совместимости).

решение2

Поскольку вы не используете -soption, поэтому sudoбудем использовать _PATH_BSHELL(который определен в /usr/include/paths.hUbuntu 12.04 LTS), чтобы запустить $SHELLего. Заглядываем в sudoисходный код:

/* 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;
    }

Если вы используете -soption, sudoбудет использоваться ваш $SHELLвместо _PATH_BSHELL:

$ cat ./test.sh
ps | grep "$$" | awk '{ print $4 }'

$ ./test.sh
bash

$ sudo -s ./test.sh
bash

решение3

Ядро может запускать только исполняемые двоичные образы. Так как же запускаются скрипты? В конце концов, я могу печатать my_script_without_shebangв командной строке оболочки и не получаю ошибку ENOEXEC. Выполнение скрипта выполняется не ядром, а оболочкой. Код exec в оболочке обычно выглядит примерно так:

/* 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);

Вы можете убедиться в этом, выполнив трассировку фиктивного скрипта оболочки без shebang:

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)

Итак, выполнение продолжается так, как описал Стефан — используется оболочка по умолчанию (в приведенном выше фрагменте кода это жестко запрограммировано).Этот замечательный FAQ по UNIXмогу ответить подробнее.

Связанный контент