SSH를 통해 `cd` 명령이 작동하지 않는 이유는 무엇입니까?

SSH를 통해 `cd` 명령이 작동하지 않는 이유는 무엇입니까?

SSH를 통해 일부 파일을 백업하려고 하는데 tar원하는 파일을 백업하는 대신 홈 폴더가 백업됩니다. 나는 몇 가지 추가 테스트를 수행했으며 결과는 다음과 같습니다.

ssh root@server /bin/sh -c "cd /boot && ls -l"

놀랍게도 파일이 나열되었습니다./root아니요 /boot. 그러나 /bin/sh터미널에서 전체 명령을 실행 하면 cd올바르게 작동하고 /boot파일이 인쇄됩니다.

여기서 무슨 일이 일어나고 있는 걸까요?

답변1

ssh에서는 원격 호스트의 execvp에 전달될 일련의 인수만큼 정확하게 명령을 지정할 수 없습니다. 대신 모든 인수를 문자열로 연결하고 원격 셸을 통해 실행합니다. 제 생각에는 이것은 ssh의 주요 설계 결함입니다. 대부분의 측면에서 잘 작동하는 유닉스 도구이지만 명령을 지정할 때가 되면 argv 대신 단일 단일 문자열을 사용하도록 선택합니다. MSDOS용으로 설계되었습니다!

ssh는 명령을 단일 문자열로 전달하므로 sh -c직접 제공할 필요가 없습니다 sh -c.

sh -c '/bin/sh -c cd /boot && ls -l'

원본 참조가 손실됩니다. 따라서 구분 기호가 있는 명령은 다음 &&과 같습니다.

`/bin/sh -c cd /boot`
`ls -l`

$0첫 번째는 명령 텍스트 "cd" 및 = 를 사용하여 셸을 실행합니다 "boot". "cd" 명령은 성공적으로 완료되고 중요하지 않으며 $0성공 /bin/sh -c을 표시한 다음 ls -l발생합니다.

답변2

인용 문제입니다. ssh는 쉘에 전달한 명령을 실행했습니다. 여러 인수를 전달하면 공백으로 연결되어 문자열을 구성합니다. 따라서 원격으로 실행하는 원격 명령은 /bin/sh -c cd /boot && ls -l(명령의 따옴표가 로컬 쉘에 의해 해석되므로 따옴표가 없습니다)입니다.

/bin/sh -c cd /boot실행 /bin/sh하고 명령을 실행 cd하고 $0로 설정하도록 지시합니다 /boot. 완료되면 상위 셸( 에서 시작한 셸 sshd)이 실행됩니다 ls -l.

귀하의 경우 sh -c원격 쉘( /etc/passwd또는 다른 비밀번호 데이터베이스와 같이)이 이 명령을 이해하지 못하는 한 이를 제거하는 것은 완전히 쓸모가 없습니다.

ssh root@server "cd /boot && ls -l"

다른 쉘을 호출해야 하는 경우 원격 명령을 인용하여 호출하는 원격 쉘에 의해 확장되는 것을 방지해야 합니다 sshd. 예를 들어 로그인 셸이 대시이고 bash 명령을 실행하려는 경우:

ssh root@server 'bash -c "cd ~bob && ls -l"'

답변3

나는 이것이 쉘이 옵션을 구문 분석하는 방법과 더 관련이 있다고 생각합니다. 예를 들어 다음과 같이 작동합니다.

$ ssh root@server /bin/sh -c '"cd /boot && ls -l"'

이것은 귀하의 명령과 동일한 문제가 있습니다.

$ ssh root@server /bin/sh -c 'cd /boot && ls -l'

-v스위치를 활성화하면 ssh어떤 일이 발생하는지 확인할 수 있습니다.

첫 번째 명령:

debug1: 명령 보내기: /bin/sh -c "cd /boot && ls -l"

두 번째 명령:

debug1: 명령 보내기: /bin/sh -c cd /boot && ls -l

일반적으로 명령을 보낼 때 ssh따옴표와 따옴표 안의 따옴표에 특별한 주의를 기울여야 합니다. 개별 레이어에서 이를 제거하기 때문입니다. 귀찮게 보내지 마세요 /bin/sh.

ssh다음 참고 자료를 이해하면 매우 유용한 작업을 수행할 수 있습니다. 그러면 원격 서버에서 명령이 실행되지만 ssh명령이 실행되는 시스템의 로컬 파일 에 결과가 수집됩니다 .

$ ssh root@server 'free -m' > /tmp/memory.status

또는 이 방법으로 원격 서버의 디렉토리를 압축하여 로컬 시스템에 생성합니다.

$ ssh remotehost 'tar zcvf - SOURCEDIR' | cat > DESTFILE.tar.gz

인용하다

답변4

일반적으로 사용할 쉘을 지정할 필요는 없습니다. 이것은 작동합니다:

ssh user@host "cd /boot && pwd"

그러나 기본 쉘에 문제가 있는 경우 다음을 인용하십시오.모두쉘 호출을 포함한 명령. 다음 작품 중 하나

ssh user@host '/bin/sh -c "cd /boot && pwd"'
ssh user@host "/bin/sh -c \"cd /boot && pwd\""

관련 정보