如何在 运行 多个命令 Linux 的同时 运行 并行 ssh 连接

How to run ssh connection in parallel while running multiple commands Linux

我试图了解在远程主机上 运行 以 parallel 方式使用 ssh 执行多个命令的最佳方法,并在挤压警告时在屏幕上显示输出,屏幕上的错误。

此 post 主要与 where KamilCuk 联系 POST 用一些漂亮的技巧回答了 POST 但是我还有一些未解决的问题。

下面的代码适用于给定的命令,但是我的系统中很少有人真的很旧并且不理解 nproc 命令来获取系统上的处理器数量因此我需要使用 grep -c processor /proc/cpuinfo如果我在 tmp=$(ssh "$server" bash -c 'grep -c "^processor" /proc/cpuinfo; free -g').

这样的当前解决方案中这样做,这是行不通的

也会考虑合并条件,例如如果 nproc 存在,则使用文件 /proc/cpuinfo 来计算 CPU,这只是一件与许多其他事情相似的事情。 因此,如果您有不同的命令子集需要从 commandsfiles.

获取值,那么如果有更多方法可以做到这一点,我很期待
 #!/bin/bash

read -rsp $'Please Enter password below: ' SSHPASS
export SSHPASS

work() {
   server=
   # ONE connection
   tmp=$(ssh "$server" bash -c 'nproc; free -g')
   # parsing later
   cpu_info=$(<<<"$tmp" awk 'NR==1')
   mem_info=$(<<<"$tmp" awk '/Mem:/{printf }')
   swap_info=$(<<<"$tmp" awk '/Swap:/{printf }')
   # outputting
   printf "%-40s %5s %5s %5s\n" "$server" "$cpu_info" "$mem_info" "$swap_info"
}
export -f work
< /home/user1/mem xargs -P0 -n1 -d'\n' bash -c 'work "$@"' _

我试过下面的想法是 borrowed from 但它只打印 SEREVR 名称,没有其他内容:

#!/bin/bash
read -rsp $'Please Enter password below: ' SSHPASS
export SSHPASS

for SERVER in '$(cat /home/user1/mem)'
do
sshpass -e ssh -q -t -oStrictHostKeyChecking=no $SERVER << EOF
        cpu_info=$(grep processor /proc/cpuinfo | awk 'NF==3{count++} END {printf count}')
        mem_info=$(free -g | awk /Mem:/{printf' '})
        swap_info=$(free -g | awk /Swap:/{printf' '})
        
        printf "%-40s %5s %5s %5s\n" "$server" "$cpu_info" "$mem_info" "$swap_info"

EOF
done | tee  2>/dev/null

我可能有很多错误,请原谅我只是想学习。

编辑注:

我知道会有一个明确的问题,为什么不使用 ssh keysalready existed tooling,比如 ansible,salt 等,原因只是,由于公司安全政策,我们不能使用任何他们没有办法重新发明轮子,但是我们在正常环境中大量使用 Ansible 和其他工具。

首先,这个循环不起作用:

for SERVER in '$(cat /home/user1/mem)'
do
...
done

因为 '',删除 '' 或最好先读取 var 或数组中的主机列表:

var=$(cat  /home/user1/mem)
arr=($(cat /home/user1/mem))

并循环这个 var(arr):

for SERVER in   $var     ; { ...; }
for SERVER in "${arr[@]}"; { ...; }

并行 ssh 连接可以这样完成:

cmd="
    cpu_info=$(grep processor /proc/cpuinfo | awk 'NF==3{count++} END {printf count}')
    mem_info=$(free -g | awk /Mem:/{printf' '})
    swap_info=$(free -g | awk /Swap:/{printf' '})

    printf \"%-40s %5s %5s %5s\n\" \"$HOSTNAME\" \"$cpu_info\" \"$mem_info\" \"$swap_info\"
"

for SERVER in "${arr[@]}"; {
    sshpass -p "$SSHPASS" ssh -q -t -oStrictHostKeyChecking=no "$SERVER" "$cmd" &
}

获取您需要的这些值的另一种解决方案可能是:

$ ssh user@foobar "bash -c \"grep -c '^processor' /proc/cpuinfo; free -g\"" | awk '{if (NR==1) {printf  " "} if (=="Mem:") { for (i=1; i<=NF; i++) printf $i " "}; if (=="Swap:") { for (i=1; i<=NF; i++) printf $i " "};}'
user@foobar's password:
4 Mem: 15 2 2 0 10 11 Swap: 15 0 15                                                                                                                                                                                                

最好告诉我们这些“旧”系统中可用的命令或工具是什么。我只习惯于使用脚本中的命令(grep 和 awk)。

对于多个SSH连接,只需将命令行引入for循环即可。

更新:要处理如果机器没有命令 nproc 的问题,只需添加一个 if 条件:

if ! command -v nproc &> /dev/null
then
        ssh user@foobar "bash -c \"grep -c '^processor' /proc/cpuinfo; free -g\"" | awk '{if (NR==1) {printf  " "} if (=="Mem:") { for (i=1; i<=NF; i++) printf $i " "}; if (=="Swap:") { for (i=1; i<=NF; i++) printf $i " "};}'

else
        ssh user@foobar "bash -c \"nproc ; free -g\"" | awk '{if (NR==1) {printf  " "} if (=="Mem:") { for (i=1; i<=NF; i++) printf $i " "}; if (=="Swap:") { for (i=1; i<=NF; i++) printf $i " "};}'
fi