重击:通过 ssh 并行命令执行[关闭]
-
21-12-2019 - |
题
我的问题如下:我正在编写一个脚本,其目的是在不同的服务器上并行运行某些脚本。也就是说,我想登录到远程服务器,输入密码(这是不能协商的,因为老板),启动脚本,在脚本仍在运行时关闭连接,连接到下一个服务器并再次执行整个舞蹈。我该怎么做?
解决方案
假设 bash 是所有远程计算机上的目标 shell,您可以对一台计算机执行以下操作:
ssh user@host /path/to/script '&>/dev/null' '</dev/null' '&' disown
对于多台机器,您可以编写如下脚本:
hosts='user1@host1 user2@host2'
for host in $hosts
do
ssh $host /path/to/script '&>/dev/null' '</dev/null' '&' disown
done
这应该只是让您输入密码。
或者,如果您可以在多台计算机上使用相同的密码,我建议您查看 集群SSH. 。这样,您可以同时登录多台计算机,并在单个窗口中或在每个 xterm 窗口中单独键入要发送到所有计算机的命令。这将避免您重复输入相同的密码。登录后,您可以运行上面的命令(无需 ssh user@host
部分)并退出。
更新
这里有一些额外的想法。首先,完全丢弃脚本输出可能不是一个好主意,因为如果出现问题,您永远不会知道会发生什么。您可以将其放入文件中,以便稍后通过替换来查看 '&>/dev/null'
和 '&>filename'
. 。另一种方法是让远程计算机通过电子邮件将其发送给您(前提是它已正确设置为执行此操作):
host=user@host
ssh $host \(/path/to/script '2>&1' \| mail -s "$host output" me@me.com\) \
'&>/dev/null' '</dev/null' '&' disown
其次,如果脚本位于本地主机上,您可以将其复制并通过一个命令执行。假设是一个shell脚本,如果不是就替换 sh
有正确的翻译)
</path/to/script ssh user@host \
cat \>script \; sh ./script '&>/dev/null' '</dev/null' '&' disown
其他提示
登录后,您可以使用 screen 实用程序启动新的终端会话,然后从中分离,例如:
[user@local]$ ssh machine
[user@machine]$ screen -S my_session
# you are now switched to new terminal session named "my_session"
# now you can start long operation, that you want to keep in background
[user@machine]$ yes
# press "Ctrl-a d" to detach, you will go back to original session
[detached from 11271.my_session]
# now you can leave ssh (your session with "yes" running will be kept in background)
# to list existing screen sessions run:
[user@machine]$ screen -list
There is a screen on:
11271.my_session (Detached)
1 Socket in /var/run/screen/S-user.
# to re-attach use -r
[user@machine]$ screen -r my_session
# you will be back to session with "yes" still running (press Ctrl-C to stop it)
一旦您了解了屏幕的工作原理,您就可以尝试编写脚本;这是在分离状态下运行 my_command 启动屏幕会话的方法:
$ screen -d -m my_command
expect
可以很容易地实现自动化:
#!/usr/bin/expect -f
set hosts {your list of hosts goes here ...}
foreach host $hosts {
spawn ssh -t user@$host screen ./script.sh
expect "assword:"
send -- "secret\r"
sleep 1
send -- "d"
expect eof
}
不隶属于 StackOverflow