You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过SSH运行含后台进程的脚本:让SSH无需等待子进程退出

解决SSH执行脚本等待子进程退出才返回的问题

这个问题我之前也碰到过——核心原因是SSH会话会保持与远程shell的标准输入、输出、错误流的连接,哪怕你把进程放到后台,如果它还在使用这些流(比如你的echo "done"会输出到stdout),SSH就会一直等着这些流关闭才会断开连接返回。

下面给你几个实用的解决方案,按推荐程度排序:

1. 重定向后台进程的所有IO流

最简单直接的方式,把后台子进程的标准输出、标准错误都重定向到/dev/null(或者你指定的日志文件),让它彻底脱离SSH的会话流:

修改你的test.sh:

#!/bin/bash
( sleep 2
echo "done" ) > /dev/null 2>&1 &

这样后台进程的输出不会再占用SSH的会话通道,SSH执行完脚本后会立即返回,而后台的sleep和echo会继续运行。如果需要保存输出,把/dev/null换成具体的文件路径就行,比如./test.log。

2. 使用nohup启动守护进程

nohup是专门用来让进程脱离终端运行的工具,它会自动帮你处理IO重定向,还能让进程忽略挂起信号(比如SSH会话断开时的SIGHUP)。

可以直接在脚本里用:

#!/bin/bash
nohup sh -c 'sleep 2; echo "done"' > /dev/null 2>&1 &

或者在SSH命令里直接调用:

ssh user@remote-host 'nohup ./test.sh > /dev/null 2>&1 &'

默认情况下nohup会把输出写到nohup.out,你也可以像上面那样自定义重定向。

3. 用disown移除后台作业

如果你不想修改IO流,可以在后台启动进程后,用bash的内置命令disown把它从shell的作业列表中移除——这样远程shell退出时,不会再跟踪这个后台进程,SSH也就会立即返回:

修改test.sh:

#!/bin/bash
( sleep 2
echo "done" ) &
disown

不过这种方式要注意,如果后台进程还在使用SSH的会话流,可能还是会有延迟(比如echo "done"输出的时候,SSH可能会等输出完成),所以最好还是配合IO重定向一起用。

另外,如果你用的是ssh命令的-f参数(让SSH在后台运行),结合上面的方法效果会更好:

ssh -f user@remote-host './test.sh'

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:14:09