shebang e caminho


22

Por que um shebang precisa de um caminho?

Errado

#!ruby

Corrigir

#!/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 fornecido?

Respostas:


22

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.


5

Você pode obter a PATHsemâ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 PATHnã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

  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 sistema operacional 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 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 ~/binchama um script /usr/local/binque chama Ruby? Esse script deve depender da versão do sistema operacional instalada /usr/bin/rubyou da cópia pessoal que o usuário possui ~/bin/ruby? PATHa pesquisa fornece a semântica imprevisível associada ao último (talvez ~/bin/rubyseja 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 #!.


0

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

4
Mas por que isso tornaria necessário? Você pode executar ruby ​​diretamente com ruby, mas isso não impede que você especifique /home/user/myrubyinterpreterse deseja
Michael Mrozek

O ponto de Michael é exatamente o que eu estou perguntando.
sawa

0

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/shnã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/awkversus /usr/bin/awk).

-2

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.


Essa preocupação se aplica apenas se o script estiver sendo executado com privilégios elevados. E isso é incomum, porque shebang e setxid não tocam bem juntos, e há muito mais com o que se preocupar $PATH. . Sem privilégios elevados, e se LD_PRELOADfor usado? PS Votado porque dar um aviso falso sobre segurança é prejudicial à segurança.
Gilles 'SO- stop be evil'

Seu ponto sobre setxid é válido, no entanto, é um vetor de ataque perfeitamente útil para que definitivamente não é um falso aviso
Rory Alsop

1
Você poderia dar um exemplo de caso em que PATHexiste um vetor de ataque e não existem tantos outros vetores de ataque que toda a abordagem deva ser repensada?
Gilles 'SO- stop be evil'

@ Gilles - +1, você tem um bom argumento, definitivamente, como se isso estivesse quebrado, provavelmente existem outras maneiras válidas, no entanto, em termos de coisas quebradas que você pode consertar, é fácil.
Rory Alsop
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.