首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >linux命令setsid

linux命令setsid
EN

Stack Overflow用户
提问于 2012-03-13 09:46:56
回答 2查看 29.2K关注 0票数 16

我正在尝试编写一个包装器,它将作为会话领导者执行脚本。我对linux命令setsid的行为感到困惑。考虑一下这个名为test.sh的脚本

代码语言:javascript
复制
#!/bin/bash
SID=$(ps -p $$ --no-headers -o sid)
if [ $# -ge 1 -a $$ -ne $SID ] ; then
  setsid bash test.sh
  echo pid=$$ ppid=$PPID sid=$SID parent
else
  sleep 2
  echo pid=$$ ppid=$PPID sid=$SID child
  sleep 2
fi

根据输出是执行的还是源的,输出会有所不同:

代码语言:javascript
复制
$ bash
$ SID=$(ps -p $$ --no-headers -o sid)
$ echo pid=$$ ppid=$PPID sid=$SID
pid=9213 ppid=9104 sid= 9104
$ ./test.sh 1 ; sleep 5
pid=9326 ppid=9324 sid= 9326 child
pid=9324 ppid=9213 sid= 9104 parent
$ . ./test.sh 1 ; sleep 5
pid=9213 ppid=9104 sid= 9104 parent
pid=9336 ppid=1 sid= 9336 child
$ echo $BASH_VERSION 
4.2.8(1)-release
$ exit
exit

因此,在我看来,setsid在脚本获得源代码时会立即返回,但它会在脚本执行时等待其子对象。为什么控制tty的存在会与setsid有关?谢谢!

编辑:为了清楚起见,我为所有相关命令添加了pid/ppid/sid报告。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-03-13 22:24:42

The source code of the setsid utility实际上是非常简单的。您将注意到,它只有在发现自己的进程ID和进程组ID相等时才返回s(即,如果它看到自己是进程组领导者)-并且它从不为其子进程wait()s :如果它fork()s,则父进程将立即返回。如果它不是fork(),那么它看起来就像是一个孩子的wait()ing,但实际上发生的只是这个孩子,而Bash就是wait()ing (就像它总是做的那样)。(当然,当它真正执行fork()时,Bash不能为它创建的子进程执行wait(),因为它为他们的子进程处理wait(),而不是为他们的孙子进程。)

所以你看到的行为是不同行为的直接结果:

  • 当您运行. ./test.shsource ./test.sh或诸如此类的东西时-或者就此而言,当您直接从Bash提示符运行setsid时- Bash将使用一个新的进程组ID启动setsid以用于job control目的,因此setsid将具有与其进程组ID相同的进程ID(即,它是进程组领导者),因此它将运行而不会运行< fork() >d22或bash test.sh或诸如此类的,并启动setsid,等待将作为运行它的脚本的同一进程组的一部分,因此它的process-ID和process - setsid -ID将不同,所以它不会等待,所以它将显示为fork() (没有实际的等待
票数 22
EN

Stack Overflow用户

发布于 2012-03-13 14:12:26

我不认为你的脚本有任何问题。我在代码中添加了额外的语句来查看发生了什么:

代码语言:javascript
复制
    #!/bin/bash

    ps -H -o pid,ppid,sid,cmd

    echo '$$' is $$

    SID=`ps -p $$ --no-headers -o sid`

    if [ $# -ge 1 -a $$ -ne $SID ] ; then
      setsid bash test.sh
      echo pid=$$ ppid=$PPID sid=$SID parent
    else
      sleep 2
      echo pid=$$ ppid=$PPID sid=$SID child
      sleep 2
    fi

你所关心的情况是:

代码语言:javascript
复制
./test.sh 1 

相信我,运行这个修改过的脚本,你就会明白到底发生了什么。如果不是会话领导者的shell运行该脚本,那么它将直接转到else块。我是不是遗漏了什么?

我现在明白您的意思了:当您按原样对脚本执行./test.sh 1时,parent将等待孩子完成。子项阻止父项。但是如果你在后台启动了子进程,那么你会注意到父进程先于子进程完成。因此,只需在您的脚本中进行以下更改:

代码语言:javascript
复制
      setsid bash test.sh &
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9677306

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档