"command not found" para seus proprios scripts - PATH e chmod
O que voce vai aprender
- Por que apenas o seu script diz
command not found - Como diferenciar
command not founddePermission denied - Como seguir na ordem
./,chmod +x, PATH ehash -r
Resumo rapido
command not found significa que o shell nao encontrou esse comando no seu PATH. Para seus proprios scripts, corrija nesta ordem:
- Execute do diretorio atual com
./script.sh(um nome simples so busca no PATH) - Adicione o bit de execucao com
chmod +x script.sh - Adicione o diretorio ao PATH para uso diario (
~/binou~/.local/bin) - Limpe o cache de caminhos com
hash -rapos mover ou substituir o script
Premissas
- Shell: bash (o padrao no Ubuntu / Debian)
- Alvo: um script
.shque voce escreveu, ou um comando que voce compilou - zsh funciona da mesma forma; apenas detalhes como
hash -rdiferem
Por que apenas o meu script diz command not found?
Conclusao: O bash busca um nome de comando simples apenas nos diretorios listados no PATH. O diretorio atual nao esta no PATH por padrao, entao digitar
script.shnao encontra nada.
Quando voce digita script.sh, o bash resolve na seguinte ordem:
- Funcoes do shell, aliases e builtins
- Caminhos ja em cache no
hash - Os diretorios listados na variavel de ambiente
PATH(do inicio ao fim)
Se script.sh nao esta em nenhum dos diretorios do PATH, voce recebe command not found mesmo que o arquivo esteja bem na sua frente.
$ ls script.sh $ script.sh bash: script.sh: command not found
Deixar o diretorio atual (.) fora do PATH e um padrao de seguranca deliberado. Se . estivesse no inicio do PATH, um atacante poderia colocar um arquivo malicioso com nome de um comando real (ls) em um diretorio onde voce faz cd, e voce o executaria por acidente. Por isso um script "bem aqui" precisa ser nomeado explicitamente.
Qual a diferenca entre command not found e Permission denied?
Conclusao:
command not foundsignifica "nao localizado";Permission deniedsignifica "localizado, mas sem permissao de execucao." A mensagem indica qual caminho seguir.
Esses dois erros tem causas e correcoes diferentes.
| Mensagem | Significado | Correcao principal |
|---|---|---|
command not found |
Comando nao encontrado no PATH | Usar ./ / adicionar ao PATH |
Permission denied |
Arquivo existe mas sem bit de execucao | chmod +x |
bad interpreter |
Caminho shebang errado / terminacoes CRLF | Corrigir shebang / dos2unix |
# O caminho esta certo, mas nao ha permissao de execucao $ ./script.sh bash: ./script.sh: Permission denied
Se adicionar ./ muda o erro para Permission denied, o problema de PATH esta resolvido e a proxima questao sao permissoes. Se voce ve bad interpreter, o shebang ou terminacoes de linha estao com problema, entao leia Corrigindo "bad interpreter".
Execute com ./ primeiro
Conclusao: Execute um script no diretorio atual com
./script.sh. O./e um caminho explicito que pula a busca no PATH.
# NG: apenas o PATH e buscado, entao nao e encontrado $ script.sh bash: script.sh: command not found # OK: nomeie o arquivo no diretorio atual diretamente $ ./script.sh Hello
Se esta em outro lugar, use um caminho absoluto ou relativo.
$ /home/alice/tools/script.sh $ ~/tools/script.sh $ bash script.sh # passar ao bash funciona mesmo sem o bit de execucao
Passar o script para um interpretador (bash script.sh) o executa mesmo sem permissao de execucao. Isso e util para separar temporariamente um "problema de PATH" de um "problema de permissao."
O que acontece sem permissao de execucao?
Conclusao: Sem o bit de execucao,
./script.shpara comPermission denied. Conceda comchmod +x.
Scripts recem-criados, baixados ou copiados frequentemente perdem a permissao de execucao.
$ ls -l script.sh -rw-r--r-- 1 alice alice 42 Jun 6 10:00 script.sh $ ./script.sh bash: ./script.sh: Permission denied
-rw-r--r-- nao tem x (bit de execucao). Adicione.
$ chmod +x script.sh $ ls -l script.sh -rwxr-xr-x 1 alice alice 42 Jun 6 10:00 script.sh $ ./script.sh Hello
chmod 777 e desnecessario e perigoso. Se voce so precisa executar o arquivo, chmod +x (ou chmod 755) e suficiente. Torna-lo gravavel por todos com 777 e um risco de seguranca.
Como adicionar meu diretorio ao PATH?
Conclusao: Para evitar digitar
./toda vez, adicione o diretorio do seu script aoPATH. Coloqueexport PATHno~/.bashrcpara tornar permanente.
Primeiro, verifique o PATH atual.
$ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
Adicione o diretorio onde voce guarda seus scripts (por exemplo ~/bin).
# Apenas para esta sessao (shell atual) $ export PATH="$HOME/bin:$PATH"
Para tornar permanente, adicione ao final de ~/.bashrc (ou ~/.profile para login shells).
# Adicionar ao final de ~/.bashrc export PATH="$HOME/bin:$PATH"
# Recarregar no shell atual $ source ~/.bashrc $ which script.sh /home/alice/bin/script.sh $ script.sh # executa sem ./ Hello
~/bin e ~/.local/bin
O ~/.profile padrao do Ubuntu adiciona ~/bin e ~/.local/bin ao PATH no login se eles existirem. Coloque seus scripts em qualquer um dos dois e o PATH geralmente funciona sem configuracao extra (pode ser necessario fazer login novamente para que tenha efeito).
Entradas do PATH sao separadas por :, e a posicao define a prioridade. Com $HOME/bin:$PATH seu script vence; com $PATH:$HOME/bin comandos existentes vencem. Para evitar sobrescrever acidentalmente um comando do sistema com o mesmo nome, adicione no final.
Ainda nao encontra, ou pega o binario antigo?
Conclusao: O bash armazena em cache o caminho de um comando uma vez que o encontra (
hash). Logo apos mover ou substituir um script, ele pode usar o caminho antigo. Limpe o cache comhash -r.
Quando PATH e permissoes parecem corretos mas o comportamento esta errado, use type para ver o que o bash realmente pretende executar e de onde.
$ type -a script.sh script.sh is /home/alice/bin/script.sh
Se type aponta para um local antigo, ou um comando que voce excluiu ainda executa, o cache esta desatualizado.
# Limpar caminhos de comandos em cache $ hash -r # Verificar novamente $ type -a script.sh
which busca no PATH no sistema de arquivos, mas type reporta como o bash realmente resolve o nome, incluindo aliases, funcoes, builtins e o cache hash. Para diagnostico, type -a e a escolha confiavel.