shebang e caminho

21

Por que um shebang precisa de um caminho?

Errado

#!ruby

Correto

#!/usr/local/bin/ruby

#!/usr/bin/env ruby

O sistema operacional deve ter as informações sobre o caminho para um comando registrado, e por que ele ainda espera que seja dado?

    
por sawa 24.04.2011 / 03:17

5 respostas

21

Provavelmente para manter o kernel mais simples. Eu não acho que o kernel sempre procura seu caminho para encontrar um executável. Isso é tratado pela biblioteca C. O processamento de #! é 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 os processos possuem um ambiente. O kernel não. Eu suponho que ele poderia acessar o ambiente do processo que executou o exec, mas acho que nada atualmente no kernel acessa variáveis de ambiente como essa.

    
por 24.04.2011 / 06:54
5

Você pode obter a semântica de PATH -searching usando env , então:

#!/usr/bin/env ruby  

tem a semântica que você gostaria de

#!ruby

A razão que depende de PATH não ser considerada 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" de binários onde

  1. /bin contém os executáveis necessários no momento da inicialização;
  2. /usr/bin contém os outros executáveis usados pela instalação do SO;
  3. /usr/local/bin contém executáveis instalados pelo administrador do sistema que não fazem parte do SO base.
  4. ~/bin contém os próprios executáveis do usuário.

Cada nível não deve assumir a existência de binários mais tarde na sequência, que são mais "aplicativos", mas podem depender de binários anteriores, que são mais "fundamentados". E a variável PATH tende a correr de applicationy para fundamental, que é a direção oposta à dependência natural acima.

Para ilustrar o problema, pergunte a si mesmo o que acontece se um script em ~/bin chamar um script em /usr/local/bin que invoque o Ruby? Esse script deve depender da versão instalada do SO em /usr/bin/ruby ou da cópia pessoal que o usuário tem em ~/bin/ruby ? PATH search fornece a semântica imprevisível associada a esta última (talvez ~/bin/ruby seja um link simbólico quebrado), enquanto assa o caminho para #! fornece o primeiro.

Não há realmente nenhum outro sistema operacional "independente de plataforma ... informações sobre o caminho para um comando registrado", então o mais simples é insistir no caminho que está sendo fornecido no #! .

    
por 24.04.2011 / 14:17
0

Acredito que você possa especificar um intérprete alternativo, se precisar ou quiser. Por exemplo:

#!/home/user/myrubyinterpreter

Mais frequentemente visto com scripts de shell:

#!/bin/bash
#!/bin/sh
#!/bin/dash
#!/bin/csh
    
por 24.04.2011 / 04:09
0

Do livro Script clássico do Shell :

Shell scripts typically start with #! /bin/sh. Use the path to a POSIX-compliant shell if your /bin/sh isn't POSIX compliant. There are also some low-level "gotchas" to watch out for:

  • You have to know the full pathname to the interpreter to be run. This can prevent cross-vendor portability, since different vendors put things in different places (e.g., /bin/awk versus /usr/bin/awk).
    
por 21.12.2011 / 00:30
-2

Existem outros motivos, mas, do ponto de vista da segurança, eu nunca desejaria que um script fizesse suposições sobre o caminho correto. E se estiver errado e executar o shell ou o interpretador errado? Um que tenha sido inserido por um usuário mal-intencionado? Ou se depender de um determinado shell e falhar se o shell errado for usado?

Os usuários podem mexer no seu caminho e quebrar coisas - não confiem no usuário :-) Eu conduzi inúmeros ataques que dependem de o usuário fazer a coisa errada com o caminho deles - geralmente colocando as coisas na ordem errada - então Posso subverter uma chamada de script normal.

Sim, eu sei que se você escreveu o roteiro você mesmo pode afirmar que você escolheu o seu próprio caminho, mas um intérprete não pode tomar essas decisões.

    
por 24.04.2011 / 12:01