SSH를 통해 명령을 실행할 때 .profile에 변수가 없습니다.

SSH를 통해 명령을 실행할 때 .profile에 변수가 없습니다.

.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.profileecho.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

편집하다:

전혀 중요하지 않은 것은 아닙니다. 효과가 있고 부작용이 없다는 것이 입증되었습니다.

echoand 앞에는 es를, top 뒤에는 es를 붙였습니다 ..profile.bashrcset-vars.shechocase ... 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

관련 정보