for
루프는 여기 괜찮습니다. 그러나 파일에 공백 문자 나 글 로빙 문자가 포함되지 않은 시스템 이름이 포함되어 있기 때문입니다. 쉘은 먼저 공백이있는 곳 어디에서나 명령의 출력을 분할 한 다음 각 단어를 glob 패턴으로 취급하므로 더 확장 되기 때문에 일반적으로 for x in $(cat file); do …
행을 반복하지 않습니다 . 작업 하면 안전 할 수 있습니다 .file
cat file
\[?*
for x in $(cat file)
set -f
IFS='
'
for x in $(cat file); do …
관련 독서 : 이름에 공백이있는 파일을 반복합니까? ; bash의 변수에서 한 줄씩 읽는 방법은 무엇입니까? ; 왜 while IFS= read
대신에 자주 사용 IFS=; while read..
됩니까? 를 사용할 때 while read
행을 읽는 안전한 구문은 while IFS= read -r line; do …
입니다.
이제 당신의 while read
시도 에 무엇이 잘못되었는지를 살펴 봅시다 . 서버 목록 파일의 리디렉션은 전체 루프에 적용됩니다. 따라서 ssh
실행될 때 표준 입력은 해당 파일에서 가져옵니다. ssh 클라이언트는 원격 애플리케이션이 표준 입력에서 읽을 수있는시기를 알 수 없습니다. 따라서 ssh 클라이언트가 일부 입력을 감지하면 해당 입력을 원격으로 보냅니다. ssh 서버는 원할 경우 해당 입력을 원격 명령에 공급할 준비가되었습니다. 귀하의 경우 원격 명령은 입력을 읽지 않으므로 데이터는 버려 지지만 클라이언트 측은 그것에 대해 아무것도 모릅니다. 입력을 읽지 echo
않기 때문에 시도 echo
했지만 표준 입력 만 남겨 둡니다.
이것을 피할 수있는 몇 가지 방법이 있습니다. -n
옵션을 사용하여 표준 입력에서 읽지 말도록 ssh에 지시 할 수 있습니다 .
while read server; do
ssh -n $server "uname -a"
done < /home/kenny/list_of_servers.txt
-n
사실 옵션은 말한다 ssh
로부터 입력을 리디렉션 /dev/null
. 쉘 수준에서 그렇게 할 수 있으며 모든 명령에서 작동합니다.
while read server; do
ssh $server "uname -a" </dev/null
done < /home/kenny/list_of_servers.txt
파일에서 ssh의 입력을 피하는 유혹 방법은 read
명령에 리디렉션을 설정하는 것 while read server </home/kenny/list_of_servers.txt; do …
입니다. read
명령이 실행될 때마다 파일이 다시 열리 므로 파일의 첫 번째 줄을 반복해서 읽게되므로 작동하지 않습니다 . 루프가 지속되는 동안 파일이 한 번 열리도록 리디렉션이 전체 while 루프에 있어야합니다.
일반적인 해결책은 표준 입력 이외 의 파일 디스크립터 에서 루프에 입력을 제공하는 것입니다. 쉘에는 하나의 디스크립터 번호에서 다른 디스크립터 번호로 입력 및 출력을 전달하는 구성이 있습니다. 여기서는 파일 디스크립터 3에서 파일을 열고 파일 디스크립터 3에서 read
명령의 표준 입력을 경로 재 지정합니다 . ssh 클라이언트는 열린 비표준 디스크립터를 무시하므로 모든 것이 좋습니다.
while read server <&3; do
ssh $server "uname -a"
done 3</home/kenny/list_of_servers.txt
bash에서 read
명령에는 다른 파일 디스크립터에서 읽을 수있는 특정 옵션이 있으므로 쓸 수 있습니다 read -u3 server
.
관련 읽기 : 파일 디스크립터 및 쉘 스크립팅 ; 추가 파일 설명자를 언제 사용 하시겠습니까?