一个锁,保证同时间只有一个python3在运行当前脚本

主要用途是使用cron定时运行脚本的时候,避免重复运行

import os
import sys
import asyncio
import signal
import logging
import traceback

logging.basicConfig(filename='./script.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
LOCK_FILE = "/tmp/script.lock"

async def main():
    try:
        # 在这里编写你的主任务逻辑
        pass
    except asyncio.CancelledError:
        log_message = "主任务被取消"
        logging.info(log_message)
    except Exception as e:
        log_message = f"错误信息 = {e}, trace = {traceback.format_exc()}"
        logging.error(log_message)

async def stop_program():
    asyncio.get_running_loop().stop()

def handle_sigterm():
    log_message = "收到 SIGTERM 信号,正在退出..."
    logging.info(log_message)
    asyncio.create_task(stop_program())

async def start():
    # 检查是否存在锁文件
    if os.path.exists(LOCK_FILE):
        with open(LOCK_FILE, 'r') as f:
            pid = f.read().strip()
        # 如果锁文件存在,并且其中记录的进程 ID 不是当前进程 ID,则说明已经有另一个进程在运行该脚本,因此退出
        if pid.isdigit() and int(pid) != os.getpid():
            log_message = f"Another pid({pid}) is already running this script. Exiting."
            logging.error(log_message)
            sys.exit(0)  # 正常退出
        else:  # 锁文件不存在或者pid就是当前pid
            with open(LOCK_FILE, 'w') as f:
                f.write(str(os.getpid()))
    else:
        # 如果锁文件不存在,则创建并写入当前进程 ID
        with open(LOCK_FILE, 'w') as f:
            f.write(str(os.getpid()))

    try:
        # 创建并执行主任务
        run_main_task = asyncio.create_task(main())
        await run_main_task
    except KeyboardInterrupt:
        logging.error("收到键盘中断信号,正在退出...")
        if not run_main_task.done():
            run_main_task.cancel()  # 取消主任务
            await run_main_task  # 等待主任务完成
    finally:
        # 无论脚本是否成功执行,都删除锁文件
        os.remove(LOCK_FILE)

# 设置 SIGTERM 信号处理函数
signal.signal(signal.SIGTERM, handle_sigterm)

# 启动事件循环
asyncio.run(start())
Last modification:September 10, 2024
V50%看看实力