我有以下 bash 脚本deploy.sh:
#!/usr/bin/env bash\n\n# Some useful resources:\n# while read ip user pass; do : http://unix.stackexchange.com/questions/92664/how-to-deploy-programs-on-multiple-machines\n# -o StrictHostKeyChecking=no: http://askubuntu.com/questions/180860/regarding-host-key-verification-failed\n# -T: http://stackoverflow.com/questions/21659637/how-to-fix-sudo-no-tty-present-and-no-askpass-program-specified-error\n# echo $pass |: http://stackoverflow.com/questions/11955298/use-sudo-with-password-as-parameter\n\nwhile read ip user pass; do \n echo $ip\n sshpass -p "$pass" ssh $user@$ip -o StrictHostKeyChecking=no -T "\n echo \'yo\'\n "\n echo \'done\'\ndone < servers.txt\nRun Code Online (Sandbox Code Playgroud)\n\nservers.txt包含:
53.12.45.74 my_username my_password\n54.12.45.74 my_username my_password\n57.12.45.74 my_username my_password\n\xe2\x80\x8c\xe2\x80\x8c \nRun Code Online (Sandbox Code Playgroud)\n\n根据我的理解,while read ip user pass; do [\xe2\x80\xa6] done < servers.txt应该循环servers.txt.
但是,当我尝试运行它时,它只执行一次迭代:
\n\nubuntu@server:~$ bash deploy.sh\n53.12.45.74\nyo\ndone\nubuntu@server:~$\nRun Code Online (Sandbox Code Playgroud)\n\n为什么?
\n\n如果循环很简单:
\n\nwhile read ip user pass; do \n echo $ip\ndone < servers.txt\nRun Code Online (Sandbox Code Playgroud)\n\n它执行所有三个迭代:
\n\nubuntu@server:~$ bash deploy.sh\n53.12.45.74\n54.12.45.74\n57.12.45.74\nubuntu@server:~$\nRun Code Online (Sandbox Code Playgroud)\n
sshpass正在控制stdin或可能替换它并导致while循环丢失来自重定向的输入stdin。
要解决此问题,请避免从 stdin 读取。
首先,使用循环将文件加载到数组中while。
while read line; do
entries+=("$line")
done < servers.txt
Run Code Online (Sandbox Code Playgroud)
接下来,使用for循环来解析这些行并sshpass在该循环中执行。
for line in "${entries[@]}"; do
set $line
ip=$1
user=$2
pass=$3
echo $ip
sshpass -p "$pass" ssh $user@$ip -o StrictHostKeyChecking=no -T "
echo 'yo'
"
echo 'done'
done
Run Code Online (Sandbox Code Playgroud)
第二个循环不读取stdin.
但我会建议Rany Albeg Wein 的 答案使用一个单独的描述符而不是当前的stdin.
while read ip user pass <&3; do
echo $ip
sshpass -p "$pass" ssh $user@$ip -o StrictHostKeyChecking=no -T "
echo 'yo'
"
echo 'done'
done 3<servers.txt
Run Code Online (Sandbox Code Playgroud)