Чому це програмне забезпечення не працює так, як очікувалося?


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#.

У чому причина?


Текст, який досить легко можна копіювати в редактор 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, він виводить універсальний час. Коли запускається як 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.