다음 셸 스크립트가 있습니다. 목적은 대상 파일의 각 행 (그 경로가 스크립트에 대한 입력 매개 변수)을 통해 반복하고 각 행에 대해 작업하는 것입니다. 이제 대상 파일의 첫 번째 줄에서만 작동하며 해당 줄이 처리 된 후 중지됩니다. 내 스크립트에 문제가 있습니까?
#!/bin/bash
# SCRIPT: do.sh
# PURPOSE: loop thru the targets
FILENAME=$1
count=0
echo "proceed with $FILENAME"
while read LINE; do
let count++
echo "$count $LINE"
sh ./do_work.sh $LINE
done < $FILENAME
echo "\ntotal $count targets"
에서는 do_work.sh
몇 가지 ssh
명령을 실행 합니다.
답변
문제는 명령 을 do_work.sh
실행 ssh
하고 기본적으로 ssh
입력 파일 인 stdin에서 읽는다는 것입니다. 결과적으로 ssh
파일의 나머지를 소비하고 while 루프가 종료 되기 때문에 처리 된 첫 번째 줄만 볼 수 있습니다.
이를 방지하려면 -n
옵션을 ssh
명령에 전달하여 /dev/null
stdin 대신 읽도록하십시오 .
답변
보다 일반적으로 다음과 관련된 해결 방법은 다음과 같습니다. ssh
은 while
루프의 입력을 소비 할 수있는 명령에 대한 표준 입력을 리디렉션하는 것 입니다.
while read -r LINE; do
let count++
echo "$count $LINE"
sh ./do_work.sh "$LINE" </dev/null
done < "$FILENAME"
를 추가하는 </dev/null
것이 여기서 중요한 점입니다 (수정 된 인용도 다소 중요합니다. 쉘 변수 주위에 인용 부호를 묶을 때 ). read -r
없이 얻을 레거시 약간 이상한 동작이 특별히 필요하지 않는 한 사용하고 싶을 것 -r
입니다.
다소 구체적인 또 다른 해결 방법 ssh
모든 ssh
명령에 표준 입력이 묶여 있는지 확인 하는 것입니다.
ssh otherhost some commands here
대신 여기 문서에서 명령을 읽을 수 있습니다.이 문서는 편리하게 (이 특정 시나리오의 경우) ssh
명령 에 대한 표준 입력 을 연결합니다.
ssh otherhost <<'____HERE'
some commands here
____HERE
답변
ssh -n 옵션은 출력을 다른 프로그램으로 파이핑하는 동안 HEREdoc을 사용할 때 ssh의 종료 상태를 확인하지 못하도록합니다. 따라서 stdin으로 / dev / null을 사용하는 것이 좋습니다.
#!/bin/bash
while read ONELINE ; do
ssh ubuntu@host_xyz </dev/null <<EOF 2>&1 | filter_pgm
echo "Hi, $ONELINE. You come here often?"
process_response_pgm
EOF
if [ ${PIPESTATUS[0]} -ne 0 ] ; then
echo "aborting loop"
exit ${PIPESTATUS[0]}
fi
done << input_list.txt
답변
내가했기 때문에 이것은 나에게 무슨 일이 일어나고 set -e
과 grep
루프에서이 (이 아닌 에러 코드를 제공하는) 어떠한 출력을 반환했다.