Запуск сценарію оболонки, коли "/ bin / sh" вказує на "/ bin / bash"


11

У цьому запитанні я прочитав наступне :

bash підтримує перемикач --posix, що робить його більш сумісним з POSIX. Він також намагається імітувати POSIX, якщо його викликають як sh .

Вищенаведена цитата передбачає, що /bin/shце посилання, на яке вказує /bin/bash.

Але я не зовсім розумію, що розуміється під "посиланням як sh" .


Скажіть, що у мене є такий сценарій, який називається "script.sh":

#!/bin/bash
echo "Hello World"

Будь ласка, скажіть мені у кожному з наступних випадків, чи буде сценарій виконуватись у звичайному bashрежимі чи в режимі POSIX (припустимо, що я виконував такі команди в запущеному терміналі bash):

  1. sh script.sh
  2. bash script.sh
  3. ./script.sh

Тепер скажіть, що у мене є наступний скрипт, який називається "script.sh" (який подібний до вищезазначеного сценарію, але без shebang):

echo "Hello World"

Будь ласка, скажіть мені у кожному з наступних випадків, чи буде сценарій виконуватись у звичайному bashрежимі чи в режимі POSIX (припустимо, що я виконував такі команди в запущеному терміналі bash):

  1. sh script2.sh
  2. bash script2.sh
  3. ./script2.sh

Відповіді:


19

Тільки випадки 1 і 4 будуть працювати в режимі POSIX (якщо вважати, що shце bash, а не якась інша реалізація sh). Будь-який випадок, який явно дзвонить bashбез --posix, не буде, чи з шебангу, чи ні. Будь-який випадок, який явно дзвонить, shбуде. Shebang використовується лише тоді, коли жодна оболонка не була явно запущена для сценарію.

Випадок 6, якщо ваш термінал працює bash, не працюватиме в режимі POSIX, і Bash буде викликати його, використовуючи сам. Якщо ваш термінал був запущений ЗШ замість цього, випадок 6 буде також працювати в режимі POSIX. POSIX неоднозначно стосується того, що саме повинно статися в такому випадку , і Bash і zsh зробили там різні варіанти. Bash викликає сценарій, використовуючи себе, а zsh використовує sh(що б там не сталося). Інші снаряди також залежать від цього питання.


Один простий спосіб сказати, в якому режимі ви перебуваєте, - це зробити свій сценарій:

kill -SIGHUP

який не вдасться з помилкою в режимі POSIX , але дасть інструкції щодо використання killпоза ним. Це просте розрізнення, і воно працює завдяки великому діапазону версій Bash, які повертаються назад, наскільки ви, мабуть, зіткнетеся.


3
Є інші речі, які змусять bashзапускатися в режимі POSIX, наприклад, POSIXLY_CORRECTзмінна середовище або SHELLOPTS=posix.
Стефан Шазелас

