É possível ter um shebang que, em vez de especificar um caminho para um intérprete, tenha o nome do intérprete e permita que o shell o encontre através de $ PATH?
Caso contrário, existe uma razão para isso?
É possível ter um shebang que, em vez de especificar um caminho para um intérprete, tenha o nome do intérprete e permita que o shell o encontre através de $ PATH?
Caso contrário, existe uma razão para isso?
Respostas:
A pesquisa PATH é um recurso da biblioteca C padrão no espaço do usuário, assim como as variáveis de ambiente em geral. O kernel não vê variáveis de ambiente, exceto quando passa por um ambiente do chamador execvepara o novo processo.
O kernel não executa nenhuma interpretação no caminho execve(depende das funções do wrapper, como execvpexecutar a pesquisa PATH) ou em um shebang (que mais ou menos redireciona a execvechamada internamente). Então você precisa colocar o caminho absoluto no shebang¹. A implementação original do shebang era apenas algumas linhas de código e não foi significativamente expandida desde então.
Nas primeiras versões do Unix, o shell fez o trabalho de se chamar quando percebeu que você estava chamando um script. Shebang foi adicionado ao kernel por várias razões (resumindo a lógica de Dennis Ritchie :
Shebangs sem caminho exigiriam aumentar o kernel para acessar variáveis e processos do ambiente PATH, ou fazer com que o kernel execute um programa no espaço do usuário que execute a pesquisa PATH. O primeiro método requer a adição de uma quantidade desproporcional de complexidade ao kernel. O segundo método já é possível com um #!/usr/bin/envshebang .
¹ Se você colocar um caminho relativo, ele será interpretado em relação ao diretório atual do processo (não ao diretório que contém o script), o que dificilmente é útil em um shebang.
execvenem no shebang, embora faça pouco sentido ter um caminho relativo em um shebang.
/lib64/ld-linux-x86-64.so.2(consulte a lddsaída). O Linux o torna totalmente genérico: o binfmtsuporte (desde 2.1.43) permite registrar pares de intérprete / caminho / número mágico ou extensão de arquivo. Você pode ter PE32 .exeinvoke s winequando você executá-los, arquivos de classe e jar Java invocar java, etc. etc.
Há mais coisas acontecendo do que aparenta. #!As linhas são interpretadas pelo kernel Unix ou Linux, #!não é um aspecto dos shells. Isso significa que PATHrealmente não existe no momento em que o kernel decide o que executar.
A maneira mais comum de lidar com o desconhecimento de qual executável executar, ou chamar de perlmaneira portátil ou similar, é usar #!/usr/bin/env perl. O kernel é executado /usr/bin/env, que herda uma PATHvariável de ambiente. envachados (neste exemplo) perlem PATHe usa a execve(2)chamada de sistema para obter o kernel para executar o perlexecutável.
$ strace sleep 1
execve("/usr/bin/sleep", ["sleep", "1"], [/* 99 vars */]) = 0
A conversão para o caminho completo é feita pelo shell (mais geral: no espaço do usuário). O kernel espera um nome / caminho de arquivo que possa acessar diretamente.
Se você deseja que o sistema encontre seu executável olhando através da variável PATH, você pode reescrever seu shebang como #!/usr/bin/env EXEC.
Mas também neste caso, não é o kernel que faz a pesquisa.
strace(convertido /usr/bin/straceem algum momento) com 2 argumentos.