Por que o Bash não conseguiu encontrar o comando, mesmo que $ PATH esteja especificado corretamente?

9

Estou especificando o caminho para o meu comando no arquivo / etc / profile :

export PATH=$PATH:/usr/app/cpn/bin

Meu comando está localizado em:

$ which ydisplay 
/usr/app/cpn/bin/ydisplay

Então, quando eu executo a saída "echo $ PATH", é semelhante a:

$ echo $PATH
...:/usr/app/cpn/bin

E está tudo bem, mas quando estou tentando iniciar meu comando via SSH, estou recebendo um erro:

$ ssh 127.0.0.1 ydisplay
$ bash: ydisplay: command not found

Mas o meu caminho ainda está presente:

$ ssh 127.0.0.1 echo $PATH
...:/usr/app/cpn/bin

Explique-me por que o Bash não conseguiu encontrar o ydisplay durante a sessão SSH e como configurar o SSH corretamente para evitar esse problema.

Além disso, se eu especificar $ PATH no arquivo local .bashrc no usuário atual, tudo funcionará corretamente. Mas quero modificar apenas um arquivo, especificando muitos arquivos para cada usuário. É por isso que estou perguntando.

SIGSEGV
fonte
11
apenas executando o ydisplaytrabalho? faz ssh 127.0.0.1 /usr/app/cpn/bin/ydisplayo trabalho?
Bananguin
@ user1129682 Sim, o ydisplay com o nome completo especificado funciona e o ydisplay funciona #
SIGSEGV
Quando você não está logado (não possui uma sessão remota), mas apenas envia um comando remotamente, não tem acesso a variáveis ​​de ambiente da mesma maneira, porque seus arquivos .bashrc / .profile não são executados. É por esse motivo que eles são responsáveis ​​por definir variáveis ​​para a sessão atual.
Mnmnc 23/08/12
14
Apenas uma observação: ssh 127.0.0.1 echo $PATHnão faz o que você pensa que faz: o shell expande $ PATH antes que o ssh seja executado, para que não prove ou refute nada.
Ulrich Schwarz
2
esta pergunta stackoverflow pode ser de alguma ajuda
BSD

Respostas:

5

tl; dr

Executando ssh 127.0.0.1 ydisplayfontes em ~/.bashrcvez de /etc/profile. Mude seu caminho em ~/.bashrcvez disso.

detalhes

A única vez que /etc/profilese lê é quando seu shell é um "shell de login".

No Manual de Referência do Bash :

Quando o bash é chamado como um shell de login, ... ele primeiro lê e executa comandos do arquivo / etc / profile

Mas quando você executa ssh 127.0.0.1 ydisplay, bashnão é iniciado como um shell de logon. No entanto, ele lê um arquivo de inicialização diferente. O Manual de Referência do Bash diz:

quando ... executado por ... sshd. ... lê e executa comandos de~/.bashrc

Então você deve colocar suas PATHconfigurações ~/.bashrc.

Na maioria dos sistemas, ~/.bash_profilefontes ~/.bashrc, para que você possa colocar suas configurações apenas em ~/.bashrcvez de colocá-las nos dois arquivos.

Não há nenhuma maneira padrão para alterar a configuração para todos os usuários, mas a maioria dos sistemas têm um /etc/bashrc, /etc/bash.bashrcou similar.

Caso contrário, configure pam_enve insira a PATHconfiguração /etc/environment.

Veja também:

Mikel
fonte
1

Historicamente, os arquivos de perfil ( /etc/profilee ~/.profile) eram chamados quando você fazia login (no console de texto, o que mais?) E serviam a muitos propósitos:

  • Defina variáveis ​​de ambiente e outros parâmetros (por exemplo, umask) para a sessão.
  • Execute programas extras no início da sessão (por exemplo, notificação por email).
  • Execute o programa para a sessão, se diferente do shell (por exemplo, outro shell ou X Window).
  • Defina os parâmetros do terminal (por exemplo stty).
  • Defina os parâmetros do shell (por exemplo, aliases).

Todos esses propósitos não foram identificados como separados até mais tarde. Como os scripts de perfil podem fazer coisas que só fazem sentido em uma sessão interativa (interação do terminal, iniciar outros programas), quando a chamada de shell remoto ( rsh ) foi introduzida, as marcas do rsh decidiram não chamar o shell remoto como um shell de logon, para que os scripts de perfil não sejam executados. (Algumas versões do rshdtêm a opção de executar o shell remoto como um shell de logon.) O Ssh copiou esse comportamento para substituir o rsh.

Se você deseja que seus scripts de perfil sejam executados, é possível invocá-los explicitamente.

ssh 127.0.0.1 '. /etc/profile; . ~/.profile; ydisplay'

Observe o comando .para carregar os scripts de perfil dentro do shell: eles são comandos a serem executados dentro desse shell, não um programa externo.

Se você deseja definir uma variável de ambiente globalmente para todos os usuários, existe outro método em muitos sistemas: em vez de defini-lo /etc/profile, defina-o /etc/environment. Este arquivo é lido através do pam_envmódulo; a maioria das distribuições Linux é configurada para lê-lo.

Se o seu shell de login for bash, há uma possibilidade adicional. Normalmente, você não deve definir variáveis ​​de ambiente.bashrc (porque elas não serão definidas nas sessões X, exceto se você passar por um terminal com um shell interativo, porque elas não serão definidas se você efetuar logon interativamente em um console de texto ou por um ssh, porque eles substituirão as configurações personalizadas se você chamar um shell dentro de outro programa). No entanto, o bash tem um recurso estranho que eu nunca entendi: ele lê ~/.bashrcem duas circunstâncias não relacionadas:

  • em shells interativos que não são shells de login;
  • em shells não interativos que não são shells de logon, se o bash achar que foi invocado por rshdou sshd.

Quando você executa um comando sobre ssh, está no segundo caso. Você pode organizar a leitura do seu perfil lendo /etc/profilee a .profilepartir de .bashrc. Inclua o seguinte código no seu ~/.bashrc:

case $- in
  *i*) :;; # this is an interactive shell, fine
  *) # This is not an interactive shell! This must be a non-interactive remote shell session.
    . /etc/profile; . ~/.profile
    return;;
esac
Gilles 'SO- parar de ser mau'
fonte