1
[ -o posix ]це більш очевидний спосіб перевірити, чи працює ви в режимі posix в bash (не в інших оболонках (крім yash), так що ви не хочете робити це в shсценарії). POSIXLY_CORRECT=1 bash -c '[ -o posix ] && echo yes'виходи yes`
Стефан Шазелас

2
У випадку 6, bash викликає скрипт із собою в режимі POSIX, коли він перебуває в режимі POSIX, як вимагає POSIX. POSIX не визначає механізм she-bang, і 6 є єдиним способом POSIX для виконання виконуваних сценаріїв і чітко визначений (у середовищах POSIX сценарій повинен інтерпретуватися сумісною утилітою sh).
Стефан Шазелас

8

«Викликається як» ставиться до того , що це те , що процес запуску Bash ставить у своїй «нульовий» аргумент командного рядка, argv[0].

Коли програма запускається з exec*()систематичними дзвінками , вони насправді не дізнаються назву двійкового файлу, що містить програму, але натомість процес виклику вільний помістити все, що хоче. Звичайно, звичайно, ім'я береться з файлової системи, тож якщо ви запустите /bin/sh, це те, що туди ставиться. І якщо /bin/shце Bash, це не повинно бути символьним посиланням, це може бути жорстке посилання або просто інша копія програми оболонки.

Як приклад встановлення "імені програми", execкоманда Баша може встановити нульовий аргумент за допомогою -aпараметра. (Ми могли б зробити те ж саме з Perl або безпосередньо з C тощо)

Ось mynameпроста програма C, яка просто надрукує нульовий аргумент, ім'я, яке вона бачить сама:

$ ./myname 
I am ./myname
$ (exec -a something ./myname )
I am something
$ mv ./myname somename
$ ln -s somename othername
$ ./somename 
I am ./somename
$ ./othername
I am ./othername

Джерело:

#include <stdio.h>
int main(int argc, char *argv[]) {
    printf("I am %s\n", argv[0]);
    return 0;
}

Але, щоб відповісти на нумеровані питання ...

(1 і 4) біг sh somescriptбуде виконувати все, що shє на вашому PATH, можливо, /bin/shале можливо щось подібне/usr/xpg4/bin/sh .

  • Якщо це Bash, він працює в режимі POSIX, оскільки бачить ім'я sh.
  • Якщо це оболонка Z або оболонка Korn, вона також бачить назву sh, але вона працює в режимі "сумісний з SH", який спрямований на сумісність оболонки Борна і тонко відрізняється від повного режиму, відповідного POSIX в обох цих оболонках .
  • Це могла бути оболонка Алквіста, фактична оболонка Борна чи щось інше, звичайно.

(2 і 5) Біг bash somescriptбуде працювати в звичайному режимі Bash (знову ж, це, звичайно, залежить від того, що bashу вас PATHє.)

(3) Тут назва скрипту вводиться безпосередньо до системного виклику замість файлу програми. Ядро зчитує рядок hashbang і використовує його для запуску сценарію.

(6) Це складний. Це аналогічно (3), але системний виклик для запуску програми виходить з ладу ( ENOEXEC (Exec format error)), оскільки немає лінії хешбангу. Що буде далі, залежить від того, чи знаходиться оболонка, яку ви працюєте, сама в режимі POSIX. POSIX вимагає, щоб оболонка, сумісна з POSIX, поводилася конкретно у відповідь на ENOEXEC. Однак є деяка свобода в "команді, еквівалентній виклику оболонки", що означає, що різні оболонки роблять різні речі.

  • Оболонка Bourne Again знову запускається в тому ж режимі з назвою сценарію, що і його перший аргумент командного рядка. У режимі, сумісному з POSIX, він, звичайно, працює у своєму режимі, сумісному з POSIX, таким чином, підкоряючись вимозі POSIX, щоб викликати оболонку, сумісну з POSIX.
  • Оболонка Z, оболонка Almquist і оболонка Korn виконуються /bin/shз назвою скрипту, вставленого перед іншими аргументами, як його першого аргументу командного рядка. Оболонка Z, оболонка Almquist і оболонка Korn намагаються викликати оболонку, сумісну з POSIX, припускаючи, що /bin/shпрограма передбачає одну.

Чи можете ви поділіться вихідним кодом цієї програми на С ..
GypsyCosmonaut

int main(int argc, char *argv[]){printf("I am %s\n",argv[0]);}
Стиг Хеммер

Це майже все.
ilkkachu

4

Оболонка виконується або тим, що викликається в командному рядку, або тим, що знаходиться в шебангу (якщо командний рядок не визначає його).

Отже, версії 1 і 4 працюватимуть з sh, 2 і 5 з bash і 6 можуть не працювати, якщо ви використовуєте sh (та деякі інші) інтерактивно. Bash дійсно запускає сценарій. Кш також. Zsh починає це як sh.

Тільки ті, що розпочалися так sh, використовуватимуть опцію posix, якщо bash пов'язаний з /bin/sh.

Додайте цей рядок до свого сценарію, щоб виявити, чи працює будь-яка версія bash ksh чи zsh:

echo "Hello World $BASH_VERSION $KSH_VERSION $ZSH_VERSION"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.