Respostas:
Provavelmente para manter o kernel mais simples. Acho que o kernel nunca pesquisa seu caminho para encontrar um executável. Isso é tratado pela biblioteca C. #!
O processamento é feito no kernel, que não usa a biblioteca C padrão.
Além disso, não acho que o kernel tenha uma noção de qual é o seu caminho. $PATH
é uma variável de ambiente e apenas processos têm um ambiente. O kernel não. Suponho que ele possa acessar o ambiente do processo que executou o executor, mas não acho que nada atualmente no kernel acesse variáveis de ambiente como essa.
Você pode obter a PATH
semântica de pesquisa usando env
, portanto:
#!/usr/bin/env ruby
tem a semântica que você gostaria de
#!ruby
O motivo pelo qual a dependência PATH
não é considerada uma boa prática é que o script não pode fazer suposições sobre o conteúdo da variável de ambiente PATH, quebrando o "modelo de dependência sequencial" dos binários em que
/bin
contém os executáveis necessários no momento da inicialização;/usr/bin
contém os outros executáveis usados pela instalação do SO;/usr/local/bin
contém executáveis instalados pelo administrador do sistema que não fazem parte do sistema operacional base.~/bin
contém os próprios executáveis do usuário.Cada nível não deve assumir a existência de binários posteriormente na sequência, que são mais "aplicativos", mas podem contar com binários anteriores, que são mais "fundamentais". E a variável PATH tende a ser aplicada de fundamental a fundamental, que é a direção oposta à dependência natural acima.
Para ilustrar o problema, pergunte-se o que acontece se um script ~/bin
chama um script /usr/local/bin
que chama Ruby? Esse script deve depender da versão do sistema operacional instalada /usr/bin/ruby
ou da cópia pessoal que o usuário possui ~/bin/ruby
? PATH
a pesquisa fornece a semântica imprevisível associada ao último (talvez ~/bin/ruby
seja um link simbólico quebrado), enquanto #!
abre caminho para o primeiro.
Não há realmente nenhum outro "sistema operacional ... independente de plataforma ... informações sobre o caminho para um comando registrado", então a coisa mais simples é insistir no caminho que está sendo fornecido no #!
.
Acredito que seja para que você possa especificar um intérprete alternativo, se precisar ou desejar. Por exemplo:
#!/home/user/myrubyinterpreter
Mais frequentemente visto com scripts de shell:
#!/bin/bash
#!/bin/sh
#!/bin/dash
#!/bin/csh
Do livro Classic Shell Scripting :
Os scripts de shell geralmente começam com
#! /bin/sh
. Use o caminho para um shell compatível com POSIX se o seu/bin/sh
não for compatível com POSIX. Há também algumas dicas de baixo nível a serem observadas:
- Você precisa saber o nome completo do caminho do intérprete a ser executado. Isso pode impedir a portabilidade entre fornecedores, uma vez que diferentes fornecedores colocam as coisas em lugares diferentes (por exemplo,
/bin/awk
versus/usr/bin/awk
).
Há outros motivos, mas, do ponto de vista da segurança, eu nunca gostaria que um script fizesse suposições sobre o caminho correto. E se estiver errado e executar o shell ou intérprete errado? Um que foi inserido por um usuário mal-intencionado? Ou, se depender de um shell específico e travar se o shell errado for usado?
Os usuários podem mexer com seu caminho e interromper as coisas - não confie no usuário :-) Eu conduzi vários ataques que dependem do usuário fazer a coisa errada com o caminho - geralmente obtendo as coisas na ordem errada - para que eu possa subverter uma chamada de script normal.
Sim, eu sei que se você mesmo escreveu o script, pode afirmar, com toda a razão, que resolveu seu próprio caminho, mas um intérprete não pode tomar essas decisões.
$PATH
. . Sem privilégios elevados, e se LD_PRELOAD
for usado? PS Votado porque dar um aviso falso sobre segurança é prejudicial à segurança.
PATH
existe um vetor de ataque e não existem tantos outros vetores de ataque que toda a abordagem deva ser repensada?
ruby
, mas isso não impede que você especifique/home/user/myrubyinterpreter
se deseja