disown 是一个 Shell 内建命令(主要用于 Bash 和 Zsh),用于从 Shell 的当前任务列表中移除作业(job),这听起来可能有点抽象,但它的核心作用非常实用:让一个正在后台运行的进程,在你退出当前终端会话后,继续独立运行,而不会被挂起或终止。

为什么需要 disown?
想象一下这个常见的场景:
- 你在终端启动一个耗时很长的任务,
python my_script.py。 - 你立刻按下
Ctrl+Z将其暂停,然后使用bg命令将其在后台继续运行。 - 你关闭了 SSH 连接或直接关闭了终端窗口。
会发生什么?
默认情况下,这个后台进程会收到一个 SIGHUP(Hangup,挂断)信号,这个信号通常会导致进程终止,你辛辛苦苦跑的程序,因为关闭了终端而中途夭折了。
disown 就是为了解决这个问题而生的,它的作用是告诉 Shell:“这个作业我已经不管了,请不要在 Shell 退出时给它发送 SIGHUP 信号。”

disown 的工作原理
disown 通过从 Shell 的“作业控制”表中移除作业来实现其功能。
- 作业控制表:Shell 维护一个表,记录了所有由它启动的、正在运行的或已停止的进程(作业)。
SIGHUP信号:当你退出终端时,Shell 会向其作业表中的所有作业发送SIGHUP信号,通知它们“主人要走了”。disown的作用:当你对一个作业执行disown后,该作业会从作业控制表中消失,当 Shell 退出时,它就不会再向这个“已消失”的作业发送SIGHUP信号,该进程就变成了一个“孤儿进程”,由系统init进程(或systemd)接管,继续独立运行。
disown 的用法和选项
disown 命令通常和 jobs, bg, fg, & 等命令配合使用。
基本语法
disown [options] [job_spec ...]
job_spec:作业标识符,可以是作业 ID(如%1,%2),或者进程 ID (PID),如果不指定任何作业,disown会作用于当前 Shell 的所有作业。
主要选项
-h(--help):显示帮助信息。-a(--all):将所有作业从作业表中移除。-r(--remove):只移除正在运行的作业(这是默认行为)。-d(--delete):移除指定的作业,与直接指定作业效果相同。-h(--nohup):这是一个非常实用的选项,它不仅会从作业表中移除作业,还会立即对该作业设置nohup标志,这意味着即使用户没有退出,该作业也会忽略SIGHUP信号。
实战示例
让一个已经运行的作业在退出 Shell 后继续运行
假设你启动了一个长时间运行的脚本,然后意识到需要在退出后让它继续运行。
-
启动一个测试任务: 我们用
sleep命令模拟一个长时间任务。
(图片来源网络,侵删)sleep 300 # 这个命令会睡眠 300 秒
按下
Ctrl+Z暂停它。 -
查看当前作业:
jobs
输出可能如下:
[1]+ Stopped sleep 300这表示作业 1 (
%1) 处于停止状态。 -
将作业放入后台继续运行:
bg %1
输出:
[1]+ sleep 300 &现在作业 1 在后台运行。
-
执行
disown:disown %1
再次查看作业列表:
jobs
这次列表是空的,因为
%1已经被从作业表中移除了。 -
安全退出终端: 你可以放心地关闭终端窗口或断开 SSH 连接。
sleep 300进程会继续在后台运行,直到 300 秒后自然结束。
启动一个作业时直接让它“disown”
这是一个更常见的“最佳实践”用法,你可以在启动命令的同时就设置好它。
-
使用
&后台运行,并立即disown: 这是最简洁、最推荐的方式。nohup long_running_command.sh & disown
或者,你也可以这样写,效果相同:
long_running_command.sh & disown
这两行命令做了三件事:
long_running_command.sh &:在后台启动命令。disown:立即将这个新作业从作业表中移除。- (可选的
nohup):显式地告诉命令忽略SIGHUP,增加了健壮性。
-
使用
disown -h:disown -h的作用是设置nohup标志,这比nohup命令更“内聚”,因为它直接作用于 Shell 的作业。long_running_command.sh & disown -h
这种方式同样能让作业在退出 Shell 后继续运行,
nohup标志确保了它不会意外挂起。
disown 所有作业
如果你想一次性处理所有后台作业:
disown -a
这会把所有当前 Shell 的后台作业都移除,让它们在你退出后继续运行。
disown vs nohup vs &
这三个命令经常一起出现,但功能不同,容易混淆。
| 命令/方法 | 作用 | 优点 | 缺点 |
|---|---|---|---|
& |
将命令在后台运行。 | 命令不占用当前终端,你可以继续输入其他命令。 | 当你关闭终端时,进程会收到 SIGHUP 并被终止。 |
nohup |
让命令忽略 SIGHUP 信号。 |
即使你关闭终端,进程也不会被终止,输出会默认写入 nohup.out。 |
需要单独记忆 nohup 命令,且通常需要配合 & 使用。 |
disown |
从 Shell 的作业表中移除作业。 | Shell 退出时不会向该进程发送 SIGHUP,是 Shell 内建命令,更灵活。 |
只对当前 Shell 会话中的作业有效,如果进程已经终止,disown 不会“复活”它。 |
最佳实践组合:
对于需要在退出后继续运行的后台任务,最推荐、最健壮的方式是:
nohup your_script.sh > my_output.log 2>&1 &
或者,如果你想利用 Shell 的作业控制:
your_script.sh > my_output.log 2>&1 & disown
或者:
your_script.sh & disown -h
重要注意事项
- 无法恢复:一旦一个作业被
disown,你就无法通过fg %1这样的命令将它重新调回前台了,因为它已经不属于 Shell 的作业管理范围了。 - 仅对当前 Shell 有效:
disown只影响执行它的那个 Shell 进程及其子进程,如果你通过 SSH 登录,在终端 A 中disown一个作业,然后从终端 B 登录同一个系统,你是无法通过jobs看到或管理那个被disown的作业的。 disown不等于守护进程:disown只能防止进程被SIGHUP终止,如果进程因为其他原因(如内存错误、代码 bug)崩溃,它还是会退出,对于需要高可用性、日志管理、自动重启的服务,应该使用专业的进程管理工具,如systemd,supervisord,pm2等。
disown 是一个简单而强大的 Shell 工具,专门用于解决“后台进程因终端关闭而被终止”的痛点,它的核心思想是“断绝” Shell 与后台进程之间的父子联系,让进程成为“孤儿”,从而在用户退出后能够独立存活,对于临时性的后台任务,disown 是一个非常方便的解决方案。
