.NET을 통해 원격 컴퓨터에서 스크립트 중 하나를 실행하려고 ssh
하면 이상한 동작이 발생합니다 .
$PATH
내 .profile 에 스크립트 디렉터리 경로를 추가했습니다 . 그러나 실행하면 ssh kalle@Raspi foo
"명령을 찾을 수 없습니다"라는 메시지가 나타납니다.
ssh kalle@Raspi 'echo $PATH'
기본값이 주어지고 .profile에서 설정하고 내보낸 변수를 사용하면 출력이 비어 있습니다.
.profile에 하나를 넣었 echo foo
더니 당연히 인쇄되었습니다. 그런 다음 첫 번째 줄을 입력하면 set -vx
줄이 이상한 순서로 인쇄됩니다. 예를 들어 "+echo foo" 앞에 "foo"가 인쇄됩니다.
무슨 일인지 알아낼 수 있는 사람 있나요?
편집하다:
이렇게 하면 ssh kalle@Raspi 'bash -lc "echo \$PATH"'
전체 경로를 얻게 됩니다.
편집 2:
혼란을 드려 죄송합니다. 원격 스크립트를 실행하려고 할 때 매우 피곤했고 지금은 기억이 틀렸는데 지금은 무엇을 했는지 기억이 납니다.
사용해 본 후 bash -lc
명령만 사용해도 작동하지 않았는데 백슬래시가 빠졌네요! 따라서 ssh kalle@Raspi 'bash -lc "echo $PATH"'
평소와 같이 명령 문자열을 다른 명령에 제공하면 쉘은 해당 명령 문자열에 대해 다양한 확장을 수행합니다.
따라서 따옴표를 제거한 후 bash -lc "echo $PATH"
이를 단일 매개변수로 전달 ssh
하고 쉘이 매개변수 대체를 수행하는 원격 시스템에서 실행합니다. 즉, $PATH
기본 경로로 바꿉니다.앞으로로 전달되어 bash -lc
후자를 쓸모없게 만듭니다.
그러다가 멍청 하게 을 사용하고 있다는 사실 bash -lc
을 잊어버리고 .ssh kalle@Raspi foo
.profile
echo
.profile
정말 부끄러운 일입니다. 이 질문을 작성할 때 백슬래시를 사용하여 변수를 보호해야 한다는 것이 나에게는 전혀 당연하다고 느꼈기 때문에 피곤했을 것입니다. 그러나 나는 지금 깨달은 것을 아직도 깨닫지 못했습니다.
따라서 이 동작은 매우 명백하고 절대적으로 정상이지만 문제는 여전히 존재합니다.
bash -lc
상황에 따라 인용 및 이스케이프가 번거로울 수 있는 해결 방법을 사용할 수도 있고 , . .profile
실제 명령 앞에 넣을 수도 있습니다.
더 우아한 솔루션을 아는 사람이 있습니까? 서버에서 조정할 수 있는 것이 있습니까 ssh kalle@Raspi foo
?
답변1
@ilkkachu 덕분에 해결책을 찾았습니다.
변수 내용 을 .profile
..profile
그런 다음 "대화형으로 실행되지 않으면 아무 작업도 수행하지 않음" 부분을 .bashrc
다음과 같이 수정했습니다.
case $- in
*i*) ;;
*)
# Not running interactively.
# Check if we are the server of an SSH connection without a PTY.
# If so, sshd is about to execute a command issued by some client,
# in which case this script has been invoked directly by sshd, not
# by .profile, so we need to set vars that are normally set in .profile
# and that are important for my scripts (like $PATH) here before returning.
# This way, I can call my scripts just via ‘ssh kalle@Raspi foo’ without
# using ‘bash -lc’.
#
# References:
# https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html
# https://man.openbsd.org/ssh#ENVIRONMENT
[[ $SSH_CONNECTION && -z $SSH_TTY ]] && . $HOME/scripts/bashrc-include/set-vars.sh
return;;
esac
편집하다:
전혀 중요하지 않은 것은 아닙니다. 효과가 있고 부작용이 없다는 것이 입증되었습니다.
echo
and 앞에는 es를, top 뒤에는 es를 붙였습니다 ..profile
.bashrc
set-vars.sh
echo
case ... in ... esac
나는 모든 기계에서 동일한 것을 사용한다는 것을 언급해야 한다 .profile
..bashrc
이제 테스트해 보겠습니다.
이 글을 쓰고 있는 컴퓨터에서 터미널을 열면 다음과 같은 결과가 나타납니다.
.profile: Started.
set-vars.sh: Setting vars.
.bashrc: Started.
.bashrc: Interactive shell, proceeding.
Raspi에 SSH를 연결하면 똑같은 결과가 나타납니다.
발행하면 ssh kalle@Raspi 'echo $PATH'
다음을 얻습니다.
.bashrc: Started.
set-vars.sh: Setting vars.
그리고 정확합니다 $PATH
.
편집 2:
메시지 열기 및 닫기를 위한 작은 스크립트:
#!/bin/bash
# Author: derkallevombau
# Created 2023-04-07 12:58:48
if [[ $1 =~ ^on|1|true$ ]]; then
sedScript='"s/^#([\t ]*echo $(basename $f):.*)/\1/"'
elif [[ $1 =~ ^off|0|false$ ]]; then
sedScript='"s/^([\t ]*echo $(basename $f):.*)/#\1/"'
else
cat <<-END
Unknown argument: '$1'.
Invocation: bash-startup-messages-set (on|1|true)|(off|0|false)
END
exit
fi
for f in ~/.{profile,bashrc} /home/kalle/scripts/bashrc-include/set-vars.sh; do
eval sed -Ei $sedScript $f
done