
다음 예는 파이프를 사용하는 전형적인 방법입니다. 파이프의 오른쪽에는 표준 입력(파이프)에서 데이터를 읽고 이를 표준 출력의 역순으로 인쇄하는 "간단한" 유틸리티가 있습니다.
{ cat <</EOF
Hello
World
/EOF
} | rev
결과는 다음과 같습니다.
olleH
dlroW
이제 데이터를 셸의 일부인 명령/유틸리티(여기 문서)로 파이프하고 싶습니다.
{ cat <</EOF
Hello
World
/EOF
} | ksh -x <</EOF
rev
/EOF
이것은 작동하지 않습니다. 오류 메시지도 없고, 아무것도 없습니다. ksh가 stdin을 here-doc로 리디렉션하기 때문에 파이프 데이터가 손실됩니다.
나는 일종의 리디렉션을 시도했습니다.
set -x
{ cat <</EOF
Hello
World
/EOF
} | { exec 4<&0; ksh -x <</EOF; exec 0<&4 4<&-; }
rev <&4
/EOF
그러나 이것도 작동하지 않습니다. rev 명령에 오류가 표시됩니다. 분명히 stdin에서 fd4로의 리디렉션이 ksh의 하위 프로세스로 전달되지 않습니다.
+ exec
+ 4<& 0
+ ksh -x
+ cat
+ 0<< \/EOF
rev <&4
/EOF
+ 0<< \/EOF
Hello
World
/EOF
+ rev
+ ksh[1]: 4: cannot open [Ungültiger Dateideskriptor]
+ exec
+ 0<& 4 4<& -
나는 여기에 갇혀있다.
내 실제 애플리케이션은 훨씬 더 복잡합니다. 파이프라인의 왼쪽에서 소스 서버로 ssh를 실행하고 선택적으로 해당 서버의 다른 사용자에게 sudo를 실행한 다음 tar를 실행하여 일부 데이터 파일을 파이프합니다. 파이프의 오른쪽에서는 대상 서버로 ssh를 실행하고 선택적으로 다른 사용자에게 sudo를 실행한 다음 마지막으로 tar를 실행하여 파이프에서 데이터를 수신해야 합니다.
참고: 파이프 오른쪽에 있는 문서를 사용하지 않으면 모든 것이 잘 작동합니다.
{ cat <</EOF
Hello
World
/EOF
} | ksh -xc "rev"
ssh와 sudo, tar를 사용해도 정상적으로 작동할 수 있습니다. 어떤 이유에서인지 나는 여기 오른쪽에 있는 쉘 문서를 원합니다. 보시다시피 ksh는 이 애플리케이션에서 제가 가장 좋아하는 셸입니다.
요청한 대로: 내 원래 진술은 다음과 같습니다.
ssh $SSHOPT $INST_FILE_USER@$INST_FILE_HOST "cd $IDIR && { tar -cvf - $IFIL && echo RCSRC0 >&2 || echo RCSRC1 >&2; }" 2>$TMPFILE.err.src | ssh $SSHOPT $TRG_USER@$TRG_HOST "cd $TDIR && { tar -xmvf - && echo RCTRG0 || echo RCTRG1; }" 1>$TMPFILE.out.trg 2>&1
여태까지는 그런대로 잘됐다. 보시다시피 최소한의 오류 검사가 수행되어 tar를 성공적으로 인식할 수 있습니다. 이제 sudo 기능을 추가해야 합니다. 이는 ssh 셸과 cd 명령 사이에 사용자를 전환하기 위한 일부 코드를 추가해야 함을 의미합니다. 정말 sudo인가요? 사용되나요? 고객이 pbrun을 선호할 수 있으므로 아마도 pbrun 명령일 것입니다. 1개의 몬스터 설명문 대신 이 문서를 사용하면 이러한 다양한 시나리오를 보다 유연하게 처리할 수 있습니다.
5월 21일 업데이트됨: 지금까지 제공된 조언을 따르려고 노력했지만 여전히 정체되어 있습니다. 아래 답변을 살펴보겠습니다. 제게는 효과적이었습니다.
echo yup | ksh -c 'exec 4<&0; ksh -c "rev <&5" 5<&4'
puy
ssh를 사용하거나 sudo와 함께 ssh를 사용하기 시작하면 리디렉션 예제가 더 이상 작동하지 않습니다.
echo yup | ssh admin@trg14 ksh -c 'exec 4<&0; ksh -c "rev <&5" 5<&4'
bash: 4: Bad file descriptor
echo yup | ssh admin@trg14 sudo -n -u trg4 ksh -c 'exec 4<&0; ksh -c "rev <&5" 5<&4'
bash: 4: Bad file descriptor
ssh와 sudo 조합으로 2가지 시나리오를 시도했습니다. 첫 번째는 ksh에 대한 입력으로 here-doc를 사용하는 것이었습니다.
장면 1:
echo yup | ssh admin@trg14 sudo -n -u trg4 -- ksh<</EOF
whoami && whoami && rev && whoami
/EOF
trg4
trg4
trg4
지금까지는 이것이 작동합니다. 참고: 4개 명령은 모두 사용자 trg4로 실행되며, 여기 문서로 인해 rev는 파이프를 통해 예상대로 입력을 받지 못합니다.
그래서 아래에 제안된 솔루션을 구현하려고 했습니다. here-doc는 ksh에 대한 인수로 입력됩니다.
시나리오 2:
echo yup | ssh admin@trg14 sudo -n -u trg4 -- ksh -c "$(cat<</EOF
whoami && whoami && rev && whoami
/EOF
)"
trg4
admin
puy
admin
rev의 출력은 예상대로입니다.하지만:whoami는 이 버전/구현에서만 이를 보여줍니다.첫 번째명령은 sudo 사용자로 실행되고 나머지 명령은 ssh 로그인 사용자로 실행됩니다! rev의 경우에는 문제가 없지만 데이터베이스 파일에 액세스하거나 작성해야 하는 경우 권한 문제로 인해 실패하게 됩니다.
이 두 가지 예의 결론: 시나리오 1은 올바른 sudo 사용자로 모든 명령을 실행하는 올바른 방법일 수 있지만 파이프를 사용하려면 stdin 리디렉션 문제를 해결해야 합니다.
도움을 주시면 감사하겠습니다!
답변1
간단한 해결 방법은 -c
here-doc 스크립트를 내부 쉘에 인수로 전달하는 것입니다.
{ cat <<'/EOF'
Hello
World
/EOF
} | ksh -c "$(<<'/EOF'
rev
# you can freely use " inside this script
/EOF
)"
줄게
olleH
dlroW
이것 역시 작동 합니다 zsh
.$(<<
$(cat<<
어느껍데기.
다음을 사용하는 대신 명령 수준에서 수행하는 경우 리디렉션을 조작할 수도 있습니다 exec
.
... | ksh 4<&0 <<'/EOF'
rev <&4
/EOF
이 경우 here-doc 스크립트에서 fds로 다시 교체하는 방법을 사용할 수도 있지만 exec 5<&4 4<&0 <&5 5<&-
IMHO 이 모든 것은 쓸모없는 합병증입니다.
ksh의 스크립트 수준 리디렉션
세 번째 예의 문제는 더 간단한 테스트 사례로 축소될 수 있습니다.
$ echo yup | ksh -c 'exec 4<&0; ksh -c "rev <&4"'
ksh: 4: cannot open [Bad file descriptor]
하지만:
$ echo yup | dash -c 'exec 4<&0; ksh -c "rev <&4"'
puy
ksh
이는 ( )로 열린 모든 fd에 close-on-exec 플래그가 설정되기 때문입니다.O_CLOEXEC
스크립트 수준리디렉션(예: exec 4</path/to
또는 사용 exec 4<&0
) 이는 다음으로 인해 발생합니다.기준:
exec
명령이나 인수 없이 지정되고 2보다 큰 번호의 파일 설명자가 연관된 리디렉션 문을 사용하여 열리는 경우, 쉘이 다른 유틸리티를 호출할 때 해당 파일 설명자가 열려 있는지 여부는 지정되지 않습니다 .
추가 작업을 수행하면 이 문제를 해결할 수 있습니다.명령 수준리디렉션:
echo yup | ksh -c 'exec 4<&0; ksh -c "rev <&5" 5<&4'
puy
([1] 이전 ksh93
버전은 사용하지 않음 )을 사용하여 fd를 다시 복사하면 저절로 작동합니다.mksh
R57
$ echo yup | ksh93 -c 'exec 4<&0; ksh -c "rev <&4" 4<&4'
puy
[1] 2019년 3월에 출시되었으며 여기에서 수정되었습니다.범죄.
답변2
[다른 질문을 해봐야 해.다른이것을 쌓는 대신 질문]
[command] 매개변수를 사용하여 SSH를 실행합니다.
다음과 같이 매개변수를 ssh
사용 하여 실행 하면 어떤 일이 발생합니까 ?[command]
ssh user@host foo bar baz
공간-c
스위치를 통해 원격 시스템에 있는 사용자의 로그인 셸로 전달되는 단일 매개변수로 변환 됩니다(해당 셸이 실행 /bin/sh
중이 면 /bin/sh -c 'foo bar baz'
실행됩니다).
이제 귀하의 예에서는 어떤 일이 발생합니까?
echo yup | ssh admin@trg14 ksh -c 'exec 4<&0; ksh -c "rev <&5" 5<&4'
ssh에 대한 인수는 문자열로 연결됩니다.
ksh -c exec 4<&0; ksh -c "rev <&5" 5<&4
머신에서 쉘을 제거하면 먼저 실행됩니다
ksh -c exec 4<&0
그런 다음
ksh -c "rev <&5" 5<&4
두 개의 개별 명령이므로 물론 두 번째 명령의 fd 4는 첫 번째 명령에서만 리디렉션되므로 아무 것도 가리키지 않습니다.