Ponieważ plik nie należy do żadnego z typów plików wykonywalnych rozpoznawanych przez system i przy założeniu, że masz uprawnienia do wykonania tego pliku, execve()wywołanie systemowe zwykle kończy się niepowodzeniem z błędem ENOEXEC( nie wykonywalnym ).
To, co się wtedy stanie, zależy od aplikacji i / lub funkcji bibliotecznej użytej do wykonania polecenia.
Może to być na przykład powłoka, funkcja execlp()/ execvp()libc.
Większość innych aplikacji będzie używać jednej z tych aplikacji po uruchomieniu polecenia. Będą wywoływać powłokę na przykład za pomocą system("command line")funkcji libc, która zwykle wywołuje w shcelu parsowania tej linii poleceń (której ścieżkę można określić w czasie kompilacji (jak /bin/shvs /usr/xpg4/bin/shw Solarisie)) lub wywołuje powłokę przechowywaną $SHELLprzez siebie jak viz jego !poleceniem lub xterm -e 'command line'wieloma innymi poleceniami ( su user -czamiast tego wywoła powłokę logowania użytkownika $SHELL).
Zasadniczo plik tekstowy bez shebang, który się nie zaczyna, #jest uważany za shskrypt. Które shto będzie się różnić.
execlp()/ execvp(), po execve()powrocie ENOEXECzwykle wywołuje shna nim. W przypadku systemów, które mają więcej niż jeden, shponieważ mogą być zgodne z więcej niż jednym standardem, co shzwykle określa się w czasie kompilacji (aplikacji używającej execvp()/ execlp()przez połączenie innego obiektu blob kodu, który odnosi się do innej ścieżki sh). Na przykład w /usr/xpg4/bin/shsystemie Solaris będzie to (standard, POSIX sh) lub /bin/sh(powłoka Bourne'a (przestarzała powłoka) w systemie Solaris 10 i starszych wersjach, ksh93 w systemie Solaris 11).
Jeśli chodzi o muszle, istnieje wiele odmian. bash, AT&T ksh, powłoka Bourne'a zazwyczaj interpretuje sam skrypt (w procesie potomnym, o ile nie execjest używany) po symulacji a execve(), czyli nieuzbrojonej wszystkich nieobsługiwanych zmiennych, zamykając wszystkie fds close-on-exec, usuwając wszystkie niestandardowe pułapki, aliasy, funkcje ... ( bashzinterpretuje skrypt w shtrybie). yashwykona się ( tak shjak argv[0]w shtrybie), aby go zinterpretować.
zsh, pdksh, ashOpartych powłoki zazwyczaj wywołania sh(ścieżka, która określona w czasie kompilacji).
Dla cshi tcsh(i shniektórych wczesnych BSD), jeśli pierwszym znakiem pliku jest #, to wykonają się, aby go zinterpretować, i w shprzeciwnym razie. To sięga czasów sprzed shebang, w których cshrozpoznawano #jako komentarze, ale nie powłokę Bourne'a, więc #była to wskazówka, że był to skrypt csh.
fish(przynajmniej wersja 2.4.0), po prostu zwraca błąd, jeśli się execve()nie powiedzie (nie próbuje traktować go jako skryptu).
Niektóre powłoki (jak bashAT&T ksh) najpierw spróbują heurystycznie ustalić, czy plik prawdopodobnie ma być skryptem, czy nie. Może się więc okazać, że niektóre powłoki odmówią wykonania skryptu, jeśli w pierwszych kilku bajtach ma znak NUL.
Zauważ też, że jeśli execve()nie powiedzie się ENOEXEC, ale plik ma linię shebang, niektóre powłoki próbują sami interpretować tę linię shebang.
Oto kilka przykładów:
- Kiedy
$SHELLjest /bin/bash, xterm -e 'myscript with args'będzie myscriptinterpretowane przez bashw shtrybie. Podczas gdy xterm -e myscript with args, xtermużyje, execvp()więc skrypt zostanie zinterpretowany przez sh.
su -c myscriptna Solarisie 10, gdzie rootpowłoka logowania jest /bin/shi /bin/shjest powłoką Bourne'a, zostanie myscriptzinterpretowana przez powłokę Bourne'a.
/usr/xpg4/bin/awk 'BEGIN{system("myscript")'na Solarisie 10 będzie interpretowany przez /usr/xpg4/bin/sh(to samo dla /usr/xpg4/bin/env myscript).
find . -prune -exec myscript {} \;na Solarisie 10 (używanie execvp()) będzie interpretowane /bin/shnawet przez /usr/xpg4/bin/find, nawet w środowisku POSIX (błąd zgodności).
csh -c myscriptbędzie interpretowany przez, cshjeśli zacznie od #, w shprzeciwnym razie.
Podsumowując, nie możesz być pewien, która powłoka zostanie użyta do interpretacji tego skryptu, jeśli nie wiesz jak i przez co zostanie on wywołany.
W każdym razie read -pjest to bashtylko składnia, więc upewnij się, że skrypt jest interpretowany przez bash(i unikaj tego mylącego .shrozszerzenia). Albo znasz ścieżkę bashpliku wykonywalnego i użyj:
#! /path/to/bash -
read -p ...
Lub możesz polegać na $PATHwyszukiwaniu bashpliku wykonywalnego (zakładając, że bashjest zainstalowany), używając:
#! /usr/bin/env bash
read -p ...
( envjest prawie wszechobecny w /usr/bin). Alternatywnie możesz ustawić kompatybilność POSIX + Bourne. W takim przypadku możesz użyć /bin/sh. Wszystkie systemy będą miały /bin/sh. W większości z nich będzie (w przeważającej części) kompatybilny z POSIX, ale możesz od czasu do czasu znaleźć tam powłokę Bourne'a.
#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"