所以我对 bash 了解不多,需要一些专业人士的帮助。我正在尝试运行这样的脚本:
filename='file1'
while read p; do
ssh -p 2222 $p 'who -b' | awk '{print $(NF-1)" "$NF}' >> file2*
Run Code Online (Sandbox Code Playgroud)
我想要制作的是一个脚本,它遍历文件 1 中的所有地址,以查看它们上次重新启动的时间,然后是文件 2 中的答案。
问题是它只通过第一个地址而不是另一个。
第一个地址有一个密码,我需要输入才能继续该过程。这可能是问题,还是我指定了 file1 中的每一行,还是我一开始就做错了?
最后我认为,脚本的其余部分没问题。然后我遵循@dessert 的评论并使用shellcheck它引导我解决实际问题及其解决方案:
SC2095:添加
< /dev/null以防止 ssh 吞下 stdin。
所以你必须以这种方式改变你的脚本:
ssh -p 2222 "$p" 'who -b' < /dev/null | awk '{print $(NF-1)" "$NF}' >> 'file2'
Run Code Online (Sandbox Code Playgroud)
根据原始答案并感谢@EliahKagan和@rexkogitans在评论中提供的有用建议,完整的脚本可能如下所示:
ssh -p 2222 "$p" 'who -b' < /dev/null | awk '{print $(NF-1)" "$NF}' >> 'file2'
Run Code Online (Sandbox Code Playgroud)
< /dev/null/由命令的-n选项替换ssh。来自man ssh:
#!/bin/bash
# Collect the user's input, and if it`s empty set the default values
[[ -z "${1}" ]] && OUT_FILE="reboot-indication.txt" || OUT_FILE="$1"
[[ -z "${2}" ]] && IN_FILE="hosts.txt" || IN_FILE="$2"
while IFS= read -r host; do
indication="$(ssh -n "$host" 'LANG=C who -b' | awk '{print $(NF-1)" "$NF}')"
printf '%-14s %s\n' "$host" "$indication" >> "$OUT_FILE"
done < "$IN_FILE"
Run Code Online (Sandbox Code Playgroud)IFS= read -r line- 正如@StéphaneChazelas 在他的百科全书式回答中所说- 是使用read内置.
printf '%s %s' "$VAR1" "$VAR2"将提供更好的输出格式(参考)。
LANG=C将保证who -b每台服务器上的输出相同,因此输出的解析awk也将得到保证。
注意这里假设有不需要的~/.ssh/config文件和附加参数-p 2222(参考)。
调用上面的脚本ssh-check.sh(不要忘记chmod +x)并以这种方式使用它:
使用输入 ( hosts.txt ) 和输出 ( reboot-indication.txt ) 文件的默认值:
-n Redirects stdin from /dev/null (actually, prevents reading from stdin).
This must be used when ssh is run in the background... This does not work
if ssh needs to ask for a password or passphrase; see also the -f option.
Run Code Online (Sandbox Code Playgroud)为输出文件设置自定义值;也为输入文件设置自定义值:
./ssh-check.sh
Run Code Online (Sandbox Code Playgroud)阅读此答案以了解如何改进整个方法。
您忘记关闭 while-do 循环。添加done到最后。
filename='file1'
while read p; do
ssh -p 2222 $p 'who -b' | awk '{print $(NF-1)" "$NF}' >> file2*
done
Run Code Online (Sandbox Code Playgroud)