运行 在多台服务器上通过 ssh 执行顺序命令
Running sequential commands through ssh on multiple servers
我在传递给以下脚本的文件中有一个服务器列表:
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
ssh_cmd="user@$line"
ssh $ssh_cmd 'hostname && ls -l /path/to/folder | grep some_token' &
done < ""
我想要的是这样的输出:
output from hostname (1)
output from ls -l (1)
output from hostname (2)
output from ls -l (2)
output from hostname (3)
output from ls -l (3)
但是这些好像混在一起了:
output from ls -l (1)
output from hostname (1)
output from hostname (2)
output from ls -l (2)
output from ls -l (3)
output from hostname (3)
有什么方法可以确保这些命令按顺序执行吗?
在此致谢!
此行末尾的 &
使进程在后台运行:
ssh $ssh_cmd 'hostname && ls -l /path/to/folder | grep some_token' &
如果您从该行中删除 &
,脚本将等到 ssh 会话完成以继续循环的下一次迭代。此外,您需要将 -n
标志添加到 ssh 命令,这样它就不会从标准输入中读取。这将为您提供所需的顺序输出。
最终命令:
ssh -n $ssh_cmd 'hostname && ls -l /path/to/folder | grep some_token'
使用 GNU Parallel
并行处理它们并使用 -k
选项保持输出顺序:
parallel -k -a hosts.txt 'echo ssh user@{} "hostname; ls"'
因此,如果 hosts.txt
包含以下内容:
host1
host27
host32
host100
hostfreddyfrog
hostmichaelfish
你会得到这个:
ssh user@host1 hostname; ls
ssh user@host27 hostname; ls
ssh user@host32 hostname; ls
ssh user@host100 hostname; ls
ssh user@hostfreddyfrog hostname; ls
ssh user@hostmichaelfish hostname; ls
很明显,您需要删除 echo
并添加您的引用和抓取,但概念应该足够清楚。
另一个优点,除了它现在是单行的,如果你有 32,000 台主机要工作,GNU Parallel
可以使用 -j
标志告诉,有多少个进程一次 运行 而不会使您的服务器超载。默认情况下,如果您的 CPU 中有 8 个内核,它将并行 运行 8 个作业,但您可以将其设置为 64,例如
parallel -k -j 64 ...
您还可以设置 GNU Parallel
以便能够 ssh
进入主机本身,通常是为了在服务器之间分配处理作业,这样作业就变得更加容易了。
parallel -S node1,node4,node56 'hostname; grep ...'
传递 hosts.txt
的替代语法是
parallel -k 'echo ssh user@{} "hostname; ls"' < hosts.txt
或
parallel -k 'echo ssh user@{} "hostname; ls"' :::: hosts.txt
我在传递给以下脚本的文件中有一个服务器列表:
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
ssh_cmd="user@$line"
ssh $ssh_cmd 'hostname && ls -l /path/to/folder | grep some_token' &
done < ""
我想要的是这样的输出:
output from hostname (1)
output from ls -l (1)
output from hostname (2)
output from ls -l (2)
output from hostname (3)
output from ls -l (3)
但是这些好像混在一起了:
output from ls -l (1)
output from hostname (1)
output from hostname (2)
output from ls -l (2)
output from ls -l (3)
output from hostname (3)
有什么方法可以确保这些命令按顺序执行吗?
在此致谢!
此行末尾的 &
使进程在后台运行:
ssh $ssh_cmd 'hostname && ls -l /path/to/folder | grep some_token' &
如果您从该行中删除 &
,脚本将等到 ssh 会话完成以继续循环的下一次迭代。此外,您需要将 -n
标志添加到 ssh 命令,这样它就不会从标准输入中读取。这将为您提供所需的顺序输出。
最终命令:
ssh -n $ssh_cmd 'hostname && ls -l /path/to/folder | grep some_token'
使用 GNU Parallel
并行处理它们并使用 -k
选项保持输出顺序:
parallel -k -a hosts.txt 'echo ssh user@{} "hostname; ls"'
因此,如果 hosts.txt
包含以下内容:
host1
host27
host32
host100
hostfreddyfrog
hostmichaelfish
你会得到这个:
ssh user@host1 hostname; ls
ssh user@host27 hostname; ls
ssh user@host32 hostname; ls
ssh user@host100 hostname; ls
ssh user@hostfreddyfrog hostname; ls
ssh user@hostmichaelfish hostname; ls
很明显,您需要删除 echo
并添加您的引用和抓取,但概念应该足够清楚。
另一个优点,除了它现在是单行的,如果你有 32,000 台主机要工作,GNU Parallel
可以使用 -j
标志告诉,有多少个进程一次 运行 而不会使您的服务器超载。默认情况下,如果您的 CPU 中有 8 个内核,它将并行 运行 8 个作业,但您可以将其设置为 64,例如
parallel -k -j 64 ...
您还可以设置 GNU Parallel
以便能够 ssh
进入主机本身,通常是为了在服务器之间分配处理作业,这样作业就变得更加容易了。
parallel -S node1,node4,node56 'hostname; grep ...'
传递 hosts.txt
的替代语法是
parallel -k 'echo ssh user@{} "hostname; ls"' < hosts.txt
或
parallel -k 'echo ssh user@{} "hostname; ls"' :::: hosts.txt