Como o arquivo não é de nenhum dos tipos de executáveis reconhecidos pelo sistema e, assumindo que você tem permissão para executá-lo, a execve()
chamada do sistema normalmente falhará com um erro ENOEXEC
( não executável ).
O que acontece então depende da aplicação e / ou função da biblioteca usada para executar o comando.
Pode ser, por exemplo, um shell, a função execlp()
/ execvp()
libc.
A maioria dos outros aplicativos usará um deles quando executar um comando. Eles invocam um shell, por exemplo, por meio da system("command line")
função libc, que normalmente invoca sh
para analisar essa linha de comando (cujo caminho pode ser determinado em tempo de compilação (como /bin/sh
vs /usr/xpg4/bin/sh
no Solaris)), ou invoca o shell armazenado $SHELL
por eles mesmos, como vi
com seu !
comando ou com xterm -e 'command line'
muitos outros comandos ( su user -c
invocará o shell de login do usuário em vez de $SHELL
).
Geralmente, um arquivo de texto sem shebang que não inicia #
é considerado como um sh
script. Qual sh
é o que irá variar embora.
execlp()
/ execvp()
, ao execve()
retornar ENOEXEC
, normalmente o invocará sh
. Para sistemas que possuem mais de um, sh
porque podem estar em conformidade com mais de um padrão, o que sh
normalmente será determinado no momento da compilação (do aplicativo usando execvp()
/ execlp()
vinculando um blob diferente de código que se refere a um caminho diferente para sh
). Por exemplo, no Solaris, isso será /usr/xpg4/bin/sh
(um padrão, POSIX sh
) ou /bin/sh
(o shell Bourne (um shell antiquado) no Solaris 10 e mais antigo, ksh93 no Solaris 11).
Quando se trata de conchas, há muita variação. bash
, AT&T ksh
, o shell Bourne normalmente interpreta o próprio script (em um processo filho, a menos que exec
seja usado) depois de simular a execve()
, que está desmarcada todas as variáveis não exportadas, fechou todos os fds de execução imediata, removeu todas as traps personalizadas, aliases, funções ... ( bash
interpretará o script no sh
modo). yash
se executará (com sh
o argv[0]
modo no sh
modo) para interpretá-lo.
zsh
, pdksh
, ash
Conchas baseados irá tipicamente invocar sh
(o caminho de que determinado no momento da compilação).
Para csh
e tcsh
(e o sh
de alguns BSDs iniciais), se o primeiro caractere do arquivo for #
, eles se executarão para interpretá-lo e de sh
outra forma. Isso remonta a um período pré-shebang, onde csh
ele reconheceu #
como comentários, mas não o shell Bourne, então #
havia uma dica de que era um script csh.
fish
(pelo menos versão 2.4.0), apenas retorna um erro se execve()
falhar (ele não tenta tratá-lo como um script).
Alguns shells (como a bash
AT&T ksh
) primeiro tentarão determinar heuristicamente se o arquivo provavelmente deve ser um script ou não. Portanto, você pode achar que alguns shells se recusam a executar um script se ele tiver um caractere NUL nos primeiros bytes.
Observe também que, se houver execve()
falha no ENOEXEC, mas o arquivo tiver uma linha shebang, alguns shells tentarão interpretar essa linha shebang.
Então, alguns exemplos:
- Quando
$SHELL
estiver /bin/bash
, xterm -e 'myscript with args'
terá myscript
interpretado por bash
no sh
modo. Enquanto estiver com xterm -e myscript with args
, xterm
usará execvp()
para que o script seja interpretado por sh
.
su -c myscript
no Solaris 10, onde root
o shell de logon é /bin/sh
e /bin/sh
é o shell Bourne terá sido myscript
interpretado pelo shell Bourne.
/usr/xpg4/bin/awk 'BEGIN{system("myscript")'
no Solaris 10, ele será interpretado por /usr/xpg4/bin/sh
(o mesmo para /usr/xpg4/bin/env myscript
).
find . -prune -exec myscript {} \;
no Solaris 10 (usando execvp()
), ele será interpretado por /bin/sh
even with /usr/xpg4/bin/find
, mesmo em um ambiente POSIX (um erro de conformidade).
csh -c myscript
terá interpretado por csh
se começa com #
, com o sh
contrário.
Em suma, você não pode ter certeza de qual shell será usado para interpretar esse script se você não souber como e pelo que será chamado.
De qualquer forma, read -p
é bash
apenas uma sintaxe, portanto, você deve garantir que o script seja interpretado por bash
(e evitar essa .sh
extensão enganosa ). Você conhece o caminho do bash
executável e usa:
#! /path/to/bash -
read -p ...
Ou você pode tentar confiar na $PATH
pesquisa do bash
executável (supondo que bash
esteja instalado) usando:
#! /usr/bin/env bash
read -p ...
( env
é quase onipresente encontrado em /usr/bin
). Como alternativa, você pode torná-lo compatível com POSIX + Bourne e, nesse caso, você pode usá-lo /bin/sh
. Todos os sistemas terão a /bin/sh
. Na maioria deles, é (na maior parte) compatível com POSIX, mas você ainda pode encontrar de vez em quando um shell Bourne lá.
#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"