菜鸟科技网

setsid命令是什么?如何使用?

setsid 是一个在 Linux 和类 Unix 系统中非常有用的命令,它的全称是 "set session id"(设置会话 ID),它的核心功能是创建一个新的会话,并在这个新会话中运行指定的程序

setsid命令是什么?如何使用?-图1
(图片来源网络,侵删)

核心概念:进程、会话和进程组

要理解 setsid,首先要明白三个相关的概念:

  1. 进程:正在执行的程序实例。
  2. 进程组:一个或多个进程的集合,通常用于一起控制(通过一个终端发送信号 SIGINTSIGTERM 给整个组),每个进程组都有一个唯一的 ID (PGID)。
  3. 会话:一个或多个进程组的集合,一个会话由一个会话首进程 引导,会话的主要作用是管理终端,一个会话可以关联一个控制终端

关键点:

  • 当你打开一个终端(如 gnome-terminalxterm),这个终端启动的 Shell(如 bash)就是一个会话的首进程。
  • 在这个终端中启动的所有程序(ls, vim)都属于这个会话,并且它们的进程组 ID 通常与 Shell 的进程组 ID 相同或相关。
  • 当你关闭终端时,系统会给该会话的首进程发送一个 SIGHUP(挂断)信号,默认情况下,SIGHUP 信号会传递给会话中的所有进程组,导致它们也终止,这就是为什么在终端里运行一个程序,然后关闭终端,程序也会退出的原因。

setsid 的作用和工作原理

setsid 命令通过执行以下步骤,将一个程序与当前的终端环境“解耦”:

  1. 创建一个新的会话setsid 调用 setsid() 系统调用,创建一个新的会话,调用 setsid() 的进程会成为这个新会话的首进程
  2. 成为新进程组的组长:该进程同时成为新进程组的组长进程
  3. 脱离控制终端:最重要的是,新创建的会话没有关联任何控制终端,这意味着它不再接收来自原终端的信号(如 SIGHUP, SIGINT)。

setsid 的核心效果是:让一个程序在“后台”独立运行,不受你当前登录终端的任何影响。

setsid命令是什么?如何使用?-图2
(图片来源网络,侵删)

setsid 的主要用途和示例

setsid 最常见的用途就是让程序在后台“真正地”运行,即使你关闭了启动它的终端窗口。

用法 1: 让程序在后台独立运行

这是 setsid 最经典的应用场景。

场景:你想在终端运行一个长时间运行的程序(如一个下载任务、一个数据备份脚本),但你不希望一直开着终端窗口,担心误关闭它导致任务中断。

错误的做法: 直接在命令后加 & 符号(后台运行)。

setsid命令是什么?如何使用?-图3
(图片来源网络,侵删)
# 错误示例
$ sleep 3600 &
[1] 12345

这确实让 sleep 进程到后台了,但它仍然属于当前终端的会话,当你关闭这个终端时,sleep 进程会收到 SIGHUP 信号并终止。

正确的做法: 使用 setsid

# 正确示例
$ setsid sleep 3600

执行后,setsid 会立即返回,你的终端提示符会立刻出现,但 sleep 3600 进程已经在一个没有关联终端的新会话中运行了,你可以安全地关闭终端窗口,sleep 进程会继续运行,直到 3600 秒后自然结束。

如何验证?

  1. 执行 setsid sleep 10
  2. 立即打开另一个终端,使用 ps 命令查看进程:
    $ ps aux | grep sleep
    # 你会看到类似这样的输出,注意 TTY 一列通常显示为 ?,表示没有控制终端
    # user      12345  0.0  0.0  0.0  0.0 pts/0    S    10:00   10:00 /usr/bin/sleep 10
    # 注意:TTY 为 ? 才是脱离终端的标志
  3. 关闭你运行 setsid 的那个终端窗口。
  4. 过几秒后,再在第二个终端里执行 ps aux | grep sleep,你会发现 sleep 进程已经消失了,因为它正常执行完毕了,这证明它没有因为终端关闭而中断。

用法 2: 防止程序被 Ctrl+C 中断

当你按下 Ctrl+C 时,终端会向当前前台进程组发送 SIGINT 信号。setsid 启动的进程不在任何前台进程组中,因此它不会响应 Ctrl+C

示例

$ setsid bash
# 你在一个新的、没有终端的 bash 会话中
# 尝试按下 Ctrl+C,你会发现没有任何反应
# 你需要使用 'exit' 或者 'logout' 来退出这个 bash
$ exit

这个用法比较特殊,但展示了 setsid 如何隔离信号。


与其他命令的比较

命令/符号 作用 是否脱离终端 (SIGHUP) 是否立即返回终端
command & 在后台运行进程 (会随终端关闭而终止)
nohup command 忽略 SIGHUP 信号 (忽略挂断信号) (除非也加上 &)
setsid command 创建新会话,脱离终端 (没有终端可挂断)

nohup vs setsid

这是最常见的混淆点。

  • nohup (No Hang Up):

    • 它本身不创建新会话。
    • 它的作用是捕获 SIGHUP 信号并忽略它
    • 默认情况下,nohup 会将命令的输出重定向到当前目录下的 nohup.out 文件。
    • 如果你运行 nohup sleep 3600,你的终端会被这个进程占用,直到它结束,为了让它立即返回,你必须加上 &nohup sleep 3600 &
  • setsid:

    • 它的核心是创建一个没有控制终端的新会话
    • 因为没有终端,所以自然也就不存在“挂断”的概念,SIGHUP 信号根本不会被发送过来。
    • 它会立即返回你的终端,让你可以继续做其他事情。
    • 不会自动重定向标准输出和错误输出,如果你不关心输出,最好手动重定向到 /dev/nullsetsid sleep 3600 > /dev/null 2>&1

如何选择?

  • 如果你只是想让一个命令在后台运行,并且不怕它产生输出污染你的终端,setsid 是一个非常简洁的选择。
  • 如果你明确需要忽略 SIGHUP 信号,并且希望将所有输出(包括标准输出和标准错误)都保存到一个文件中,nohup 更合适。
  • 两者可以结合使用:nohup setsid command &,但这通常是多余的,因为 setsid 已经解决了核心问题。

实际应用场景举例

  1. 启动守护进程:很多系统服务(Daemon)都是以 setsid 的方式启动的,以确保它们在系统启动后独立运行,不依赖于任何用户终端。
  2. 执行长时间任务:如前所述,数据备份、文件传输、编译大型项目等,你可以启动任务后安心关闭电脑或终端。
  3. 自动化脚本:在 cron 定时任务中,你可能希望一个脚本在无人干预的情况下运行,虽然 cron 本身就有脱离终端的特性,但在某些复杂脚本中,显式使用 setsid 可以确保其行为符合预期。
  4. 图形应用程序:有时你想从命令行启动一个 GUI 程序,但又不希望它阻塞你的终端。setsid 可以完美实现这一点。
    # 启动一个图形编辑器,终端可以立即关闭而不会影响程序
    $ setsid gimp

setsid 是一个功能强大且底层的工具,它通过创建一个新的、无控制终端的会话,来确保一个程序能够独立、稳定地在后台运行,它是解决“关闭终端导致程序退出”这个问题的根本方法之一,与 nohup& 互为补充,为 Linux 用户提供了灵活的进程管理能力。

分享:
扫描分享到社交APP
上一篇
下一篇