【centos】【python】程序单例

需求:

避免同一个程序在不同时刻、终端并行执行;不是绝对不能,是两个同样的程序尽量不要一块执行;

技术:

在程序执行时将pid写入到一个文件里,结束时再删除pid文件,下一个程序先检查pid文件是否存在再决定是否提前终止;

python 复制代码
import datetime
import shutil
from pathlib import Path
import logging
import os
# import fcntl
import psutil
from logging.handlers import RotatingFileHandler


LOG_PATH_PARENT = "./"
LOG_PATH = LOG_PATH_PARENT + "/log"


logger = logging.getLogger()
logger.setLevel(logging.INFO)

formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s')
log_abs_file = os.path.join(LOG_PATH_PARENT, 'suri_logrotate.log')

handler = RotatingFileHandler(log_abs_file, maxBytes=1024 * 1024 * 10, backupCount=10)  # 大小10MB , 10个
handler.setFormatter(formatter)
logger.addHandler(handler)

console = logging.StreamHandler()
console.setFormatter(formatter)
logger.addHandler(console)



class SingletonProgress:

    def _get_lock(self):
        """开启进程占用锁,确保其他同名称进程不再重复运行"""
        # file_name = os.path.basename(__file__)
        # lock_file_name = f"/var/run/{file_name}.pid"
        # self.fd = open(self.lock_file_name, "w")
        if not os.path.exists(self.lock_file_name):
            with open(self.lock_file_name, "w", encoding='utf-8') as f:
                f.write(str(os.getpid()))
        else:
            if os.path.exists(self.lock_file_name):
                print(self.lock_file_name)
                with open(self.lock_file_name, 'r', encoding='utf8') as f:
                    pid = f.read().strip()
                if not pid:
                    logger.error("Program abnormal exit,no pid, Please try again.")
                    os.remove(self.lock_file_name)
                elif pid and pid.isdigit() and int(pid) not in psutil.pids():
                    logger.error("Program abnormal exit,pid err, Please try again.")
                    os.remove(self.lock_file_name)
                elif self.file_name not in psutil.Process(int(pid)).cmdline():
                    logger.error("Program abnormal exit,pid not, Please try again.")
                    os.remove(self.lock_file_name)
                else:
                    logger.info(f"{self.file_name} have another instance running.")
                    self.remove_lock_file = False

                exit(1)

    def __init__(self):
        self.file_name = os.path.basename(__file__)
        self.lock_file_name = os.path.join(LOG_PATH_PARENT, self.file_name+'.pid')
        self.remove_lock_file = True
        self.err_delete_lock_file_name = False
        self._get_lock()

    def __del__(self):
        # 占用锁的进程被关闭后,释放锁
        if self.remove_lock_file:
            os.remove(self.lock_file_name)


def method():
    import time
    while 1:
        time.sleep(1)
        logger.info(str(os.getpid()))


if __name__ == '__main__':

    keep_lock = SingletonProgress()
    method()
    # del keep_lock
相关推荐
Java面试题总结9 分钟前
基于 Java 的 PDF 文本水印实现方案(iText7 示例)
java·python·pdf
不懒不懒11 分钟前
【决策树算法实战指南:从原理到Python实现】
python·决策树·id3·c4.5·catr
马猴烧酒.21 分钟前
【面试八股|Java集合】Java集合常考面试题详解
java·开发语言·python·面试·八股
-Try hard-30 分钟前
Linuv软件编程 | Shell命令
linux·运维·服务器
释怀不想释怀32 分钟前
Linux快捷键,软件安装启动
linux·运维·服务器
天空属于哈夫克336 分钟前
Java 版:利用外部群 API 实现自动“技术开课”倒计时提醒
数据库·python·mysql
喵手1 小时前
Python爬虫实战:全站 Sitemap 自动发现 - 解析 sitemap.xml → 自动生成抓取队列的工业级实现!
爬虫·python·爬虫实战·零基础python爬虫教学·sitemap·解析sitemap.xml·自动生成抓取队列实现
Hello World . .1 小时前
Linux:软件编程
linux·运维·服务器·vim
luoluoal1 小时前
基于深度学习的web端多格式纠错系统(源码+文档)
python·mysql·django·毕业设计·源码
深蓝海拓1 小时前
PySide6从0开始学习的笔记(二十七) 日志管理
笔记·python·学习·pyqt