O padrão de shell POSIX diz neste site
http://pubs.opengroup.org/onlinepubs/9699919799/
sobre como os shells usam PATH
para procurar executáveis:
"A lista deve ser pesquisada do começo ao fim, aplicando o nome do arquivo a cada prefixo, até que um arquivo executável com o nome especificado e as permissões de execução apropriadas seja encontrado."
Bem, não é assim que isso parece funcionar na implementação real do POSIX:
man which
diz:
"retorna os nomes de caminho dos arquivos (ou links) que seriam executados no ambiente atual, se seus argumentos fossem dados como comandos em um shell estritamente compatível com POSIX. Isso é feito pesquisando no PATH por arquivos executáveis que correspondem aos nomes dos argumentos. Não segue links simbólicos ".
OK, vamos olhar para esta situação:
$ pwd
/home/mark
$ echo $PATH
/home/mark/bin:
...
$ ls -l bin/foobar
lrwxrwxrwx 1 mark mark 18 Dec 12 22:51 bin/foobar -> /home/mark/foobar1
$ touch foobar1
$ which foobar
$ chmod a+x foobar1
$ which foobar
/home/mark/bin/foobar
OK, aqui está um link simbólico PATH
com o nome correto e é relatado ls
como sendo executável.
which
não olha nada, mas só está interessado no que aponta.
Isso apesar do fato de ambos man which
dizerem explicitamente que ele não segue links simbólicos (e, de fato, o vemos, porque which foobar
não imprime foobar1
), e também que a documentação do shell POSIX citada acima, nunca menciona os links simbólicos no PATH
algoritmo.
Então, which
as conchas existentes estão erradas ou não estou entendendo a documentação?
ESCLARECER:
Eu sei e posso explicar o comportamento existente. Minha pergunta não é "como isso funciona?". Que eu saiba.
Minha pergunta é sobre documentação: onde está meu erro em seguir a documentação que citei. Ou a documentação está errada?
MOTIVAÇÃO: Por que eu me importo?
Bem, eu sou um implementador. Implementadores diferentes têm requisitos diferentes. Para mim, o requisito é que a palavra do padrão POSIX atual DEVE ser seguida EXATAMENTE (ou, mais precisamente, o melhor que pode ser, porque o próprio padrão é um tanto incorreto). Como se fosse a palavra de Deus.
Agora, a redação padrão é bastante clara - os links simbólicos a seguir não são mencionados, onde em muitos outros lugares, é mencionado onde precisa ser feito. Então, neste caso, não.
No entanto, eu sempre verifiquei como dash
e me bash
comporte, apenas para ter certeza. Agora, é claro, também há um pequeno problema aqui, dash
mesmo que seja anunciado como POSIX, possui muitos pequenos bugs com conformidade com o POSIX. bash
, Ainda não encontrei nenhum bug com o POSIX, mas ... o bash não é realmente o POSIX, é muito mais do que isso.
Então aí está. É por isso que eu me importo.
fonte
$PATH
can contém links simbólicos. Tentewhich sh
.$PATH
, não possui links simbólicos.lstat(2)
), segui-los geralmente não é indicado. Por exemplo, a descriçãoopen(2)
apenas menciona links simbólicos ao falar sobre o comportamento deO_CREAT | O_EXCL
. Não é necessário declarar que o arquivo de destino será aberto.Respostas:
As permissões do próprio link simbólico são irrelevantes. Você nem poderia alterá-los se tentasse.
O que importa são as permissões do arquivo subjacente.
É bom ter diretórios em seu PATH incluir links simbólicos para executáveis. De fato, é provável que muitos executáveis no seu PATH sejam links simbólicos. Por exemplo, em sistemas como o debian / ubuntu:
Documentação
De
man chmod
:Exemplo
O shell tem um teste,
-x
para determinar se um arquivo é executável. Vamos tentar isso:Portanto, assim como você encontrou
which
, o shell não considera um executável de link programável a menos que o arquivo subjacente seja executável.Como funciona
Em um sistema Debian,
which
é um script de shell. A seção relevante do código é:Como você pode ver, ele usa o
-x
teste para determinar se um arquivo é executável.POSIX especifica o
-x
teste da seguinte maneira:Portanto, o POSIX verifica o que o nome do caminho resolve . Em outras palavras, ele aceita links simbólicos.
Função exec POSIX
A função exec POSIX segue links simbólicos. A especificação do POSIX continua detalhadamente para especificar as condições de erro que podem ser relatadas se os links simbólicos forem circulares ou muito profundos, como:
fonte
which
existe um shell script. Portanto, é provável que apenas usando o-x
teste que mostrei. De acordo com o POSIX,-x
testa se um arquivo "resolve" para um executável. Se você está vendo algo diferente, para onde está olhando?which
funciona, ou se é-x
ou algo mais. Estou interessado em saber onde não estou seguindo corretamente a documentação que citei.exec
segue links simbólicos. Isso parece deixar bem claro que os arquivos com links simbólicos podem ser executáveis no POSIX.man which
que diz "Ele não canoniza nomes de caminhos". Isso não significa que não segue os links. Isso significa apenas, como você observou, que não "canoniza" os nomes.Nesse caso, os links simbólicos são seguidos de forma transparente, sem canonizar o caminho final. Em outras palavras,
which
não se importa se/home/mark/bin
é um link simbólico ou não. O que importa é se o arquivo/home/mark/bin/foobar
existe ou não. Ele não precisa nivelar manualmente os links simbólicos ao longo do caminho - o sistema operacional pode fazer isso sozinho.E, de fato, quando
which
pergunta sobre as informações do arquivo/home/mark/bin/foobar
, o SO percebe/home/mark/bin
ser um link simbólico, o segue e encontra com êxitofoobar
no diretório de destino.Esse é o comportamento padrão, a menos que o programa use
open(…, O_NOFOLLOW)
oufstatat(…, AT_SYMLINK_NOFOLLOW)
acesse o arquivo.[comentários mesclados]
Enquanto você dizer que os utilitários de shell fazê-lo numa base caso-a-caso, não é o mesmo com syscalls kernel: todas as chamadas de arquivo relacionada com fazer seguir os links por padrão, a menos que o flag "nofollow" é dada. (Mesmo o lstat segue links simbólicos em todos os componentes do caminho, exceto o último.)
Quando a especificação não menciona explicitamente o que fazer com links simbólicos, isso implica que o comportamento padrão será usado. Ou seja, um shell que segue o algoritmo de caminho que os neithers resolvem os links simbólicos manualmente nem exclui explicitamente o SO do sistema operacional. (Apenas concatena cada componente $ PATH com o nome do executável.)
Quando a página do manual what (1) diz que não segue links simbólicos, pode significar várias coisas, mas a versão do coreutils do GNU diz o seguinte:
O escopo é muito mais restrito - significa apenas
which
que não tentará canonizar manualmente todos os caminhos para eliminar duplicatas, mas isso não implica que a ferramenta desative o link simbólico seguido pelo SO em geral. Por exemplo, se/bin
for um link simbólico para/usr/bin
, a execuçãowhich -a sh
retornará ambos/bin/sh
e/usr/bin/sh
.fonte
which
página de manual do GNU afirma de forma diferente: "O que considerará dois diretórios equivalentes diferentes quando um deles contém um caminho com um link simbólico".execve("/home/mark/bin/foobar", …)
, todos os links simbólicos são seguidos.execve
argumento, na verdade, na minha implementação, é aexecl()
mesma coisa. Por favor, se você incluir isso na sua resposta, eu aceito.O shell está em conformidade com sua documentação, pois segue as regras para a resolução do nome do caminho.
which
está de acordo com sua documentação. Os dois fazem coisas ligeiramente diferentes.A saída de
which
é o nome do arquivo e o caminho do link, não o caminho para o qual o link simbólico aponta. Isso está escrito na página de manual.Quando um comando é executado, o link é "seguido" de acordo com a Seção 4.13 resolução Pathname na mesma . A cláusula relevante para a execução de um arquivo é:
fonte