一些服务进程在在启动的时候会生成一个.pid文件, 里面包含了当前进程的pid. 这个.pid文件主要有两种作用:
- 方便杀死/重启当前进程
- 通过添加文件锁实现对该文件的互斥访问, 防止生成多个进程.
使用python的fcntl模块模拟实现
import os
import sys
import time
import fcntl
from signal import signal, SIGHUP, SIGTERM, SIGINT
import fire
class Server:
def __init__(self, pidfile):
self.pidfile = pidfile
self.setup()
def setup(self):
print(f'setup pid {os.getpid()}')
self.fileno = open(self.pidfile, 'w')
self.fileno.write(str(os.getpid()))
self.fileno.flush()
fcntl.flock(self.fileno, fcntl.LOCK_EX | fcntl.LOCK_NB)
def shutdown(self):
print('shutdown')
fcntl.flock(self.fileno, fcntl.LOCK_UN)
self.fileno.close()
os.remove(self.pidifle)
sys.exit(0)
def run(self):
while True:
print(f'running pidfile {self.pidfile} pid {os.getpid()}')
time.sleep(3)
def main(pidfile_path):
server = Server(pidfile_path)
server.run()
signal(SIGHUP, lambda s, f: server.restart())
signal(SIGTERM, lambda s, f: server.stop())
signal(SIGINT, lambda s, f: server.stop())
if __name__ == '__main__':
fire.Fire(main)
通过下面命令启动该服务
python pythonpid.py ./pid.pid
然后再次启动的时候会报错
BlockingIOError: [Errno 35] Resource temporarily unavailable
如果想要停止该服务,用到下面的命令
kill -SIGTERM $(cat pid.pid)