You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Ubuntu cronjob实现任务完成即重启且不重叠运行

可行实现方案

首先纠正你原有cron配置的问题:你当前写的*/20 09-05 * * *不符合9点到17点的运行要求,09-05会匹配9点到次日凌晨5点的时段,需要调整时段规则。

以下是两种可直接落地的实现方案:


方案一:Shell包装脚本+crontab触发(改造成本最低,无需额外依赖)

这个方案通过单脚本控制循环逻辑+锁文件机制,完全满足你的调度要求,天然避免任务重叠。

  1. 新建包装脚本,比如路径为/opt/your_project/run_task.sh,给脚本加执行权限:chmod +x /opt/your_project/run_task.sh
    脚本内容如下,你可以根据实际路径调整变量:
    #!/bin/bash
    # 配置项,根据实际情况修改
    LOCK_FILE="/tmp/python_task.lock" # 普通用户运行建议用/tmp路径,root可用/var/run
    PY_SCRIPT="/opt/your_project/your_task.py" # 你的Python脚本绝对路径
    PYTHON_PATH="/usr/bin/python3" # Python可执行文件绝对路径,避免cron找不到命令
    START_HOUR=9
    END_HOUR=17
    
    # 锁文件检查,避免重复启动任务
    if [ -f "$LOCK_FILE" ]; then
        PID=$(cat "$LOCK_FILE")
        if ps -p "$PID" > /dev/null 2>&1; then
            exit 0
        fi
        # 清理残留锁文件
        rm -f "$LOCK_FILE"
    fi
    echo $$ > "$LOCK_FILE"
    # 脚本退出时自动清理锁文件
    trap 'rm -f "$LOCK_FILE"; exit' INT TERM EXIT
    
    # 时段内循环运行任务
    while true; do
        # 超出运行时段直接退出
        CURRENT_HOUR=$(date +%H)
        if [ "$CURRENT_HOUR" -lt "$START_HOUR" ] || [ "$CURRENT_HOUR" -ge "$END_HOUR" ]; then
            break
        fi
    
        # 运行Python任务,统计执行时长
        START_TS=$(date +%s)
        $PYTHON_PATH $PY_SCRIPT
        END_TS=$(date +%s)
        RUN_DURATION=$((END_TS - START_TS))
    
        # 运行时长小于10分钟(600秒),立即重启任务
        if [ $RUN_DURATION -lt 600 ]; then
            continue
        fi
    
        # 运行时长>=10分钟,计算等待到下一个20分钟调度点的时间
        CURRENT_MIN=$(date +%M)
        WAIT_MIN=$(( (20 - CURRENT_MIN % 20) % 20 ))
        WAIT_SEC=$(( WAIT_MIN * 60 ))
        # 运行时长超过20分钟(1200秒),无需等待直接执行下一次
        if [ $RUN_DURATION -ge 1200 ]; then
            WAIT_SEC=0
        fi
        sleep $WAIT_SEC
    done
    
  2. 修改crontab配置,删除原有的20分钟调度规则,新增一条每天9点触发包装脚本的规则即可:
    0 9 * * * /opt/your_project/run_task.sh
    

方案二:Systemd服务+定时器(更稳定,自带日志、进程管理能力)

适合生产环境使用,Systemd会自动管理进程生命周期,天然避免重复启动,无需手动写锁文件逻辑。

  1. 新建service服务文件/etc/systemd/system/python-task.service:
    [Unit]
    Description=Scheduled Python task
    After=network.target
    
    [Service]
    Type=simple
    User=ubuntu # 替换为实际运行任务的用户
    ExecStart=/usr/bin/python3 /opt/your_project/your_task.py # 替换为实际Python脚本路径
    # 任务退出后立即重启,配合定时器控制调度逻辑
    Restart=on-failure
    RestartSec=0
    # 最长运行8小时,到17点自动停止
    RuntimeMaxSec=28800
    
  2. 新建定时器文件/etc/systemd/system/python-task.timer:
    [Unit]
    Description=Run Python task every 20min between 9-17
    
    [Timer]
    OnCalendar=*-*-* 9-17:0/20:*
    Persistent=true
    
    [Install]
    WantedBy=timers.target
    
  3. 执行命令加载配置并启动定时器:
    systemctl daemon-reload
    systemctl enable --now python-task.timer
    
    该配置下,定时器到点时如果上一次任务还在运行,不会触发新的任务,等上一次运行完成后,下一个调度点再触发,完全避免重叠。如果任务10分钟内退出,Systemd会立即重启任务。

内容的提问来源于stack exchange,提问作者Huzaifa Zahoor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 08:30:02