Почему эта ссылка не работает, как ожидалось?


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 по умолчанию).

Из примера мы можем узнать: under /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#.

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


Текст, который можно легко вставить в редактор SE в виде изображения, довольно раздражает, поэтому, пожалуйста, не делайте этого. Вместо этого выберите текст в своем терминале и нажмите CTRL-SHIFT-C.
кот

Ответы:


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, он выводит универсальное время. При запуске as etвыводит восточное время США. Например:

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

4
Возможно, стоит добавить, как это возможно, поскольку ФП ожидает, что вызовы будут идентичными. ( argv[0], obvs)
Гонки

@LightnessRacesinOrbit Хорошая идея. Я добавил пример.
John1024

Идеально сейчас. :)
Гонки легкости на орбите
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.