Оскільки файл не має жодного з типів виконуваного файлу, розпізнаваного системою, і якщо припустити, що у вас є дозвіл на виконання цього файлу, execve()
системний виклик, як правило, не працює з помилкою ENOEXEC
( не виконуваною ).
Тоді, що станеться, залежить від програми та / або функції бібліотеки, яка використовується для виконання команди.
Це може бути, наприклад, оболонка, функція execlp()
/ execvp()
libc.
Більшість інших додатків використовуватимуть будь-який із них, коли вони виконують команду. Вони будуть викликати оболонку наприклад , за допомогою шляхом system("command line")
LibC функції , яка зазвичай викликається sh
для розбору цієї командного рядка (шлях , який може бути визначений під час компіляції (наприклад , /bin/sh
проти /usr/xpg4/bin/sh
на Solaris)), або запускайте оболонки зберігається в $SHELL
самому по собі , як vi
з його !
командою або xterm -e 'command line'
та багатьма іншими командами ( su user -c
замість них буде викликати оболонку входу користувача $SHELL
).
Як правило, текстовий файл без шебангу, який не починається з #
, вважається sh
сценарієм. Який sh
він буде різним, хоча.
execlp()
/ execvp()
, після execve()
повернення ENOEXEC
зазвичай посилається sh
на нього. Для систем, які мають більше однієї, sh
оскільки вони можуть відповідати більш ніж одному стандарту, який sh
, як правило, визначається під час компіляції (програми, що використовує execvp()
/ execlp()
прив'язуючи інший фрагмент коду, який посилається на інший шлях sh
). Наприклад, для Solaris це буде або /usr/xpg4/bin/sh
(стандарт, POSIX sh
), або /bin/sh
(оболонка Bourne (антикваріальна оболонка) для Solaris 10 і старші, ksh93 в Solaris 11).
Що стосується снарядів, тут багато варіацій. bash
, AT&T ksh
, оболонка Bourne зазвичай інтерпретує сам сценарій (у дочірньому процесі, якщо exec
не використовується) після імітації a execve()
, тобто скидання всіх експортованих змінних, закриття всіх FDS-файлів close-on-exec, видалення всіх спеціальних пасток, псевдоніми, функції ... ( bash
буде інтерпретувати сценарій у sh
режимі). yash
виконає себе (з sh
таким argv[0]
чином у sh
режимі), щоб інтерпретувати його.
zsh
, pdksh
, ash
-А оболонка зазвичай викликається sh
(шлях якого визначається під час компіляції).
Для csh
і tcsh
(та sh
деяких ранніх BSD), якщо перший символ файлу є #
, то вони самі виконають його інтерпретацію та sh
інше. Це повертається до часів перед шебангом, коли csh
визнавали #
коментарі, але не оболонкою Борна, тому #
було натяком на те, що це сценарій csh.
fish
(принаймні версія 2.4.0), просто повертає помилку, якщо execve()
не вдається (вона не намагається розглянути її як сценарій).
Деякі оболонки (наприклад, bash
AT & T ksh
) спершу спробують евристично визначити, чи мається на увазі, що файл - це сценарій чи ні. Таким чином, ви можете виявити, що деякі оболонки відмовляться виконувати сценарій, якщо він отримав символ NUL в перших кількох байтах.
Також зауважте, що якщо execve()
помилка ENOEXEC, але у файлу є лінія shebang, деякі оболонки намагаються самостійно інтерпретувати цю лінію shebang.
Ось кілька прикладів:
- Коли
$SHELL
є /bin/bash
, xterm -e 'myscript with args'
буде myscript
інтерпретуватися bash
в sh
режимі. У той час як з xterm -e myscript with args
, xterm
використовуватиме, execvp()
тому сценарій буде інтерпретований sh
.
su -c myscript
на Solaris 10, де root
оболонка входу є /bin/sh
і /bin/sh
оболонка Борна, буде myscript
інтерпретована оболонкою Борна.
/usr/xpg4/bin/awk 'BEGIN{system("myscript")'
на Solaris 10 буде інтерпретовано це /usr/xpg4/bin/sh
(те саме для /usr/xpg4/bin/env myscript
).
find . -prune -exec myscript {} \;
на Solaris 10 (використовуючи execvp()
) буде інтерпретувати це /bin/sh
навіть з /usr/xpg4/bin/find
, навіть у середовищі POSIX (помилка відповідності).
csh -c myscript
буде інтерпретовано, csh
якщо це починається з #
, sh
інакше.
Загалом, ви не можете бути впевнені, яка оболонка буде використовуватися для інтерпретації цього сценарію, якщо ви не знаєте, як і на що він буде викликаний.
У будь-якому випадку read -p
це bash
синтаксис -inly, тому ви хочете переконатися, що сценарій інтерпретується bash
(і уникайте цього оманливого .sh
розширення). Або ви знаєте шлях bash
виконуваного файлу та використовуйте:
#! /path/to/bash -
read -p ...
Або ви можете спробувати покластися на $PATH
пошук bash
виконуваного файлу (при умові bash
, що встановлено), використовуючи:
#! /usr/bin/env bash
read -p ...
( env
майже всюди зустрічається в /usr/bin
). Крім того, ви можете зробити POSIX + Bourne сумісним, і в цьому випадку ви можете їх використовувати /bin/sh
. Усі системи матимуть /bin/sh
. У більшості з них це буде (здебільшого) POSIX-сумісний, але ви все ще можете знайти тут і потім оболонку Bourne.
#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"