Poiché il file non appartiene a nessuno dei tipi di file eseguibili riconosciuti dal sistema e supponendo che si disponga dell'autorizzazione per eseguire quel file, la execve()chiamata di sistema in genere fallisce con un errore ENOEXEC( non un file eseguibile ).
Ciò che accade quindi dipende dall'applicazione e / o dalla funzione di libreria utilizzata per eseguire il comando.
Può essere ad esempio una shell, la funzione execlp()/ execvp()libc.
La maggior parte delle altre applicazioni utilizzerà una di quelle quando eseguono un comando. Invoceranno una shell ad esempio tramite la system("command line")funzione libc che in genere invocherà shl'analisi di quella riga di comando (il cui percorso può essere determinato al momento della compilazione (come /bin/shvs /usr/xpg4/bin/shsu Solaris)), o invocherà la shell memorizzata $SHELLda loro stessi come vicon il suo !comando o xterm -e 'command line'molti altri comandi ( su user -cinvocherà la shell di accesso dell'utente invece di $SHELL).
Generalmente, un file di testo privo di shebang che non inizia con #viene considerato come uno shscript. Quale shè varierà comunque.
execlp()/ execvp(), al execve()ritorno ENOEXECin genere invocherà shsu di esso. Per i sistemi che ne hanno più di uno shperché possono conformarsi a più di uno standard, il che shè generalmente determinato al momento della compilazione (dell'applicazione che utilizza execvp()/ execlp()collegando un diverso BLOB di codice che fa riferimento a un percorso diverso sh). Ad esempio, su Solaris, sarà /usr/xpg4/bin/sh(uno standard, POSIX sh) o /bin/sh(la shell Bourne (una shell antiquata) su Solaris 10 e precedenti, ksh93 in Solaris 11).
Quando si tratta di conchiglie, ci sono molte varianti. bash, AT&T ksh, la shell Bourne in genere interpreterà lo script stesso (in un processo figlio a meno che non execvenga utilizzato) dopo aver simulato un execve(), che non ha impostato tutte le variabili non esportate, chiuso tutte le fds close-on-exec, rimosso tutte le trap personalizzate, alias, funzioni ... ( bashinterpreterà lo script in shmodalità). yashsi eseguirà (con shas argv[0]so in shmode) per interpretarlo.
zsh, pdksh, ashConchiglie basati in genere richiamare sh(il percorso, determinato al momento della compilazione).
Per cshe tcsh(e shper alcuni dei primi BSD), se il primo carattere del file è #, allora si eseguiranno per interpretarlo, e in shaltro modo. Questo risale a un periodo pre-shebang in cui cshriconosceva #come commenti ma non la shell Bourne, quindi #c'era un indizio che si trattasse di uno script csh.
fish(almeno versione 2.4.0), restituisce solo un errore se execve()fallisce (non tenta di trattarlo come uno script).
Alcune shell (come basho AT&T ksh) proveranno prima a stabilire in modo euristico se il file è probabilmente destinato a essere uno script o meno. Quindi potresti scoprire che alcune shell si rifiuteranno di eseguire uno script se nei primi byte ha un carattere NUL.
Nota anche che se execve()fallisce con ENOEXEC ma il file ha una linea shebang, alcune shell cercano di interpretare quella linea shebang.
Quindi alcuni esempi:
- Quando
$SHELLè /bin/bash, xterm -e 'myscript with args'sarà myscriptinterpretato da bashin shmodalità. Mentre con xterm -e myscript with args, xtermutilizzerà execvp()così lo script verrà interpretato da sh.
su -c myscriptsu Solaris 10 dove rootsi trova la shell di login /bin/shed /bin/shè la shell Bourne sarà myscriptinterpretata dalla shell Bourne.
/usr/xpg4/bin/awk 'BEGIN{system("myscript")'su Solaris 10 verrà interpretato da /usr/xpg4/bin/sh(stesso per /usr/xpg4/bin/env myscript).
find . -prune -exec myscript {} \;su Solaris 10 (utilizzo execvp()) verrà interpretato /bin/shanche con /usr/xpg4/bin/find, anche in un ambiente POSIX (un bug di conformità).
csh -c myscriptlo interpreterà cshse inizia con #, shaltrimenti.
Tutto sommato, non puoi essere sicuro di quale shell verrà utilizzata per interpretare quello script se non sai come e da cosa verrà invocato.
In ogni caso, read -pè bashsolo sintassi, quindi ti consigliamo di assicurarti che lo script sia interpretato da bash(ed evita quell'estensione fuorviante .sh). O conosci il percorso bashdell'eseguibile e usi:
#! /path/to/bash -
read -p ...
Oppure puoi provare a fare affidamento su una $PATHricerca bashdell'eseguibile (supponendo che bashsia installato) usando:
#! /usr/bin/env bash
read -p ...
(si envtrova quasi ovunque /usr/bin). In alternativa, è possibile renderlo compatibile POSIX + Bourne, nel qual caso è possibile utilizzarlo /bin/sh. Tutti i sistemi avranno a /bin/sh. Sulla maggior parte di essi sarà (per la maggior parte) compatibile POSIX, ma potresti comunque trovare una shell Bourne ogni tanto.
#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"