저는 쉘 스크립팅에 비교적 익숙하지 않기 때문에 이것이 간단한 질문처럼 보이면 사과드립니다. 나는 debian, version 11 (bullseye)
SSH를 통해( )에 연결할 수 있는 Linux VM( )을 가지고 ssh <ip>
있으며 일부 종속성(homebrew, pyenv 등)을 설치하여 성공적으로 사용할 수 있습니다. 그러나 VM 외부(스크립트 또는 Mac 터미널 사용)에서 명령을 실행하려고 하면 관련 오류가 ssh <user>@<ip> pyenv versions
발생합니다 .bash: line 1: pyenv: command not found
설명했던 내용과 관련이 있을 것 같아요여기, 하지만 이 문제를 어떻게 피할 수 있는지 잘 모르겠습니다.
아래 댓글에 @terdon이 요청한 추가 세부 정보를 추가하세요.
$ which pyenv
/home/linuxbrew/.linuxbrew/bin/pyenv
$ grep /home/linuxbrew/.linuxbrew/bin/ ~/.bashrc ~/.bash_profile ~/.profile /etc/bash.bashrc /etc/profile
grep: /home/f0p021s/.bash_profile: No such file or directory
/home/f0p021s/.profile:eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
또한 가상 머신 내에서 경로를 보면 다음과 같다는 것도 깨달았습니다.
$ echo $PATH
/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
로컬 컴퓨터에서 비슷한 명령을 실행하려고 하면 다르게 보입니다.
$ ssh <user>@<ip> 'echo $PATH'
/usr/local/bin:/usr/bin:/bin:/usr/games
답변1
컴퓨터에 SSH로 접속하면 대화형 로그인 셸이 시작됩니다. 를 실행하면 ssh ip command
비대화형, 비로그인 셸이 시작됩니다.
$ ssh localhost 'echo $- $0; shopt login_shell'
hBc bash
login_shell off
$ ssh localhost
[terdon@tpad ~]$ echo $- $0; shopt login_shell
himBHs -bash
login_shell on
바라보다이 답변이것이 실제로 무엇을 보여주는지 자세히 알아보세요.
각 유형의 셸은 시작될 때 서로 다른 파일을 읽습니다. man bash
(강조 내) 에서 :
bash를 다음과 같이 사용할 때대화형 로그인 셸또는 --login 옵션을 사용하여 먼저 파일에서 읽고 명령을 실행하는 비대화형 셸로 사용/etc/구성 파일, 파일이 존재하는 경우. 파일을 읽은 후 찾습니다.~/.bash_profile, ~/.bash_login, ~/.profile 순서대로, 첫 번째 기존 및 읽기 가능한 명령에서 명령을 읽고 실행합니다. 이 동작은 셸을 시작할 때 --noprofile 옵션을 사용하여 비활성화할 수 있습니다.
예를 들어, bash가 비대화형으로 시작될 때 쉘 스크립트를 실행하려면 환경에서 BASH_ENV 변수를 찾고 해당 값이 있는 경우 확장한 다음 확장된 값을 읽고 실행할 파일 이름으로 사용합니다. Bash는 다음 명령이 실행된 것처럼 동작합니다.
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
그러나 PATH 변수의 값은 파일 이름을 검색하는 데 사용되지 않습니다.
이제 명령이 in pyenv
에 추가되었음을 보여주었습니다 . 위에서 볼 수 있듯이 파일( )은 대화형 로그인 쉘에서 읽혀지지만 비대화형 또는 비로그인 쉘에서는 읽히지 않습니다. 왜냐하면 이러한 파일은 지정된 내용만 읽고 기본적으로 비어 있기 때문입니다.$PATH
/home/f0p021s/.profile
~/.profile
$BASH_ENV
따라서 귀하의 옵션은 다음과 같습니다.
명령의 전체 경로를 사용하십시오.
ssh ip /home/linuxbrew/.linuxbrew/bin/pyenv
원천
~/.profile
:ssh ip '. ~/.profile; pyenv'
답변2
귀하의 진단이 정확할 수도 있습니다.
이 문제를 방지하려면 어떤 rcfile이 있는지 확인해야 합니다.아니요인용한 답변의 스크립트에서 시작 시 실행됩니다(아마도 PATH를 설정하는 스크립트일 것입니다).
~/.bashrc
그런 다음 재정의하여 문제를 방지 할 수 있습니다 .
또는 다음 명령을 변경해 볼 수도 있습니다.
ssh <user>@<ip> '. /etc/profile; pyenv versions'.
/etc/profile
이는 현재 실행 중인 셸로 가져옵니다 . 를 가져 /etc/bashrc
오거나 ~/.profile
바꾸 거나 점을 찍어야 할 수도 있습니다 /etc/profile
(점과 파일 이름 사이에 공백이 있고 전체 명령이 인용되어 있음에 유의하세요).
테스트(우분투에서)
편리한 가상 머신에 로그인하세요:
leonardo@aladdin:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/opt/android-sdk-linux/platform-tools:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin
leonardo@aladdin:~$ logout
이제 SSH를 직접 사용해 보십시오.
$ ssh leonardo@aladdin "echo \$PATH"
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
좋아요 그래서, 다른 길. 예를 들어, java-8-oracle은 어디에서 왔습니까?로그인 쉘에 있을 때만 존재하는 PATH의 긴 문자열을 사용하여 유사한 검사를 수행합니다..
가상 머신의 루트로서 PATH 할당 후 어디에서나 해당 문자열을 찾습니다 /etc
(작동하지 않으면 기본 도트 파일을 지정하여 다시 시도합니다 /home/.*
).
# grep -r PATH.*java-8-oracle /etc
/etc/profile.d/jdk.csh:setenv PATH ${PATH}:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin
/etc/profile.d/jdk.sh:export PATH=$PATH:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin
PATH 할당이 바로 거기에 있습니다.
"/etc/profile.d"의 파일에서 가져옵니다. 이제 몇 가지 상식이 필요합니다. "whatever.d" 폴더는 일반적으로 다음 위치에서 생성됩니다.어느바이너리 파일과 그 내용은 순서대로 와일드카드로 표시됩니다.
따라서 폴더가 이면 /etc/profile.d
이 트릭을 구현하고 싶습니다 /etc/profile
. 어쨌든, 내가 찾을 수 있도록 누군가 "profile.d"에 개입해야 합니다.저것:
# grep -r "profile\.d" /etc
실제로 몇 줄의 출력에서 발견했습니다.
/etc/bash_completion.d/libreoffice.sh:# It is based on /etc/profile.d/complete.bash from SUSE Linux 10.1
/etc/profile:if [ -d /etc/profile.d ]; then
/etc/profile: for i in /etc/profile.d/*.sh; do
/etc/apparmor.d/snap/abstractions/bash: /etc/profile.dos r,
...
두 번째와 세 번째 줄이 제가 관심을 갖는 부분입니다. 그들은 "/etc/profile.d라는 폴더가 있다면, 그 폴더에 있는 ".sh"로 끝나는 모든 파일에 대해..."라고 말합니다. 이것은정확히이것이 내가 기대했던 것입니다.
그래서 나는 달리기를 믿을 수 있습니다 /etc/profile
.
그것은 작동합니다 :
ssh leonardo@aladdin ". /etc/profile; echo \$PATH"
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/opt/android-sdk-linux/platform-tools:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin