Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why setsid could not exit from shell script?

$ cat test1.sh
#!/bin/bash

setsid sleep 100

'test1.sh' shell script will not exit at once.

$ cat test2.sh
#!/bin/bash

setsid sleep 100 &

'test2.sh' shell script will exit at once.

Could anyone explain for me? Thanks a lot.

like image 695
user3015856 Avatar asked May 25 '26 14:05

user3015856


1 Answers

The question is probably a duplicate of this even older question, and the answer over there is quite useful. Perhaps these should be merged.

I was also surprised by this behaviour of setsid. So I checked the man page:

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.

Some jargon to understand here. Let's check the POSIX definitions list (chapter 3).

A session is:

A collection of process groups established for job control purposes. Each process group is a member of a session. A process is considered to be a member of the session of which its process group is a member. A newly created process joins the session of its creator. A process can alter its session membership; see setsid(). There can be multiple process groups in the same session.

The fork() call creates a new process by copying the current process. More info in this post.

A process group leader is:

A process whose process ID is the same as its process group ID.

So, setsid will only create a new process if it is executed as a process group leader. This is always the case when running a command directly in the shell, so that the job queue can be constructed as a list of process groups. However, when run as part of a script, the group leader is the new shell process used to run the script.

Luckily, we have the --fork option to force creation of a new process. For example, the shell script:

#!/bin/env bash
setsid --fork sleep 5

will exit without waiting for sleep to finish, and the sleep command will continue even if you close the shell from which the script was run. As far as I am aware, setsid --fork is the only way to properly ensure that a command is run as a detached process.

Other resources:

  • Forum discussion about setsid
  • Source code for setsid
  • Blog post explaining the difference compared to nohup
like image 156
adigitoleo Avatar answered May 28 '26 05:05

adigitoleo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!