- run in the background
- not under the control of a user at a terminal.
- When the kernel is bootstrapped it spawns a process called the init process. This process has a ppid of 0 and is the 'grandparent of all processes'. It's the first one and it has no ancestor. Its pid is 1 .
def daemonize_app
if RUBY_VERSION < "1.9"
exit if fork
Process.setsid
exit if fork
Dir.chdir "/"
STDIN.reopen "/dev/null"
STDOUT.reopen "/dev/null", "a"
STDERR.reopen "/dev/null", "a"
else
Process.daemon
end
end
-
Process.daemon does the same thing in the if block through C code
-
Step 1
exit if fork- parsent will exit, and orphaned child process will carry on as normal
- orphaned process's ppid always is 1, This is the only process that the kernel can be sure is active at all times.
- it cause the terminal that invoke this script to think this command is done, returning control to terminal.
-
Step 2
Process.setsid- Process.setsid does three things
- The process become a session leader of a new session
- The process become a process group leader of a new process group
- The process has
no controlling terminal
Using Process.setsid will return the id of the new sesssion group it creates, you can store that if you need it.- Process.setsid will fail in a process that is already a process group leader, it can only be run from child processes. so We need to have
step 1 - Process group
- Each and every process belongs to a group, and each group has a unique integer id
- A process group is just a collection of related processes, typically a parent process and its children
- you can also group your processes arbitrarily by setting their group id using Process.setpgrp(new_group_id)
- Typically the process group id will be the same as the pid of the process group leader.
- The process group leader is the 'originating' process of a terminal command
A child process could carry on when parent process exit but if the parent process is killed by signal this signal will be forward to the whole process group. Child processes will be killed
- Session group
-
A collection of process groups
git log | grep shipped | less In this case each command will get its own process group these commands are not part of the same process group one Ctrl-C will kill them all. These commands are part of the same session group Each invocation from the shell gets its own session group. An invocation may be a single command or a string of commands joined by pipes. -
a session group may be attached to a terminal. It might also not be attached to any terminal, as in the case of a daemon.
-
your terminal handles session groups in a special way: sending a signal to the session leader will forward that signal to all the process groups in that session, which will forward it to all the processes in those process groups
-
- Process.setsid does three things
-
Step 3
exit if fork The forked process that had just become a process group and session group leader So We need to forks again and then exits. This is newly process is no longer process group or session group leader because the previous session process has no controlling terminal- it's guaranteed that this process can never have a controlling terminal. Terminals can only be assigned to session leaders.
-
End
- These three 3 steps ensures that our process is now fully detached from a controlling terminal and will run to its completion.
-
others
Dir.chdir "/" This changes the current working directory to the root directory for the system. This isn't strictly necessary but it's an extra step to ensure that current working directory of the daemon doesn't disappear during its execution.This avoids problems where the directory that the daemon was started from gets deleted or unmounted for any reason.
STDIN.reopen "/dev/null"
STDOUT.reopen "/dev/null", "a"
STDERR.reopen "/dev/null", "a"
This sets all of the standard streams to go to /dev/null , a.k.a. to be ignored. Since the daemon is no longer attached to a terminal session these are of no use anyway. They can't simply be closed because some programs expect them to always be available. Redirecting them to /dev/null ensures that they're still available to the program but have no effect.