11
bash4.3 # pwd
/bin
bash4.3 # ll sh
lrwxrwxrwx. 1   root    root    4   May 17 22:22 sh -> bash
bash4.3 # ll bash
-rwxr-xr-x. 1   root    root    1072056 May 17 22:22 bash
bash4.3 # bash
bash4.3 # sh
sh-4.3#

Моя ОС Fedora 24 (версия GNOME по умолчанию).

Из примера мы можем узнать: в /bin , bash является двоичным исполняемым файлом; sh - это мягкая ссылка на bash .

Поэтому, насколько мне известно, type bash and press enter должны привести к тому же результату, что type sh and press enter .

Когда я type bash and press enter , я получаю [root@localhost bin]# как и ожидалось.

Однако, если я type sh and press enter , я получу sh-4.3# .

В чем причина?

1 ответ1

25

Это документированная особенность.

Если вы запустите bash по символической ссылке sh , bash запустится в режиме совместимости с sh .

От man bash:

Если bash вызывается с именем sh, он пытается максимально близко имитировать поведение при запуске исторических версий sh, при этом также соответствует стандарту POSIX. При вызове в качестве интерактивной оболочки входа в систему или неинтерактивной оболочки с параметром --login сначала он пытается прочитать и выполнить команды из /etc /profile и ~ /.profile в указанном порядке. Опция --noprofile может использоваться для подавления этого поведения. При вызове в качестве интерактивной оболочки с именем sh bash ищет переменную ENV, расширяет ее значение, если оно определено, и использует расширенное значение в качестве имени файла для чтения и выполнения. Поскольку оболочка, вызываемая как sh, не пытается читать и выполнять команды из любых других файлов запуска, опция --rcfile не имеет никакого эффекта. Неинтерактивная оболочка, вызываемая с именем sh, не пытается читать другие файлы запуска. Когда вызывается как sh, bash переходит в режим posix после чтения файлов запуска.

Как программа узнает, какое имя использовалось для ее запуска?

Если это программа переменного тока, она может проверить argv[0] . Если это сценарий оболочки или Perl, он может проверить $0 .

В качестве примера давайте рассмотрим этот простой сценарий оболочки:

$ cat utc
#!/bin/sh
case "${0##*/}" in
        utc) date -u ;;
        et) TZ=US/Eastern date ;;
esac

$0 - это имя, по которому был вызван скрипт. ${0##*/} - это имя, для которого был вызван сценарий с удаленными именами каталогов.

Давайте создадим эту символическую ссылку:

ln -s utc et

Итак, utc и et запускают один и тот же исполняемый файл, но дают разные результаты. При запуске как utc выводит универсальное время. При запуске как et , выводится американское восточное время. Например:

$ utc
Wed Jul 20 18:14:18 UTC 2016
$ et
Wed Jul 20 14:14:20 EDT 2016

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .