
FreeBSD 시스템(xxx.yyy.zzz.net)에서 명령을 실행하고 출력을 받고 있습니다.
명령
sudo camcontrol devlist | grep -o 'ada[0-9]' | while read -r a ; do sudo camcontrol identify $a | grep rotating ; done
산출
media RPM non-rotating
media RPM non-rotating
media RPM non-rotating
다른 컴퓨터에서 SSH를 사용하여 동일한 명령을 실행하려고 합니다.
명령
ssh xxx.yyy.zzz.net sudo camcontrol devlist | grep -o 'ada[0-9]' | while read -r a ; do sudo camcontrol identify $a | grep rotating ; done
오류
sudo: camcontrol: command not found
답변1
명령에서 모든 것은 |
로컬 셸에 의해 해석됩니다. 마지막 인수 ssh
는 입니다 devlist
. ssh
로컬에서 호출되지만(놀랍지 않습니다) 첫 번째 이후의 모든 항목도 마찬가지입니다 |
.
발생한 오류는 sudo
이 스니펫에서 발생했습니다 do sudo camcontrol identify $a
. 로컬로 실행되며 camcontrol
로컬 컴퓨터에서는 사용할 수 없는 것 같습니다.
적절한 이스케이프 또는 인용이 필요합니다. 이 경우 전체 원격 명령을 작은따옴표로 묶을 수 있습니다.
ssh xxx.yyy.zzz.net 'sudo camcontrol devlist | grep -o "ada[0-9]" | while read -r a ; do sudo camcontrol identify $a | grep rotating ; done'
참고 이미 가지고 있는 작은따옴표를 변경했습니다. (추가된) 작은따옴표는 전체 문자열을 그룹화할 뿐만 아니라 ssh
이를 가져옵니다. 또한 $a
.
sudo
비밀번호를 요청하려면 의사 터미널이 필요합니다 . -t
옵션을 사용하여 의사 터미널 할당을 강제로 수행할 수 있습니다 ssh
(따라서 처럼 보입니다 ssh -t xxx.yyy.zzz.net …
). Note는 ssh -t
원격 측에 의사 터미널을 할당합니다. 원격은 sudo
stderr에 대한 프롬프트를 표시하지만 stdout과 stderr은 이 의사 터미널에 의해 "인쇄"되며(일반적으로 콘솔에 인쇄되는 것처럼) 이 시점에서는 더 이상 구별할 수 없습니다. 병합된 스트림은 캡처되어 stdout으로 이동하는 로컬 측으로 전송됩니다. 원격 stdout 및 stderr이 별도로 전송 되지 않으면 -t
로컬 측의 stdout 및 stderr로 이동하면 결국 표시되는 내용으로 병합됩니다(또는 리디렉션되는 경우에는 병합되지 않음). 이는 -t
로컬 측에서 원격 stderr과 원격 stdout을 구별할 수 없음을 의미합니다. 출력을 로컬에서 추가로 처리(리디렉션)해야 하고 사용하는 -t
경우 프롬프트가 sudo
방해됩니다.
$a
또한 (를 사용하지 않는 첫 번째 명령에서도 ) 큰따옴표를 사용하고 싶을 수도 있습니다 ssh
. 보다쉘 스크립트가 공백이나 기타 특수 문자로 인해 막히는 이유는 무엇입니까?