我想远程 ssh 到多个服务器并检查这些服务器上是否有任何进程正在运行,并等待该进程完成。我已经编写了下面的代码,但是自从我添加了“继续”语句以来,这只检查文件(ip.txt)中的第一个IP。我需要修改这段代码。
while read IP
do
ssh ubuntu@$IP "pgrep -f pattern"
if [ $? -eq 0 ]; then
echo "Process is running"
sleep 10
continue
else
echo "Process is not running"
fi
done < ip.txt
答案1
最好先对 IP 列表进行排序,然后对其进行迭代:
mapfile ipaddresses < ip.txt
canary=alive
while [[ "alive" == "$canary" ]]; do
canary=dead
for ip in ${ipaddresses[@]}; do
if ssh ubuntu@$ip "pgrep -f pattern"; then
echo "Process is running on $ip"
canary=alive
sleep 10
continue
else
echo "Process not running on $ip"
fi
done
done
如果您仍然停留在低于 4 的版本bash
,请将mapfile
命令替换为:
read -r ipaddresses <<< "$( cat ip.txt )"
答案2
我在这里看到基本程序流程的一些问题。当你在这里有一个构造时,实际上有几件事被跟踪:
- 如果您列表中的任何主机在此检查中仍有正在运行的进程,我们应该记录下来并再次检查
- 如果仍然有进程的主机数量为 0,我们应该退出。
所以我会为此脚本使用两个循环。另外,continue
这里不需要,这可能是导致它每次重复第一个主机的原因。
我做了一些不同的事情,主要测试返回的 PID 数量,psget
而不是检查 ssh 退出代码,并使用一些稍微不同的语法。这是我想出的示例,它似乎适合您想要的内容:
#!/bin/bash
set -eu
# get number of IPs from lines in file
NUM_IPS=$( cat ip.txt | wc -l )
echo "checking ${NUM_IPS} hosts..."
# Set number of running hosts to the max. While arbitrary, it will
# update to the correct number before reporting, and if it is 0 the
# while loop will exit immediately.
IPS_STILL_RUNNING=${NUM_IPS}
while [ "${IPS_STILL_RUNNING}" -gt "0" ]
do
RUNNING_NOW=0
for IP in $( cat ip.txt )
do
PROC_NUM=$( ssh ${IP} -- pgrep -f pattern | wc -l )
if [ "${PROC_NUM}" -gt "0" ]; then
echo " ${IP}: still running"
RUNNING_NOW=$(( RUNNING_NOW + 1 ))
else
echo " ${IP}: not running"
fi
done
echo "still running on $RUNNING_NOW hosts"
IPS_STILL_RUNNING=${RUNNING_NOW}
sleep 10
done
答案3
如果您想并行连接多个主机,请使用类似(并行分布式 Shell)ssh
的程序。pdsh
例如,如果您ip.txt
包含 IP 地址而不是主机名,或者主机名和 IP 地址的混合:
hosts="$(awk '{l = l","$0}; END {sub(/^,/,"",l); print l}' ip.txt)"
while pdsh -l ubuntu -w "$hosts" 'pgrep -f pattern' 2>/dev/null |
grep pattern ; do
sleep 10
done
这用于awk
构建一个以逗号分隔的 IP 地址列表,以便通过ssh
.
如果ip.txt
文件包含仅有的主机名而不是IP地址,它更简单:
while pdsh -l ubuntu -F ./ip.txt -a 'pgrep -f pattern' 2>/dev/null |
grep pattern ; do
sleep 10
done
这两者都假设ip.txt
每行有一个 IP 地址或主机名。
循环while
运行直到没有任何主机产量任何与模式匹配的输出。命令中的 stderr被重定向到 /dev/null,以避免当命令返回退出代码 1pdsh
时向终端发送错误消息。pgrep
pdsh
唯一的输出来自grep pattern
管道中。grep -q pattern
如果您也希望使其静音,请使用。