저는 Ubuntu를 실행하는 로컬 호스트와 원격 호스트가 있고 쉘은 bash로 설정되어 있습니다. 내 홈 디렉토리에는 로컬 호스트와 원격 호스트에 두 개의 파일 file-1
및 이 있습니다 . 각 홈 디렉토리에는 몇 가지 다른 파일이 있으며 일치하는 파일만 나열하고 싶습니다 .file-2
remote
file-*
로컬에서는 다음과 같은 예상 결과가 생성됩니다 file-1 file-2
.
$ ls file-*
$ bash -c 'ls file-*'
그러나 이 명령은 원격 홈 디렉터리의 모든 파일을 반환합니다. 거기서 무슨 일이 일어 났어?
$ ssh remote bash -c 'ls file-*'
$ ssh remote bash -c 'ls "file-*"'
$ ssh remote bash -c 'ls file-\*'
$ ssh remote bash -c 'ls "file-\*"'
ssh remote 'ls file-*'
이것이 예상한 결과 만 생성한다는 것을 알고 있지만 ssh remote bash -c 'ls ...'
전달된 인수가 폐기된 것처럼 보이는 이유는 무엇입니까 ls ...
? (원격으로 실행된 ls의 출력도 파이프하여 전달되었으므로 ls
해당 출력만 영향을 받는 것 같습니다 ssh remote bash -c 'ls file-* | xargs -I {} echo "Got this: {}"'
.)
답변1
사용할 때 원격 호스트에서 실행되는 명령은 ssh remote bash -c 'ls file-*'
다음과 같습니다.
bash -c ls file-*
이는 bash -c
스크립트를 실행하는 것을 의미합니다 ls
. 위치 인수로서 bash -c
스크립트는 원격 호스트에서 일치하는 이름을 가져옵니다 file-*
(이 이름 중 첫 번째 이름은 에 배치되므로 $0
실제로 위치 인수의 일부가 아닙니다). 인수는 명령에 전달되지 않으므로 ls
디렉터리의 모든 이름이 나열됩니다.
ssh
첫 번째 수준 따옴표(명령줄에서 사용되는 외부 따옴표 집합)를 제거하고 원격 호스트에서 실행할 명령을 전달합니다. 호출한 셸은 ssh
이러한 따옴표를 제거하고 ssh
원격 명령의 인수를 구분하기 위해 새 따옴표를 삽입하지 않습니다(명령에서 사용되는 따옴표를 방해할 수 있으므로).
다음 명령을 사용하면 이를 확인할 수 있습니다 ssh -v
.
[...]
debug1: Sending command: bash -c ls file-*
[...]
표시되는 다른 세 가지 명령은 동일한 방식으로 작동하지만 shell 등이 아닌 $0
string 에만 설정됩니다 .file-*
$1
$2
bash -c
아마도 당신이 원하는 것은 전체 명령을 인용하는 것입니다.
ssh remote 'bash -c "ls file-*"'
ssh -v
디버그 출력 에서는 다음과 같이 보고됩니다.
[...]
debug1: Sending command: bash -c "ls file-*"
[...]
즉, 원격 명령으로 전달된 문자열이 따옴표를 제거한 후 로컬 셸에서 실행하려는 명령인지 확인해야 합니다.
당신은 또한 사용할 수 있습니다
ssh remote bash -c \"ls file-\*\"
또는
ssh remote bash -c '"ls file-*"'
답변2
나는 ssh 매개변수가 서버에 의해 직접 실행될 것으로 기대한다는 오해가 있다고 생각하지만 이는 사실이 아닙니다. 당신이 쓸 때 :
ssh remote bash -c 'ls file-*'
SSH 클라이언트는 bash
, -c
및 를 공백으로 ls file-*
연결 하여 bash -c ls file-*
서버로 보냅니다. 서버는 해당 문자열을 가져와 매개변수로 전달합니다 bash -c
(원격 셸인 경우). 즉, 서버에서 다음과 같은 작업을 수행하게 됩니다.
bash -c 'bash -c ls file-*'
strace
SSH 서버에서 다음 명령을 실행하여 이를 확인할 수 있습니다.
$ sudo strace -fe trace=execve -p "$(pgrep -o sshd)" |& grep bash
[pid 794417] execve("/bin/bash", ["bash", "-c", "bash -c ls files-*"], 0x560ab66915d0 /* 13 vars */) = 0
내 생각에 당신이 원하는 것은 다음과 같습니다.
ssh remote 'ls file-*'
서버가 실행할 수 있도록:
bash -c 'ls file-*'