【问题标题】:why setsid could not exit from shell script?为什么setsid 不能从shell 脚本中退出?
【发布时间】:2014-01-20 10:49:49
【问题描述】:
$ cat test1.sh
#!/bin/bash

setsid sleep 100

'test1.sh' shell 脚本不会立即退出。

$ cat test2.sh
#!/bin/bash

setsid sleep 100 &

'test2.sh' shell 脚本将立即退出。

谁能帮我解释一下?非常感谢。

【问题讨论】:

  • & 将命令置于后台,导致后者退出。
  • 请注意,这与setsid 命令无关。
  • 'setsid' 将解除进程,所以我希望脚本在 'setsid sleep 100' 之后继续执行,而不是等待 100 秒。

标签: linux bash shell setsid


【解决方案1】:

这个问题可能是this even older question的重复,那边的答案很有用。也许这些应该合并。

我也对setsid 的这种行为感到惊讶。所以我检查了手册页:

DESCRIPTION
       setsid runs a program in a new session. The command calls fork(2) if already a
       process group leader. Otherwise, it executes a program in the current process.
       This default behavior is possible to override by the --fork option.

这里有一些行话要理解。让我们查看POSIX 定义列表(第 3 章)。

一个会话是:

为作业控制目的而建立的流程组的集合。每个进程组都是一个会话的成员。进程被认为是其进程组所属的会话的成员。新创建的进程加入其创建者的会话。一个进程可以改变它的会话成员;请参阅 setid()。同一会话中可以有多个进程组。

fork() 调用通过复制当前进程来创建一个新进程。更多信息in this post.

流程组负责人是:

进程 ID 与其进程组 ID 相同的进程。

所以,setsid 只有在作为进程组领导者执行时才会创建一个新进程。直接在 shell 中运行命令时总是如此,因此可以将作业队列构造为进程组列表。但是,当作为脚本的一部分运行时,组长是用于运行脚本的新 shell 进程。

幸运的是,我们有--fork 选项来强制创建一个新进程。比如shell脚本:

#!/bin/sh
setsid --fork sleep 5

将在不等待sleep 完成的情况下退出,即使您关闭运行脚本的shell,sleep 命令也会继续。据我所知,setsid --fork 是正确确保命令作为分离进程运行的唯一方法

其他资源:

【讨论】:

    【解决方案2】:

    您的第一个脚本等待 setsid sleep 100 完成然后返回(换句话说,它将在睡眠完成后返回,这里是 100 秒),但第二个脚本不等待命令完成,因为 @987654322 @ 将命令置于后台并立即返回。引用man bash

    If  a  command is terminated by the control operator &, the shell executes the
    command in the background in a subshell. The shell does not wait for the command
    to finish, and the return status is 0.
    

    还要注意& 是一个控制运算符,它具有更高的优先级。希望这会有所帮助!

    【讨论】:

    • 感谢您的回复。我知道shell脚本中'&'的用法。如果 'setsid' 被删除,你的答案非常好。但是这里使用了“setsid”。你能从“setsid”的角度向我解释一下吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-27
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多