Python實(shí)現(xiàn)多BAT文件分時(shí)段每日自動(dòng)執(zhí)行
很多開(kāi)發(fā)者、運(yùn)維日常都會(huì)用到 Windows 定時(shí)任務(wù),用來(lái)自動(dòng)執(zhí)行 BAT 批處理腳本、數(shù)據(jù)備份、日志清理、程序重啟等操作。但幾乎所有人都遇到過(guò)一個(gè)無(wú)解問(wèn)題:定時(shí)任務(wù)時(shí)而運(yùn)行、時(shí)而不運(yùn)行,手動(dòng)點(diǎn)擊執(zhí)行百分百正常,到點(diǎn)卻莫名失效。
尤其是需要多個(gè) BAT 文件、不同時(shí)間段分開(kāi)運(yùn)行的場(chǎng)景,原生 Windows 計(jì)劃任務(wù)配置繁瑣、隱性坑極多,經(jīng)常出現(xiàn)任務(wù)卡死、憑據(jù)失效、條件攔截、進(jìn)程堆積等問(wèn)題。
本文將深度剖析 Windows 定時(shí)任務(wù)間歇性失效的核心原因,并提供兩套成熟可用的 Python 多時(shí)段調(diào)度 BAT 方案,一套輕量化常駐運(yùn)行、一套系統(tǒng)級(jí)穩(wěn)定無(wú)人值守,徹底根治定時(shí)任務(wù)失效問(wèn)題,開(kāi)箱即用。
一、先搞懂:為什么 Windows 定時(shí)任務(wù)偶爾不運(yùn)行?(核心坑點(diǎn))
絕大多數(shù)定時(shí)任務(wù)失效,不是系統(tǒng) bug,是隱性配置不匹配、運(yùn)行環(huán)境不一致導(dǎo)致,手動(dòng)運(yùn)行和定時(shí)運(yùn)行是兩套完全不同的環(huán)境。
1.1 運(yùn)行身份與憑據(jù)失效(最高頻)
默認(rèn)勾選「僅當(dāng)用戶(hù)登錄時(shí)運(yùn)行」,電腦鎖屏、注銷(xiāo)、重啟后無(wú)人登錄,任務(wù)直接跳過(guò)。
同時(shí),如果選擇「不管用戶(hù)是否登錄都要運(yùn)行」,保存的是當(dāng)時(shí)的賬戶(hù)密碼,Windows 修改登錄密碼后,定時(shí)任務(wù)憑據(jù)直接過(guò)期,出現(xiàn)隨機(jī)失效。
普通用戶(hù)權(quán)限不足,會(huì)導(dǎo)致讀寫(xiě)系統(tǒng)目錄、操作共享文件、執(zhí)行權(quán)限命令間歇性失敗。
1.2 條件規(guī)則攔截(最隱蔽)
計(jì)劃任務(wù)「條件」選項(xiàng)卡中,任意一條不滿(mǎn)足,任務(wù)直接不觸發(fā),且日志提示極不明顯:
- 筆記本默認(rèn)勾選「僅交流電源運(yùn)行」,電池模式直接跳過(guò)任務(wù)
- 開(kāi)啟「僅計(jì)算機(jī)空閑時(shí)運(yùn)行」,電腦有操作、CPU占用高則不執(zhí)行
- 綁定網(wǎng)絡(luò)連接,Wi-Fi/網(wǎng)線短暫斷連,任務(wù)直接終止
1.3 工作目錄與路徑問(wèn)題(手動(dòng)正常、定時(shí)異常)
手動(dòng)運(yùn)行 BAT 時(shí),工作目錄是腳本所在文件夾;Windows 定時(shí)任務(wù)默認(rèn)工作目錄是 C:\Windows\System32。
如果 BAT 腳本中使用相對(duì)路徑讀取文件、調(diào)用程序,定時(shí)運(yùn)行會(huì)直接找不到文件,表現(xiàn)為“任務(wù)啟動(dòng)了但沒(méi)效果”。同時(shí)路徑含空格不加分號(hào),也會(huì)導(dǎo)致執(zhí)行失敗。
1.4 任務(wù)卡死、進(jìn)程堆積阻塞后續(xù)任務(wù)
默認(rèn)配置:任務(wù)正在運(yùn)行時(shí),不啟動(dòng)新實(shí)例。如果上一次 BAT 腳本卡死、進(jìn)程常駐,后續(xù)所有定時(shí)任務(wù)全部跳過(guò),是典型的“第一次正常、后續(xù)全失效”。
二、多 BAT 分時(shí)段運(yùn)行方案選型
針對(duì)「多個(gè) BAT 文件、不同時(shí)間每日定時(shí)運(yùn)行」的需求,提供兩套落地方案,按需選擇:
| 方案 | 優(yōu)點(diǎn) | 缺點(diǎn) | 適用場(chǎng)景 |
|---|---|---|---|
| Python Schedule 常駐調(diào)度 | 配置簡(jiǎn)單、一鍵修改時(shí)間和腳本、無(wú)需操作系統(tǒng)計(jì)劃任務(wù) | 需要常駐運(yùn)行、窗口關(guān)閉即失效、重啟需手動(dòng)啟動(dòng) | 測(cè)試環(huán)境、短期定時(shí)、頻繁修改任務(wù) |
| Windows系統(tǒng)計(jì)劃任務(wù)+Python入口 | 系統(tǒng)級(jí)穩(wěn)定、后臺(tái)運(yùn)行、鎖屏重啟不失效、任務(wù)互不干擾 | 配置稍多,需管理員權(quán)限創(chuàng)建任務(wù) | 生產(chǎn)環(huán)境、長(zhǎng)期無(wú)人值守、服務(wù)器運(yùn)行 |
三、方案一:Python 常駐定時(shí)(多 BAT 分時(shí)段執(zhí)行)
基于 schedule 庫(kù)實(shí)現(xiàn),單文件配置所有任務(wù),支持自定義時(shí)間、多腳本、超時(shí)防卡死、日志輸出,新手友好。
3.1 安裝依賴(lài)
pip install schedule
3.2 完整可運(yùn)行代碼
import schedule
import time
import subprocess
from pathlib import Path
# ====================== 自定義配置區(qū)(按需修改)======================
# 格式:(每日?qǐng)?zhí)行時(shí)間, BAT腳本絕對(duì)路徑)
task_list = [
("08:30", r"D:\script\a.bat"),
("12:10", r"D:\script\b.bat"),
("18:45", r"D:\script\c.bat"),
("22:00", r"D:\script\d.bat"),
]
RUN_TIMEOUT = 3600 # 任務(wù)最大運(yùn)行時(shí)長(zhǎng)(秒),防止卡死
# ====================================================================
def execute_bat(bat_path):
"""執(zhí)行單個(gè)BAT腳本并輸出日志"""
bat_file = Path(bat_path)
work_dir = str(bat_file.parent)
now_str = time.strftime("%Y-%m-%d %H:%M:%S")
print(f"\n[{now_str}] 開(kāi)始執(zhí)行任務(wù):{bat_path}")
try:
# 指定工作目錄、捕獲輸出、超時(shí)終止
proc = subprocess.run(
bat_path,
cwd=work_dir,
shell=True,
capture_output=True,
text=True,
timeout=RUN_TIMEOUT
)
print("任務(wù)輸出:\n", proc.stdout)
if proc.stderr:
print("任務(wù)錯(cuò)誤:\n", proc.stderr)
print(f"任務(wù)執(zhí)行完成,返回碼:{proc.returncode}")
except subprocess.TimeoutExpired:
print(f"【超時(shí)終止】{bat_path} 運(yùn)行超時(shí),已強(qiáng)制結(jié)束進(jìn)程")
except Exception as e:
print(f"【執(zhí)行異常】{bat_path} 出錯(cuò):{str(e)}")
# 批量注冊(cè)所有定時(shí)任務(wù)
for run_time, bat_path in task_list:
schedule.every().day.at(run_time).do(execute_bat, bat_path=bat_path)
print(f"? 注冊(cè)成功:每日 {run_time} 執(zhí)行 {bat_path}")
print("\n?? 多任務(wù)定時(shí)調(diào)度已啟動(dòng),保持窗口打開(kāi)即可運(yùn)行")
# 持續(xù)檢測(cè)定時(shí)任務(wù)
while True:
schedule.run_pending()
time.sleep(20)3.3 優(yōu)缺點(diǎn)說(shuō)明
優(yōu)勢(shì):無(wú)需操作系統(tǒng)定時(shí)任務(wù)界面,增刪任務(wù)只需修改數(shù)組,支持超時(shí)防卡死,全程日志可視化。
劣勢(shì):腳本窗口關(guān)閉、程序崩潰、電腦重啟后定時(shí)失效,僅適合測(cè)試和短期使用。
四、方案二:系統(tǒng)級(jí)穩(wěn)定方案(Windows計(jì)劃任務(wù)+Python通用入口)
這是生產(chǎn)環(huán)境首選方案,徹底解決定時(shí)任務(wù)偶發(fā)失效問(wèn)題,依托 Windows 系統(tǒng)調(diào)度服務(wù),鎖屏、后臺(tái)、重啟均可自動(dòng)運(yùn)行,多個(gè)任務(wù)互不干擾。
4.1 通用執(zhí)行入口腳本(bat_runner.py)
統(tǒng)一接收 BAT 路徑參數(shù),實(shí)現(xiàn)一個(gè)腳本調(diào)用所有批處理,自動(dòng)記錄運(yùn)行日志。
import sys
import subprocess
from pathlib import Path
import time
def run_single_bat(bat_path):
# 初始化路徑與日志
bat_file = Path(bat_path)
work_dir = str(bat_file.parent)
log_path = work_dir / "task_log.txt"
now = time.strftime("%Y-%m-%d %H:%M:%S")
log_lines = [f"\n===== {now} 運(yùn)行任務(wù):{bat_path} ====="]
try:
# 執(zhí)行BAT腳本
proc = subprocess.run(
bat_path,
cwd=work_dir,
shell=True,
capture_output=True,
text=True,
timeout=3600
)
# 記錄輸出與錯(cuò)誤
log_lines.append(proc.stdout)
if proc.stderr:
log_lines.append("錯(cuò)誤信息:\n" + proc.stderr)
log_lines.append(f"任務(wù)返回碼:{proc.returncode}")
except Exception as e:
log_lines.append(f"任務(wù)執(zhí)行異常:{str(e)}")
# 追加寫(xiě)入日志文件
with open(log_path, "a", encoding="utf-8") as f:
f.write("\n".join(log_lines))
if __name__ == "__main__":
# 接收命令行參數(shù),執(zhí)行對(duì)應(yīng)BAT
if len(sys.argv) >= 2:
run_single_bat(sys.argv[1])
else:
print("用法:python bat_runner.py 【BAT文件絕對(duì)路徑】")4.2 一鍵批量創(chuàng)建系統(tǒng)定時(shí)任務(wù)(管理員運(yùn)行)
無(wú)需手動(dòng)逐個(gè)配置計(jì)劃任務(wù),Python 調(diào)用系統(tǒng)命令批量生成所有分時(shí)段任務(wù),自動(dòng)配置最高權(quán)限、每日?qǐng)?zhí)行、強(qiáng)制覆蓋。
import subprocess
# 【請(qǐng)自行修改為本地真實(shí)路徑】
PYTHON_EXE = r"C:\Python311\python.exe"
RUNNER_SCRIPT = r"D:\script\bat_runner.py"
# 多任務(wù)配置:任務(wù)名稱(chēng)、執(zhí)行時(shí)間、BAT路徑
tasks = [
("Task_Bat0830", "08:30", r"D:\script\a.bat"),
("Task_Bat1210", "12:10", r"D:\script\b.bat"),
("Task_Bat1845", "18:45", r"D:\script\c.bat"),
("Task_Bat2200", "22:00", r"D:\script\d.bat"),
]
# 批量創(chuàng)建系統(tǒng)定時(shí)任務(wù)
for task_name, run_time, bat_path in tasks:
cmd = (
f'schtasks /create /tn "{task_name}" '
f'/tr "\"{PYTHON_EXE}\" \"{RUNNER_SCRIPT}\" \"{bat_path}\" '
f'/sc daily /st {run_time} /rl highest /ru Administrator /f'
)
print(f"正在創(chuàng)建任務(wù):{task_name}")
subprocess.run(cmd, shell=True)
print("\n? 所有定時(shí)任務(wù)創(chuàng)建完成!可通過(guò) taskschd.msc 查看")4.3 關(guān)鍵最優(yōu)配置(徹底解決失效問(wèn)題)
打開(kāi) taskschd.msc 打開(kāi)任務(wù)計(jì)劃程序,對(duì)所有任務(wù)統(tǒng)一配置:
- 常規(guī):勾選「不管用戶(hù)是否登錄都要運(yùn)行」「使用最高權(quán)限運(yùn)行」
- 條件:取消「僅交流電源運(yùn)行」「空閑觸發(fā)」「網(wǎng)絡(luò)檢測(cè)」所有多余條件
- 設(shè)置:開(kāi)啟「運(yùn)行超時(shí)自動(dòng)終止」,任務(wù)實(shí)例改為「并行運(yùn)行」,防止卡死阻塞
五、終極避坑總結(jié)(必看)
所有腳本、Python、BAT 全部使用絕對(duì)路徑,杜絕相對(duì)路徑報(bào)錯(cuò)
必須指定工作目錄 cwd,解決定時(shí)環(huán)境路徑不匹配問(wèn)題
所有任務(wù)添加超時(shí)限制,避免單任務(wù)卡死拖累全部任務(wù)
開(kāi)啟日志記錄,精準(zhǔn)區(qū)分「任務(wù)未觸發(fā)」和「觸發(fā)后執(zhí)行失敗」
修改 Windows 密碼后,重新保存計(jì)劃任務(wù)憑據(jù)
筆記本務(wù)必取消電源限制,防止電池模式任務(wù)失效
六、方案總結(jié)
1. 日常測(cè)試、頻繁改時(shí)間:用 Python Schedule 常駐方案,簡(jiǎn)單高效、零配置繁瑣度;
2. 服務(wù)器、長(zhǎng)期無(wú)人值守、追求穩(wěn)定:用 Windows 計(jì)劃任務(wù) + Python 入口方案,徹底根治定時(shí)任務(wù)間歇性不運(yùn)行問(wèn)題,多 BAT 分時(shí)段獨(dú)立執(zhí)行、互不影響。
到此這篇關(guān)于Python實(shí)現(xiàn)多BAT文件分時(shí)段每日自動(dòng)執(zhí)行的文章就介紹到這了,更多相關(guān)Python定時(shí)執(zhí)行BAT文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 使用Python構(gòu)建智能BAT文件生成器的完美解決方案
- python報(bào)錯(cuò)解決之python運(yùn)行bat文件的各種問(wèn)題處理
- python實(shí)現(xiàn)遠(yuǎn)程運(yùn)行bat文件
- 利用python生成一個(gè)導(dǎo)出數(shù)據(jù)庫(kù)的bat腳本文件的方法
- Python使用schedule庫(kù)實(shí)現(xiàn)任務(wù)定時(shí)自動(dòng)化
- Python?schedule庫(kù)實(shí)現(xiàn)定時(shí)任務(wù)的避坑指南
- 從入門(mén)到避坑解析Python FastAPI定時(shí)任務(wù)全攻略
- Python實(shí)現(xiàn)定時(shí)任務(wù)調(diào)度器的示例詳解
相關(guān)文章
Python遠(yuǎn)程創(chuàng)建docker容器的方法
這篇文章主要介紹了Python遠(yuǎn)程創(chuàng)建docker容器的方法,如果docker??ps找不到該容器,可以使用?docker?ps?-a查看所有的,然后看剛才創(chuàng)建的容器的STATUS是EXIT0還是EXIT1如果是1,那應(yīng)該是有報(bào)錯(cuò),使用?docker?logs?容器id命令來(lái)查看日志,根據(jù)日志進(jìn)行解決,需要的朋友可以參考下2024-04-04
Python代碼實(shí)現(xiàn)刪除一個(gè)list里面重復(fù)元素的方法
今天小編就為大家分享一篇關(guān)于Python代碼實(shí)現(xiàn)刪除一個(gè)list里面重復(fù)元素的方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-04-04
python pyautogui實(shí)現(xiàn)圖片識(shí)別點(diǎn)擊失敗后重試功能
這篇文章主要介紹了python pyautogui實(shí)現(xiàn)圖片識(shí)別點(diǎn)擊失敗后重試效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-06-06
python基于win32實(shí)現(xiàn)窗口截圖
這篇文章主要為大家詳細(xì)介紹了python基于win32api實(shí)現(xiàn)窗口截圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03
Python腳本實(shí)現(xiàn)12306火車(chē)票查詢(xún)系統(tǒng)
本文給大家分享我使用python3實(shí)現(xiàn)的12306火車(chē)票查詢(xún)系統(tǒng),小編分步驟給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2016-09-09
Python的collections模塊中的OrderedDict有序字典
字典是無(wú)序的,但是collections的OrderedDict類(lèi)為我們提供了一個(gè)有序的字典結(jié)構(gòu),名副其實(shí)的Ordered+Dict,下面通過(guò)兩個(gè)例子來(lái)簡(jiǎn)單了解下Python的collections模塊中的OrderedDict有序字典:2016-07-07
python函數(shù)調(diào)用,循環(huán),列表復(fù)制實(shí)例
這篇文章主要介紹了python函數(shù)調(diào)用,循環(huán),列表復(fù)制實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05

