因此,我通过 ssh 在脚本中“指示”从机器 A 到机器 B 的命令(顺便说一下,这是一个脚本)并将其发送到后台。该命令是这样的:
ssh -T MACHINEB SCRIPT &
我在机器 A 上运行的脚本没有超时。有时,我注意到命令/脚本的指令存在于机器 B 上(如果我为其执行 ps 操作),但有点挂起。 ps 显示正确的 PID 和 PPID,但仅此而已,它没有完成。
我正在尝试查找可能导致进程挂起的原因。我的意思是我几乎确定与代码相关,我只是想放弃以下可能性以及你们可能添加的任何其他内容。
当我运行远程 ssh 脚本执行时,我的进程是否附加到 ssh 会话?那么,如果我从 A 到 B 出现网络或 ssh 问题,我的进程会受到影响吗?
谢谢
答案1
ssh -T MACHINEB SCRIPT &
只要 SCRIPT 运行,就保持 SSH 连接运行。它需要这样做,因为:
- 如果 SCRIPT 产生任何输出,SSH 必须将其转发到主机。
- 如果 SCRIPT 读取输入,SSH 必须从主机中继它。这可能有点微妙。
- 当 SCRIPT 退出时,SSH 将其退出状态传输给客户端,并且进程
ssh
以该状态退出。
如果连接中断,如果 SCRIPT 不尝试读取或写入 stdin、stdout 或 stderr,则不会影响 SCRIPT。由于不涉及终端,因此当连接中断时 SCRIPT 不会被 SIGHUP 终止。但是,如果 SCRIPT 确实尝试打印错误消息,该消息就会通过连接。
你应该做两件事之一。
批处理作业方法:确保 SCRIPT 不接受任何输入并将标准输出和标准错误记录到文件中。
ssh -T MACHINEB 'myprogram </dev/null >myprogram.log 2>&1'
交互方法:在屏幕多路复用器内运行 SCRIPT:屏幕或者多路复用器。
ssh -T MACHINEB screen -S somename -dm myprogram
您可以通过附加到该屏幕会话来查看程序的运行情况。
ssh MACHINEB screen -S somename -dr
当程序退出时,屏幕会话也随之退出。要保留它以查看程序的输出和错误,请参阅一旦执行的脚本结束,防止 GNU 屏幕终止会话
也可以看看执行远程命令,完全脱离ssh连接
答案2
你的问题不太清楚,有点困惑,但我会尽力提供一些答案来为你理清思路。首先,请注意该ssh
进程在 MACHINEA 上运行,而 SCRIPT 在 MACHINEB 上运行。因此,“&”符号将ssh
MACHINEA 上的命令进程置于后台,而不是在 MACHINEB 上运行的 SCRIPT(shell)进程。因此,MACHINEA 上的(主)脚本继续执行(主)脚本的以下命令,而 MACHINEB 在“ssh”会话中运行 - 就 MACHINEB 而言,在前台运行。因此,如果从 A 到 B 存在连接问题,您的ssh
命令不会停止 MACHINEA 上的主脚本 - 因为该ssh
进程正在后台运行(可能被卡住)。
答案3
当您运行脚本时,它会创建一个执行命令的子 shell。任何进程(包括运行的后台进程)(例如 ssh 命令)都附加到此子 shell。如果子 shell 终止,后台进程也会被终止。相反,请尝试在脚本 1 中将 ssh 进程作为 nohup 命令运行。答案的灵感来自于:从脚本启动后台进程并在脚本结束时对其进行管理
通过 ssh 发送的命令会附加到 ssh 进程,并且 ssh 进程必须继续运行才能完成命令。退出 ssh 进程将终止机器 B 上的所有后台进程,因为它们附加到为脚本 2 创建的子 shell。Nohup 在这里也派上用场。
但由于您的进程正在机器 B 上执行,但显然挂起并且没有提前终止,因此 ssh 进程的提前终止似乎不是问题。
网络问题也不太可能发生,因为它们可能会终止 ssh 进程并终止机器 B 上运行的进程。此外,如果网络问题没有严重到终止 ssh 进程,它们不应该影响机器 B 上运行的进程。可能是机器 B 上的脚本 2 中的某些内容导致了停顿。证明这个逻辑错误的一种方法是杀死机器 A 上的 ssh 进程,然后看看机器 B 上会发生什么。
最后,最好的选择是按照前面链接中的建议将 ssh 命令作为 nohup 进程运行。此外,如果脚本 2 中的命令不是顺序相关的,我也会使用 nohup 运行每个命令。 (https://askubuntu.com/questions/349262/run-a-nohup-command-over-ssh-then-disconnect)。我假设计算机 A 上的脚本 1 中的任何内容都不依赖于脚本 2 的执行,因为您将 ssh 命令作为后台进程运行。