ssh는 (셸 자체가 아닌) 로그인 셸에서 명령을 실행합니까?

ssh는 (셸 자체가 아닌) 로그인 셸에서 명령을 실행합니까?

에 따르면 man sshd:

 LOGIN PROCESS
      When a user successfully logs in, sshd does the following:

      <...>

            9.   Runs user's shell or command.  All commands are run under the
                 user's login shell as specified in the system password data‐
                 base.

그러나 "사용자의 로그인 셸에서 실행"이 문자 그대로 bash -l"? 에서와 같이 로그인 셸을 의미하는지 확실하지 않습니다. 내 실험에 따르면 그렇지 않습니다.

$ ssh u@h shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'
Not login shell

왜 이런 일이 일어나는지 이해가 안 되나요? 이로 인해 실행 중인 명령이 셸에 로그인하는 것과 같은 일반적인 환경을 얻지 못하게 됩니다. 이것은 번거로운 일입니다.

답변1

로그인 쉘이 경우 두 가지 다른 의미를 가질 수 있습니다.

  1. 계정 데이터베이스에서 사용자의 로그인 셸로 정의된 셸입니다.

    예를 들어:

    $ getent passwd stephane
    stephane:*:1000:1000:Stephane Chazelas:/home/stephane:/bin/zsh
    

    /bin/zsh내 로그인 쉘이며 계정 데이터베이스 에 입력한 7번째 필드입니다 . 일부 다른 사용자는 /bin/tcsh,,,,...을 (를) 가질 수 있습니다./bin/fish/bin/bash/sbin/nologin/bin/false

  2. 일반적으로 로그인/sshd에 의해 수행되는 로그인 세션을 초기화하는 데 사용되는 쉘 호출입니다. 접두사를 붙이고 argv[0]( -일부 쉘은 -l또는 --login옵션도 허용함) 쉘이 , 등과 같은 일부 세션 초기화 파일을 해석하도록 지시 .profile합니다 ..login.zlogin

어쨌든 shin ssh껍데기이전 sshd과 마찬가지로 rshd클라이언트가 보낸 코드(있는 경우)를 해석하기 위해 항상 쉘이 호출됩니다.

실행하는 경우:

ssh user@host foo    bar

여기서 foobar인수는 에 전달되고 ssh공백 ssh으로 연결되어 foo bar쉘 코드를 서버로 보냅니다.

서버가 host실행됩니다로그인 쉘3가지 매개변수 가 있습니다 user:

  1. 로그인 쉘의 기본 이름입니다. 나로서는zsh
  2. -c
  3. 고객이 제공한 코드: foo bar이 예에서는

쉘은 이를 자체 구문의 코드로 해석하며 실행되지 않습니다.~처럼로그인 쉘 argv[0]이 아닌 -.

만약에아니요매개변수는 클라이언트를 호출할 때와 마찬가지로 클라이언트에 전달됩니다.

ssh user@host

그런 다음 해당 모드로 들어가고( rlogin명령이 전달되지 않을 때 rsh실행하는 모드와 마찬가지로) rlogin 의사 tty와 단 하나의 인수( )를 사용하여 sshd사용자의 로그인 셸을 실행합니다 .argv[0]

  1. -제 경우에는 로그인 셸의 기본 이름 앞에 -zsh.

이는 로그인 쉘로 실행 중이며 .zprofile // 를 읽을 것임을 쉘에 알려줍니다 .profile..login

결론적으로:

  • ssh host shell-codersh host shell-code원격 사용자의 로그인 쉘이 일부 코드를 구문 분석하도록 하여 원격으로 명령을 실행하는 것과 같습니다 .
  • ssh host와 유사하며 rlogin host, 가상 터미널에서 로그인 쉘 모드로 로그인 쉘을 시작하여 원격으로 로그인합니다.

1 이 매우 간단한 경우 모든 쉘은 로그인 쉘 사용을 선호하는 사용자를 제외 /bin/false하고는 코드를 동일하게 해석 하지만 더 복잡한 쉘의 경우 몇 가지 변경 사항이 있습니다. 당신은 또한 볼 수 있습니다/sbin/nologin/usr/bin/python3원격 사용자의 로그인 셸을 모르고 SSH를 통해 임의의 간단한 명령을 어떻게 실행할 수 있습니까?

답변2

아니요, SSH는 명령을 실행할 때가 아니라 셸에 로그인할 때만 로그인 셸을 호출합니다. 즉, 로그인 초기화 파일을 실행하려면(예 ~/.profile: ) 이를 명시적으로 수행해야 합니다. 이는 의도적인 디자인 선택이었습니다. 대부분의 로그인이 텍스트 터미널에 이루어졌던 시절에는 많은 사용자가 .profile대화형 세션에 로그인했을 때만 의미가 있는 명령을 그곳에서 실행했습니다. (요즘에는 대부분의 사람들이 그래픽 세션에 로컬로 로그인하기 때문에 이것은 덜 일반적입니다.) 이메일을 받기 위해 Emacs를 빠르게 실행하고 모뎀을 켜는 것을 원하지는 않습니다 ssh example.com ls!rsync example.com:somefile .


SSH의 명령은 명령줄 인수를 중간 공백과 연결하여 얻은 문자열입니다. 예를 들어, ssh u@h shopt -q login_shell명령을 실행하십시오 shopt -q login_shell. ssh u@h 'shopt -q login_shell', 또는 ssh u@h 'shopt -q' login_shell등과 완전히 동일합니다 .

SSH는 이 문자열을 사용자의 로그인 셸에 전달합니다. SSH는 다른 쉘에 대해 알지 못합니다. 서버는 Unix가 아닌 시스템에서 실행 중이거나 또는 sh이라는 프로그램이 없는 제한된 환경 에서 실행 중일 수 있습니다 bash.

SSH 서버는 사용자 데이터베이스에 나열된 실행 파일을 사용자의 로그인 셸로 실행하지만 반드시 로그인 셸로 실행할 필요는 없습니다. 명령줄이 비어 있지 않으면 세 개의 인수 목록이 전달됩니다.

  • argv[0]일반적인 규칙을 따르는 프로그램의 기본 이름입니다.
  • argv[1]문자열입니다 -c.
  • argv[2]클라이언트가 전달한 명령입니다.

빈 명령줄의 경우 SSH 서버는 사용자의 로그인 셸을 호출합니다.로그인 쉘로. 이는 매개변수가 하나만 있는 목록을 의미합니다.

  • argv[0]대시( -) 뒤에 프로그램의 기본 이름이 옵니다.

ssh localhost 'cat /proc/$$/cmdline | tr \\0 \\n'예를 들어 다음은 Linux 시스템의 출력입니다.

sh
-c
cat /proc/$$/cmdline | tr \\0 \\n

로그인 쉘의 경우 로그인 쉘 자체가 다른 프로그램을 실행하는 경우가 많기 때문에 이를 관찰하기가 더 어렵습니다. 무슨 일이 일어나고 있는지 확인하는 쉬운 방법은 로그인 셸의 초기화 파일을 일시적으로 비활성화하는 것입니다. 예를 들어 일시적으로 이름을 바꾸 ~/.profile거나 사용 중인 셸에 따라 , 등으로 변경합니다 ~/.bash_profile. 다음은 계정을 로그인 셸로 ~/.zprofile사용하는 예입니다 ./bin/sh

$ mv ~/.profile ~/not.profile
$ ssh localhost
(/etc/motd content goes here)
Last login: Mon Apr 24 18:00:30 2023
$ cat /proc/$$/cmdline; echo
-sh
$ exit
Connection to localhost closed.
$ mv ~/not.profile ~/.profile

관련 정보