我有一个在 RHEL 服务器中的 bash 上运行的脚本,该脚本连接到数千个节点并返回大约 5 个执行命令的值 - 它仅从 RHEL 服务器收集信息。
它工作正常,但问题是当我运行以下命令时,某些节点最终会冻结:
rpm -q <package-name>
rpm --queryformat '%{installtime:date} %{name}\n' -q <package-name>
现在,由于这肯定会停止我的脚本,因此我想为 ssh 命令设置超时,如果 ssh 会话等待某些远程命令执行时间过长(例如 10 秒),则退出 ssh 会话。当发生这种情况时,我想超时并退出该 ssh 会话并移至下一个节点。我该怎么做呢?
这是脚本的一部分,我目前在其中提取信息并将其存储在名为 dump 的变量中[请忽略我糟糕的脚本,我是新来的]
dump=$(ssh -o ServerAliveCountMax=1 -o ServerAliveInterval=10 -o ConnectTimeout=10 -o BatchMode=yes $i "cat /proc/meminfo | grep -i \"memtotal\" | cut -d \":\" -f2 | tr -d \" \" | tr -d \"kB\"; cat /etc/redhat-release | cut -d \" \" -f7; dmidecode | grep -i \"prod\" | grep -vi \"desktop\" | grep -iv \"id\" | cut -d \" \" -f3,4| tr \" \" \"_\" ; uptime | cut -d \" \" -f4,5 | tr \" \" \"_\" | tr -d \",\"; service kdump status 2>/dev/null | tr \" \" \"_\";");
如果持续时间太长,是否有办法超时?
我已经尝试过的:
(ssh -q -o Batchmode=yes -o PasswordAuthentication=no -o ConnectTimeout=1 $i "rpm --queryformat '%{installtime:date} %{name}\n' -q \"kexec-tools\" | cut -d \" \" -f1,2,3,4|tr \" \" \"_\"" > /dev/null) & pid=$!
(sleep 10 && kill -HUP $pid ) 2>/dev/null & watcher=$!
if wait $pid 2>/dev/null; then
pkill -HUP -P $watcher
wait $watcher
else
echo -e "$i Unable to ssh" >> res && continue
fi
但是,这样我就无法存储远程 rpm 命令的结果。
非常感谢任何帮助。
答案1
使用 GNU Parallel 并行化您的集合:
parallel --slf rhel-nodes --tag --timeout 1000% --onall --retries 3 \
"rpm -q {}; rpm --queryformat '%{installtime:date} %{name}\n' -q {}" \
::: bash bc perl
将节点放入~/.parallel/rhel-nodes
.
--tag
将在输出前面添加节点名称。--timeout 1000%
表示如果一个命令的运行时间比中位数长 10 倍,它将被终止。--onall
将在所有服务器上运行所有命令。--retries 3
如果失败,将运行命令最多 3 次。::: bash bc perl
是您要测试的包。如果您有很多包,请使用cat packages | parallel ...
语法而不是parallel ... ::: packages
.
GNU Parallel 是一个通用并行器,可以轻松地在同一台计算机或多台您可以通过 ssh 访问的计算机上并行运行作业。
如果您想要在 4 个 CPU 上运行 32 个不同的作业,则并行化的直接方法是在每个 CPU 上运行 8 个作业:
相反,GNU Parallel 在完成后会生成一个新进程 - 保持 CPU 处于活动状态,从而节省时间:
安装
如果您的发行版未打包 GNU Parallel,您可以进行个人安装,不需要 root 访问权限。这样做可以在 10 秒内完成:
(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash
对于其他安装选项,请参阅http://git.savannah.gnu.org/cgit/parallel.git/tree/README
了解更多
查看更多示例:http://www.gnu.org/software/parallel/man.html
观看介绍视频:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
浏览本教程:http://www.gnu.org/software/parallel/parallel_tutorial.html
注册电子邮件列表以获得支持:https://lists.gnu.org/mailman/listinfo/parallel
答案2
感谢您尝试解决此问题。
我现在已经解决了这个问题,而且所需的解决方案是如此简单,以至于我现在感觉很愚蠢。
在我之前使用的代码中,
(ssh -q -o Batchmode=yes -o PasswordAuthentication=no -o ConnectTimeout=1 $i "rpm --queryformat '%{installtime:date} %{name}\n' -q \"kexec-tools\" | cut -d \" \" -f1,2,3,4|tr \" \" \"_\"" > /dev/null) & pid=$!
我所需要做的就是将所有输出重定向到本地计算机上的文件。就是这样。
(ssh -q -o Batchmode=yes -o PasswordAuthentication=no -o ConnectTimeout=1 $i "rpm --queryformat '%{installtime:date} %{name}\n' -q \"kexec-tools\" | cut -d \" \" -f1,2,3,4|tr \" \" \"_\"" > **test**) & pid=$!
我决定自己发布答案的唯一原因是因为您给出的答案需要引入和使用外部工具/代码,这是我不想做的事情。相反,我想要一个可以在不依赖于软件包或操作系统版本的可用性的情况下应用的解决方案。
尽管如此还是谢谢你!