python 은 fork 를 사용 하여 데 몬 을 실현 하 는 방법
os.fork()
하위 프로 세 스 가 실 행 될 때 os.fork 방법 은 0 으로 돌아 갑 니 다.
부모 프로 세 스 가 실 행 될 때 os.fork 방법 은 하위 프로 세 스 의 PID 번 호 를 되 돌려 줍 니 다.
따라서 PID 를 사용 하여 두 프로 세 스 를 구분 할 수 있 습 니 다.
#!/usr/bin/env python
#coding=utf8
from time import sleep
import os
try:
pid = os.fork()
except OSError, e:
pass
sleep(30)
실행 코드,프로 세 스 보기:
[root@localhost ~]# python test2.py &
[1] 2464
[root@localhost ~]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 2379 2377 0 80 0 - 28879 wait pts/1 00:00:00 bash
0 S 0 2464 2379 0 80 0 - 31318 poll_s pts/1 00:00:00 python
1 S 0 2465 2464 0 80 0 - 31318 poll_s pts/1 00:00:00 python
0 R 0 2466 2379 0 80 0 - 37227 - pts/1 00:00:00 ps
두 번 째 python 프로 세 스 가 첫 번 째 하위 프로 세 스 임 을 알 수 있 습 니 다.방금 말 한 바 와 같이 os.fork()방법 구역 분자 프로 세 스 와 부모 프로 세 스
#-*- coding:utf-8 -*-
from time import sleep
import os
print('start+++++++++++++')
#
source = 10
try:
pid = os.fork()
print('pid=',pid)
if pid == 0: #
print("this is child process.")
source = source - 1 # source 1
else: #
print("this is parent process." )
print(source)
except (OSError,e):
pass
print('END---------------')
면 코드 에 서 는 하위 프로 세 스 가 생 성 되 기 전에 변수 source 를 설명 한 다음 하위 프로 세 스 에서 1 을 줄 이 고 마지막 으로 source 의 값 을 출력 합 니 다.부모 프로 세 스 가 인쇄 한 값 은 10 이 어야 하고 하위 프로 세 스 가 인쇄 한 값 은 9 여야 합 니 다.
[root@localhost ~]# python test3.py
start+++++++++++++
pid= 2550
this is parent process.
10
END---------------
pid= 0
this is child process.
9
END---------------
간단 한 데 몬 예:
def main():
''' '''
pass
#
def createDaemon():
''' ( ) '''
# fork ( fork , , )
try:
if os.fork() > 0:
sys.exit(0)
except OSError, error:
print '(fork )fork #1 failed: %d (%s)' % (error.errno, error.strerror)
sys.exit(1)
''' '''
###### , ppid = 1, , 。
###### 。 , , 。
###### 。
os.chdir('/') # / ( )
os.setsid() #
os.umask(0) # ( rwx)
''' ( ) '''
# fork ( fork , , )
try:
pid = os.fork()
if pid > 0:
print 'Daemon PID %d' % pid
sys.exit(0)
except OSError, error:
print '(fork )fork #2 failed: %d (%s)' % (error.errno, error.strerror)
sys.exit(1)
''' '''
####### try , 。 ppid=1。
####### , 。
# IO( , 、 、 )
# sys.stdout.flush() #
# sys.stderr.flush() #
# inputS = file("/dev/null", 'r') # inputS
# outputS = file("/dev/null", 'a+') # outputS
# errorS = file("/dev/null", 'a+', 0) # errorS
# os.dup2(inputS.fileno(), sys.stdin.fileno()) # inputS 。
# os.dup2(so.fileno(), sys.stdout.fileno()) # outputS 。
# os.dup2(se.fileno(), sys.stderr.fileno()) # errorS 。
main() # main
if __name__ == "__main__":
if platform.system() == "Linux":
createDaemon()
else:
sys.exit()
제어 인자 가 있 는 예:데 몬 의 기본 클래스 를 작성 하여 계승 에 사용 합 니 다:
# coding: utf-8
import os
import sys
import time
import atexit
import signal
class Daemon:
def __init__(self, pidfile='/tmp/daemon.pid', stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
def daemonize(self):
if os.path.exists(self.pidfile):
raise RuntimeError('Already running.')
# First fork (detaches from parent)
try:
if os.fork() > 0:
raise SystemExit(0)
except OSError as e:
raise RuntimeError('fork #1 faild: {0} ({1})
'.format(e.errno, e.strerror))
os.chdir('/')
os.setsid()
os.umask(0o22)
# Second fork (relinquish session leadership)
try:
if os.fork() > 0:
raise SystemExit(0)
except OSError as e:
raise RuntimeError('fork #2 faild: {0} ({1})
'.format(e.errno, e.strerror))
# Flush I/O buffers
sys.stdout.flush()
sys.stderr.flush()
# Replace file descriptors for stdin, stdout, and stderr
with open(self.stdin, 'rb', 0) as f:
os.dup2(f.fileno(), sys.stdin.fileno())
with open(self.stdout, 'ab', 0) as f:
os.dup2(f.fileno(), sys.stdout.fileno())
with open(self.stderr, 'ab', 0) as f:
os.dup2(f.fileno(), sys.stderr.fileno())
# Write the PID file
with open(self.pidfile, 'w') as f:
print(os.getpid(), file=f)
# Arrange to have the PID file removed on exit/signal
atexit.register(lambda: os.remove(self.pidfile))
signal.signal(signal.SIGTERM, self.__sigterm_handler)
# Signal handler for termination (required)
@staticmethod
def __sigterm_handler(signo, frame):
raise SystemExit(1)
def start(self):
try:
self.daemonize()
except RuntimeError as e:
print(e, file=sys.stderr)
raise SystemExit(1)
self.run()
def stop(self):
try:
if os.path.exists(self.pidfile):
with open(self.pidfile) as f:
os.kill(int(f.read()), signal.SIGTERM)
else:
print('Not running.', file=sys.stderr)
raise SystemExit(1)
except OSError as e:
if 'No such process' in str(e) and os.path.exists(self.pidfile):
os.remove(self.pidfile)
def restart(self):
self.stop()
self.start()
def run(self):
#
pass
클래스 만 들 기:
#
from daemon import Daemon
#
class MyTestDaemon(Daemon):
# run ,
def run(self):
# , shell
sys.stdout.write('Daemon started with pid {}
'.format(os.getpid()))
while True:
sys.stdout.write('Daemon Alive! {}
'.format(time.ctime()))
sys.stdout.flush()
time.sleep(5)
if __name__ == '__main__':
PIDFILE = '/tmp/daemon-example.pid'
LOG = '/tmp/daemon-example.log'
daemon = MyTestDaemon(pidfile=PIDFILE, stdout=LOG, stderr=LOG)
if len(sys.argv) != 2:
print('Usage: {} [start|stop]'.format(sys.argv[0]), file=sys.stderr)
raise SystemExit(1)
if 'start' == sys.argv[1]:
daemon.start()
elif 'stop' == sys.argv[1]:
daemon.stop()
elif 'restart' == sys.argv[1]:
daemon.restart()
else:
print('Unknown command {!r}'.format(sys.argv[1]), file=sys.stderr)
raise SystemExit(1)
포크두 번 째 포크 는 필수 가 아 닙 니 다.프로 세 스 가 제어 단말 기 를 여 는 것 을 방지 하기 위해 서 입 니 다.
제어 단말 기 를 여 는 조건 은 이 프로 세 스 가 session leader 여야 한 다 는 것 입 니 다.첫 번 째 fork,setsid 이후 하위 프로 세 스 는 session leader 가 되 었 고 프로 세 스 는 터미널 을 열 수 있 습 니 다.두 번 째 fork 에서 발생 하 는 프로 세 스 는 session leader 가 아니 라 프로 세 스 는 터미널 을 열 수 없습니다.
즉,프로그램 이 잘 이 루어 지면 제어 프로그램 이 자발적으로 단말 기 를 열지 않 고 두 번 째 fork 가 없어 도 된다 는 것 이다.
코드 구현
# coding: utf-8
import os
import sys
import time
import atexit
import signal
class Daemon:
def __init__(self, pidfile='/tmp/daemon.pid', stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
def daemonize(self):
if os.path.exists(self.pidfile):
raise RuntimeError('Already running.')
# First fork (detaches from parent)
try:
if os.fork() > 0:
raise SystemExit(0)
except OSError as e:
raise RuntimeError('fork #1 faild: {0} ({1})
'.format(e.errno, e.strerror))
os.chdir('/')
os.setsid()
os.umask(0o22)
# Second fork (relinquish session leadership)
try:
if os.fork() > 0:
raise SystemExit(0)
except OSError as e:
raise RuntimeError('fork #2 faild: {0} ({1})
'.format(e.errno, e.strerror))
# Flush I/O buffers
sys.stdout.flush()
sys.stderr.flush()
# Replace file descriptors for stdin, stdout, and stderr
with open(self.stdin, 'rb', 0) as f:
os.dup2(f.fileno(), sys.stdin.fileno())
with open(self.stdout, 'ab', 0) as f:
os.dup2(f.fileno(), sys.stdout.fileno())
with open(self.stderr, 'ab', 0) as f:
os.dup2(f.fileno(), sys.stderr.fileno())
# Write the PID file
with open(self.pidfile, 'w') as f:
print(os.getpid(), file=f)
# Arrange to have the PID file removed on exit/signal
atexit.register(lambda: os.remove(self.pidfile))
signal.signal(signal.SIGTERM, self.__sigterm_handler)
# Signal handler for termination (required)
@staticmethod
def __sigterm_handler(signo, frame):
raise SystemExit(1)
def start(self):
try:
self.daemonize()
except RuntimeError as e:
print(e, file=sys.stderr)
raise SystemExit(1)
self.run()
def stop(self):
try:
if os.path.exists(self.pidfile):
with open(self.pidfile) as f:
os.kill(int(f.read()), signal.SIGTERM)
else:
print('Not running.', file=sys.stderr)
raise SystemExit(1)
except OSError as e:
if 'No such process' in str(e) and os.path.exists(self.pidfile):
os.remove(self.pidfile)
def restart(self):
self.stop()
self.start()
def run(self):
pass
사용 테스트
import os
import sys
import time
from daemon import Daemon
class MyTestDaemon(Daemon):
def run(self):
sys.stdout.write('Daemon started with pid {}
'.format(os.getpid()))
while True:
sys.stdout.write('Daemon Alive! {}
'.format(time.ctime()))
sys.stdout.flush()
time.sleep(5)
if __name__ == '__main__':
PIDFILE = '/tmp/daemon-example.pid'
LOG = '/tmp/daemon-example.log'
daemon = MyTestDaemon(pidfile=PIDFILE, stdout=LOG, stderr=LOG)
if len(sys.argv) != 2:
print('Usage: {} [start|stop]'.format(sys.argv[0]), file=sys.stderr)
raise SystemExit(1)
if 'start' == sys.argv[1]:
daemon.start()
elif 'stop' == sys.argv[1]:
daemon.stop()
elif 'restart' == sys.argv[1]:
daemon.restart()
else:
print('Unknown command {!r}'.format(sys.argv[1]), file=sys.stderr)
raise SystemExit(1)
[daemon] python test.py start 23:45:42
[daemon] cat /tmp/daemon-example.pid 23:45:49
8532
[daemon] ps -ef|grep 8532 | grep -v grep 23:46:07
502 8532 1 0 11:45 ?? 0:00.00 python test.py start
[daemon] tail -f /tmp/daemon-example.log 23:46:20
Daemon started with pid 8532
Daemon Alive! Fri Dec 2 23:45:49 2016
Daemon Alive! Fri Dec 2 23:45:54 2016
Daemon Alive! Fri Dec 2 23:45:59 2016
Daemon Alive! Fri Dec 2 23:46:04 2016
Daemon Alive! Fri Dec 2 23:46:09 2016
Daemon Alive! Fri Dec 2 23:46:14 2016
Daemon Alive! Fri Dec 2 23:46:19 2016
Daemon Alive! Fri Dec 2 23:46:24 2016
Daemon Alive! Fri Dec 2 23:46:29 2016
Daemon Alive! Fri Dec 2 23:46:34 2016
[daemon] python test.py stop 23:46:36
[daemon] ps -ef|grep 8532 | grep -v grep 23:46:43
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
로마 숫자를 정수로 또는 그 반대로 변환그 중 하나는 로마 숫자를 정수로 변환하는 함수를 만드는 것이었고 두 번째는 그 반대를 수행하는 함수를 만드는 것이었습니다. 문자만 포함합니다'I', 'V', 'X', 'L', 'C', 'D', 'M' ; 문자열이 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.