我有一个文件中的服务器列表,我将其传递给以下脚本:
#!/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 < "$1"
我想要的是这样输出:
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)
有没有办法确保这些命令按顺序发生?
先谢谢!
答案 0 :(得分:1)
此行末尾的&
使进程在后台运行:
ssh $ssh_cmd 'hostname && ls -l /path/to/folder | grep some_token' &
如果从该行中删除&
,脚本将等到ssh会话结束后继续循环的下一次迭代。此外,您需要将-n
标志添加到ssh命令,以便它不从stdin读取。这将为您提供您正在寻找的顺序输出。
最终命令:
ssh -n $ssh_cmd 'hostname && ls -l /path/to/folder | grep some_token'
答案 1 :(得分:0)
使用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