Оскільки файл не має жодного з типів виконуваного файлу, розпізнаваного системою, і якщо припустити, що у вас є дозвіл на виконання цього файлу, 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()не вдається (вона не намагається розглянути її як сценарій).
Деякі оболонки (наприклад, bashAT & 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"