Python daemonize
The process of daemonization in a Linux system always goes through the same process regardless of the development language.
In general, the ID of the parent process is 1 (init process id) through a double fork processing. Also, since the daemon needs to operate regardless of input/output, it dedirects stdout, stderr, and stdin to /dev/null.
Here is a very simple Python code. It simply displays Hello World in the loop statement. The only part I care about is adding code for handling the termination signal.
Normal Python Program
import time import os, sys import signal ''' For Smooth Closing ''' def stop(sig, frame): print('Process Exit') sys.exit(0) signal.signal(signal.SIGINT, stop) signal.signal(signal.SIGTERM, stop) while True: time.sleep(1) print('Hello World')
<normal.py>
If you run the code, you may see this screen output.
[root@gcloud-seoul-a093086b769c683771dee9c71e694a73 python_daemon]# python3 normal.py Hello World Hello World Hello World Hello World ^CProcess Exit
Python Daemonized Program
Let's turn this simple program into a daemon. As mentioned earlier, you can use the double fork method.
import time import os, sys import signal ''' For Smooth Closing ''' def stop(sig, frame): print('Process Exit') sys.exit(0) signal.signal(signal.SIGINT, stop) signal.signal(signal.SIGTERM, stop) # double fork, first fork pid = os.fork() if pid > 0: # parent procrss # just exit exit(0) else: # decouple from parent envronment os.chdir('/') os.setsid() os.umask(0) # second fork pid = os.fork() if pid > 0: exit(0) else: # daemon process does not use stdout, stderr, stdin. So redirect them to dev/null sys.stdout.flush() sys.stderr.flush() si = open(os.devnull, 'r') so = open(os.devnull, 'a+') se = open(os.devnull, 'a+') os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) while True: time.sleep(1) print('Hello World')
<daemon1.py>
If you run the code, you may see this screen output.
[root@gcloud-seoul-a093086b769c683771dee9c71e694a73 python_daemon]# python3 daemon1.py [root@gcloud-seoul-a093086b769c683771dee9c71e694a73 python_daemon]# ps -ef|grep python3 root 7058 1 0 11:38 ? 00:00:00 python3 daemon1.py root 7062 3507 0 11:38 pts/0 00:00:00 grep --color=auto python3
As soon as you run the program, it returns to the prompt state. And if we look for a Python 3 program using the ps command, we can see that process ID 7058 is the process we ran. Also, you can see that the parent process ID has been changed to 1.
This python program is now a daemon and runs in the background, and there is no more screen I/O.
Python Daemonized other Program
import time import os, sys import signal ''' For Smooth Closing ''' def stop(sig, frame): print('Process Exit') sys.exit(0) signal.signal(signal.SIGINT, stop) signal.signal(signal.SIGTERM, stop) ''' start other process and make it daemon ''' # double fork, first fork pid = os.fork() if pid > 0: # parent procrss # just exit exit(0) else: # decouple from parent envronment os.chdir('/') os.setsid() os.umask(0) # second fork pid = os.fork() if pid > 0: exit(0) else: # daemon process does not use stdout, stderr, stdin. So redirect them to dev/null sys.stdout.flush() sys.stderr.flush() si = open(os.devnull, 'r') so = open(os.devnull, 'a+') se = open(os.devnull, 'a+') os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) exec_str = ['/usr/bin/python3', '/usr/local/src/study/python_daemon/normal.py'] os.execv('/usr/bin/python3',exec_str) while True: time.sleep(1) print('Hello World')
<daemon2.py>
This program runs normal.py, which we used as the first example, and daemonizes this process.
[root@gcloud-seoul-a093086b769c683771dee9c71e694a73 python_daemon]# python3 daemon2.py
[root@gcloud-seoul-a093086b769c683771dee9c71e694a73 python_daemon]# ps -ef|grep python3 root 8027 1 7 11:46 ? 00:00:00 /usr/bin/python3 /usr/local/src/study/python_daemon/normal.py root 8029 3507 0 11:46 pts/0 00:00:00 grep --color=auto python3
Wrapping up
The method introduced above can be applied in the same way regardless of the language used, such as C/C++, Python, or Java. Only if your operating system is a Linux system.
댓글
댓글 쓰기