Reputation: 91
$ 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.
Upvotes: 3
Views: 2571
Reputation: 112
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:
Upvotes: 3
Reputation: 142585
Your first script waits for setsid sleep 100
to be finished and then returns (in other words it will return after sleep finishes, 100 seconds here), but the 2nd script don't waits for the command to finish, cause &
puts the command in background and returns immediately. To quote 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.
Also note that &
is a control operator and it has higher precedence. Hope this helps!
Upvotes: 0