【问题标题】:bash: parallel command execution over ssh [closed]bash:通过 ssh 执行并行命令 [关闭]
【发布时间】:2025-05-01 11:20:02
【问题描述】:

我的问题如下:我正在编写一个脚本,其目的是在不同的服务器上并行运行某些脚本。即,我想登录远程服务器,输入密码(这是不可协商的,因为老板),启动脚本,在脚本仍在运行时关闭连接,连接到下一个服务器并再次完成整个舞蹈。我该怎么做?

【问题讨论】:

    标签: bash ssh parallel-processing remote-execution


    【解决方案1】:

    假设 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
    

    这应该只是让您输入密码。

    或者,如果您可以为多台机器使用相同的密码,我建议您查看ClusterSSH。有了这个,您可以同时登录到多台机器,并在单个窗口中或在每个 xterm 窗口中单独键入要发送给所有机器的命令。这样可以避免您重复输入相同的密码。登录后,您可以像上面那样运行命令(不带ssh user@host 部分)并退出。

    更新

    这里有几个额外的想法。首先,完全放弃脚本输出可能不是一个好主意,因为如果出现问题,您永远不会知道会发生什么。您可以将其放入一个文件中,以便稍后通过将'&amp;&gt;/dev/null' 替换为'&amp;&gt;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
    

    【讨论】:

    • 如果脚本有参数怎么办?我将如何合并它们?
    • 好的,我想通了:ssh $host '/path/to/script' 'argument' '&amp;&gt;/dev/null' '&lt;/dev/null' '&amp;' disown.
    • 是的,只需在脚本调用后添加参数即可。除非您通常会引用它们,否则无需引用它们。
    【解决方案2】:

    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
    }
    

    【讨论】:

    • 感谢@PatrykObara 的屏幕建议。
    【解决方案3】:

    登录后,您可以使用 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
    

    【讨论】:

    • 对我不起作用。我试过ssh user@host screen -d -m"./script.sh"。我得到屏幕使用输出。选项 -m 显示为“忽略 $STY 变量,创建一个新的屏幕会话。”
    • 我刚刚检查过,它对我有用。 script.sh 文件是位于主机上还是您的本地计算机上(它应该位于主机上)?它是否设置了可执行标志?另外,-m 和 command 之间应该有空格。
    • 此外,手册将“-d -m”描述为“以“分离”模式启动屏幕。这会创建一个新会话,但不会附加到它。“这正是它的作用:)
    • script.sh 在主机上并且可执行。我在this thread找到了解决方案:
    • ssh -n -f -p$SSH_PORT test@localhost "bash -c 'nohup ./test.sh 2&gt;&amp;1 &gt; test.log &amp;'"
    最近更新 更多