"command not found" para seus próprios scripts - PATH e chmod

"command not found" para seus próprios scripts - PATH e chmod

O que você vai aprender

  • Por que apenas o seu script diz command not found
  • Como diferenciar command not found de Permission denied
  • Como seguir na ordem ./, chmod +x, PATH e hash -r

Resumo rápido

command not found significa que o shell não encontrou esse comando no seu PATH. Para seus próprios scripts, corrija nesta ordem:

  1. Execute do diretório atual com ./script.sh (um nome simples só busca no PATH)
  2. Adicione o bit de execução com chmod +x script.sh
  3. Adicione o diretório ao PATH para uso diário (~/bin ou ~/.local/bin)
  4. Limpe o cache de caminhos com hash -r após mover ou substituir o script

Premissas

  • Shell: bash (o padrão no Ubuntu / Debian)
  • Alvo: um script .sh que você escreveu, ou um comando que você compilou
  • zsh funciona da mesma forma; apenas detalhes como hash -r diferem

Por que apenas o meu script diz command not found?

Conclusão: O bash busca um nome de comando simples apenas nos diretórios listados no PATH. O diretório atual não está no PATH por padrão, então digitar script.sh não encontra nada.

Quando você digita script.sh, o bash resolve na seguinte ordem:

  1. Funções do shell, aliases e builtins
  2. Caminhos já em cache no hash
  3. Os diretórios listados na variável de ambiente PATH (do início ao fim)

Se script.sh não está em nenhum dos diretórios do PATH, você 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 diretório atual (.) fora do PATH é um padrão de segurança deliberado. Se . estivesse no início do PATH, um atacante poderia colocar um arquivo malicioso com nome de um comando real (ls) em um diretório onde você faz cd, e você o executaria por acidente. Por isso um script "bem aqui" precisa ser nomeado explicitamente.

Qual a diferença entre command not found e Permission denied?

Conclusão: command not found significa "não localizado"; Permission denied significa "localizado, mas sem permissão de execução." A mensagem indica qual caminho seguir.

Esses dois erros têm causas e correções diferentes.

Mensagem Significado Correção principal
command not found Comando não encontrado no PATH Usar ./ / adicionar ao PATH
Permission denied Arquivo existe mas sem bit de execução chmod +x
bad interpreter Caminho shebang errado / terminações 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 está resolvido e a próxima questão são permissões. Se você vê bad interpreter, o shebang ou terminações de linha estão com problema, então leia Corrigindo "bad interpreter".

Execute com ./ primeiro

Conclusão: Execute um script no diretório atual com ./script.sh. O ./ é um caminho explícito 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 está 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 permissão de execução. Isso é útil para separar temporariamente um "problema de PATH" de um "problema de permissão."

O que acontece sem permissão de execução?

Conclusão: Sem o bit de execução, ./script.sh para com Permission denied. Conceda com chmod +x.

Scripts recem-criados, baixados ou copiados frequentemente perdem a permissão de execução.

$ 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-- não tem x (bit de execução). 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 é desnecessário e perigoso. Se você só precisa executar o arquivo, chmod +x (ou chmod 755) é suficiente. Torná-lo gravável por todos com 777 é um risco de segurança.

Como adicionar meu diretório ao PATH?

Conclusão: Para evitar digitar ./ toda vez, adicione o diretório do seu script ao PATH. Coloque export PATH no ~/.bashrc para tornar permanente.

Primeiro, verifique o PATH atual.

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin

Adicione o diretório onde você 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 padrão 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 configuração extra (pode ser necessário fazer login novamente para que tenha efeito).

Entradas do PATH são separadas por :, e a posição 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 não encontra, ou pega o binário antigo?

Conclusão: O bash armazena em cache o caminho de um comando uma vez que o encontra (hash). Logo após mover ou substituir um script, ele pode usar o caminho antigo. Limpe o cache com hash -r.

Quando PATH e permissões parecem corretos mas o comportamento está 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 você excluiu ainda executa, o cache está 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, funções, builtins e o cache hash. Para diagnóstico, type -a é a escolha confiável.

Checklist

Conclusão: Siga "executar com ./ -> chmod +x -> adicionar ao PATH -> hash -r" e você resolverá quase todo command not found dos seus próprios scripts.

Siga de cima para baixo.

  • [ ] Execute scripts no diretório atual como ./script.sh
  • [ ] Verifique o bit de execução (x) com ls -l; adicione com chmod +x se faltar
  • [ ] Permission denied significa problema de permissão, não de PATH
  • [ ] Para uso diário, coloque scripts em ~/bin / ~/.local/bin ou adicione export PATH ao ~/.bashrc
  • [ ] Confirme que o diretório aparece em echo $PATH
  • [ ] Se o comportamento estiver estranho após mover/substituir, limpe o cache com hash -r
  • [ ] Confirme o alvo real com type -a script.sh

Próximas leituras: