I read the book I see, Unix processes-the basics of Unix learned in Ruby. It explains the concept of a process using Ruby code. I was impressed with the very easy-to-understand book: joy:
I would like to replace some of the Ruby code in the book with Python for review. Since it's a big deal, I implemented the process daemonization that I thought was the most practical.
from datetime import datetime
import os
import sys
import time
def daemonize():
"""
Daemonize the process.
"""
def fork():
if os.fork():
sys.exit()
def throw_away_io():
stdin = open(os.devnull, 'rb')
stdout = open(os.devnull, 'ab+')
stderr = open(os.devnull, 'ab+', 0)
for (null_io, std_io) in zip((stdin, stdout, stderr),
(sys.stdin, sys.stdout, sys.stderr)):
os.dup2(null_io.fileno(), std_io.fileno())
fork()
os.setsid()
fork()
throw_away_io()
def create_empty_file():
"""
Outputs a text file with the current time as the file name.
The process pid that output this file is entered in the file.
"""
now = datetime.now().strftime('%Y%m%d%H%M%S')
filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)),
f'tmp/{now}.txt')
with open(filepath, 'w') as f:
f.write(str(os.getpid()))
def create_empty_files(interval=60):
"""
interval create every second_empty_file()To call.
"""
while True:
create_empty_file()
time.sleep(interval)
if __name__ == '__main__':
daemonize()
create_empty_files()
The code above calls fork () twice.
def fork()
if os.fork():
sys.exit()
In os.fork (), the pid of the child process is returned in the parent process, and 0 is returned in the child process. That is, the parent process terminates and the child process survives.
os.setsid () is as its name suggests setsid () /html/LDP_man-pages/man2/setsid.2.html) Invoke the system call. And setsid () does three things [^ 1]:
This causes the child process that called os.setsid () to become the leader of the new session (and the new process group for that session) and no longer have a controlling terminal. However, it seems that it is technically possible to reset the control terminal to a session [^ 2].
The second os.fork () terminates the process that was the leader of the session and process group and spawns a new child process. Since the terminated session reader has no control terminal, and the new child process is not the session leader, this can guarantee that it will never have a control terminal. The daemon process is complete.
def throw_away_io():
stdin = open(os.devnull, 'rb')
stdout = open(os.devnull, 'ab+')
stderr = open(os.devnull, 'ab+', 0)
for (null_io, std_io) in zip((stdin, stdout, stderr),
(sys.stdin, sys.stdout, sys.stderr)):
os.dup2(null_io.fileno(), std_io.fileno())
Throw away all standard streams by sending them to / dev / null
. This is because the daemon process does not have a controlling terminal, so these resources are no longer needed. The reason why the standard stream is sent to / dev / null
instead of closing is that the standard stream is still available from the outside in consideration of the external program that assumes the use of the standard stream. It seems to be to make it look like it is.
$ python main.py
$ ps aux | grep -v grep | grep python
quanon 4621 0.0 0.0 2418360 2996 ?? S 11:46PM 0:00.00 python main.py
$ cat tmp/20170520234627.txt
4621⏎
A handmade daemon process keeps running in the background: innocent:
If you feel like it, I want to read the code of python-daemon: sunglasses:
Web
[^ 1]: It is assumed that the calling process is not the process group leader. [^ 2]: No details are mentioned in the book. In the article Unix daemon mechanism, "Old System V In the wiki / UNIX_System_V) system, I was able to connect the control terminal to the session leader process later, so I am doing it for historical reasons. "
Recommended Posts