first commit
This commit is contained in:
23
Dockerfile
Normal file
23
Dockerfile
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# 使用官方Python镜像作为基础镜像
|
||||||
|
FROM python:3.9-slim
|
||||||
|
|
||||||
|
# 设置工作目录
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 复制requirements.txt文件到工作目录
|
||||||
|
COPY requirements.txt .
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# 复制所有项目文件到工作目录
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 创建目标目录
|
||||||
|
RUN mkdir -p /opt/doc/_post
|
||||||
|
|
||||||
|
# 设置环境变量
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
# 运行主程序
|
||||||
|
CMD ["python", "auto_check_files.py"]
|
||||||
140
README.md
Normal file
140
README.md
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
# Markdown文件自动处理与定时推送系统
|
||||||
|
|
||||||
|
## 功能说明
|
||||||
|
|
||||||
|
本系统用于自动处理Markdown文件,将24小时内更新的文件复制到指定目录并提交Git变更,然后定时推送到远程仓库。
|
||||||
|
|
||||||
|
## 主要功能
|
||||||
|
|
||||||
|
1. **遍历目录**:遍历指定目录下的所有Markdown文件(包含子文件夹)
|
||||||
|
2. **解析frontmatter**:解析每个文件的YAML frontmatter属性
|
||||||
|
3. **检查更新时间**:优先使用frontmatter中的`updated`字段,否则使用文件修改时间
|
||||||
|
4. **筛选24小时内更新的文件**:只处理最近24小时内更新的文件
|
||||||
|
5. **同名文件处理**:支持三种策略:overwrite(覆盖), skip(跳过), rename(重命名)
|
||||||
|
6. **Git提交**:自动提交变更,提交信息格式:`feat: 📝 {title}`
|
||||||
|
7. **定时推送**:每天早上六点、中午12点、晚上零点推送到远程仓库
|
||||||
|
|
||||||
|
## 文件说明
|
||||||
|
|
||||||
|
- `parse_frontmatter.py`:主脚本,用于处理Markdown文件
|
||||||
|
- `push_to_remote.py`:推送脚本,用于将本地提交推送到远程仓库
|
||||||
|
- `push_to_remote.bat`:Windows批处理文件,用于运行推送脚本
|
||||||
|
- `push_to_remote.sh`:Linux shell脚本,用于运行推送脚本
|
||||||
|
- `example.md`:示例Markdown文件
|
||||||
|
|
||||||
|
## 配置说明
|
||||||
|
|
||||||
|
### 1. 添加远程仓库
|
||||||
|
|
||||||
|
在目标目录下执行以下命令添加远程仓库(使用SSH协议):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git remote add origin git@github.com:username/repo.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. SSH密钥配置
|
||||||
|
|
||||||
|
确保SSH密钥已正确配置,密钥文件应位于`~/.ssh/`目录下:
|
||||||
|
|
||||||
|
- 检查SSH密钥是否存在:
|
||||||
|
```bash
|
||||||
|
ls -la ~/.ssh/
|
||||||
|
```
|
||||||
|
|
||||||
|
- 如果没有SSH密钥,生成新密钥:
|
||||||
|
```bash
|
||||||
|
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
- 将公钥添加到GitHub/GitLab等平台
|
||||||
|
|
||||||
|
### 3. 定时任务配置
|
||||||
|
|
||||||
|
#### Windows系统(使用任务计划程序)
|
||||||
|
|
||||||
|
1. 打开"任务计划程序"(搜索"Task Scheduler")
|
||||||
|
2. 点击"创建基本任务"
|
||||||
|
3. 输入任务名称和描述
|
||||||
|
4. 选择"每天"触发器
|
||||||
|
5. 设置起始时间为"00:00:00",重复任务间隔为"12"小时,持续时间为"1天"
|
||||||
|
6. 选择"启动程序"操作
|
||||||
|
7. 浏览并选择`push_to_remote.bat`文件
|
||||||
|
8. 勾选"当单击完成时,打开此任务属性的对话框"
|
||||||
|
9. 切换到"触发器"选项卡,点击"新建"
|
||||||
|
10. 设置另一个触发器为"每天",起始时间为"12:00:00"
|
||||||
|
11. 点击"确定"完成配置
|
||||||
|
|
||||||
|
#### Linux系统(使用cron)
|
||||||
|
|
||||||
|
1. 打开cron配置文件:
|
||||||
|
```bash
|
||||||
|
crontab -e
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 添加以下行,设置每天零点、六点、十二点执行推送脚本:
|
||||||
|
```bash
|
||||||
|
0 0 * * * /path/to/push_to_remote.sh
|
||||||
|
0 6 * * * /path/to/push_to_remote.sh
|
||||||
|
0 12 * * * /path/to/push_to_remote.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 保存并退出(对于vim编辑器,按`Esc`,然后输入`:wq`)
|
||||||
|
|
||||||
|
### 4. 脚本参数配置
|
||||||
|
|
||||||
|
可以根据需要修改脚本中的默认参数:
|
||||||
|
|
||||||
|
- **parse_frontmatter.py**:
|
||||||
|
- `source_dir`:源目录路径
|
||||||
|
- `destination_dir`:目标目录路径
|
||||||
|
- `overwrite_strategy`:同名文件处理策略
|
||||||
|
|
||||||
|
- **push_to_remote.py**:
|
||||||
|
- `repo_path`:Git仓库路径
|
||||||
|
- `remote_name`:远程仓库名称
|
||||||
|
- `branch`:分支名称
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
1. **运行主脚本**:
|
||||||
|
```bash
|
||||||
|
python parse_frontmatter.py
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **手动运行推送脚本**:
|
||||||
|
- Windows:
|
||||||
|
```bash
|
||||||
|
push_to_remote.bat
|
||||||
|
```
|
||||||
|
- Linux:
|
||||||
|
```bash
|
||||||
|
chmod +x push_to_remote.sh
|
||||||
|
./push_to_remote.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. 确保Python环境已正确安装,并且已安装所需依赖:
|
||||||
|
```bash
|
||||||
|
pip install pyyaml gitpython
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 确保目标目录已初始化Git仓库,或者主脚本会自动初始化
|
||||||
|
|
||||||
|
3. 确保已正确配置SSH密钥,并且有权限访问远程仓库
|
||||||
|
|
||||||
|
4. 定时任务运行时,确保系统处于开机状态
|
||||||
|
|
||||||
|
## 日志说明
|
||||||
|
|
||||||
|
脚本会输出详细的日志信息,包括:
|
||||||
|
- 处理的文件数量
|
||||||
|
- 成功复制的文件数量
|
||||||
|
- 提交的Git变更
|
||||||
|
- 推送到远程仓库的结果
|
||||||
|
|
||||||
|
可以根据需要将日志重定向到文件,以便查看历史记录:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python parse_frontmatter.py > log.txt 2>&1
|
||||||
|
```
|
||||||
471
auto_check_files.py
Normal file
471
auto_check_files.py
Normal file
@@ -0,0 +1,471 @@
|
|||||||
|
import os
|
||||||
|
from pickle import FALSE
|
||||||
|
import yaml
|
||||||
|
import shutil
|
||||||
|
import datetime
|
||||||
|
import configparser
|
||||||
|
from typing import Dict, List, Optional
|
||||||
|
from git import Repo
|
||||||
|
from apscheduler.schedulers.blocking import BlockingScheduler
|
||||||
|
|
||||||
|
# 配置文件路径,使用绝对路径确保能找到
|
||||||
|
CONFIG_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config.ini')
|
||||||
|
|
||||||
|
# 全局变量,用于存储配置
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
|
||||||
|
# 全局变量,用于存储上一次检查的时间
|
||||||
|
last_check_time = None
|
||||||
|
|
||||||
|
|
||||||
|
def parse_markdown_frontmatter(file_path: str) -> Dict:
|
||||||
|
"""
|
||||||
|
读取Markdown文件并解析其frontmatter YAML属性
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path (str): Markdown文件的路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 解析后的frontmatter属性字典,如果没有frontmatter则返回空字典
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# 检查文件是否以frontmatter开头
|
||||||
|
if not content.startswith('---'):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
# 找到frontmatter的结束位置
|
||||||
|
end_index = content.find('---', 3)
|
||||||
|
if end_index == -1:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
# 提取frontmatter内容
|
||||||
|
frontmatter_content = content[3:end_index].strip()
|
||||||
|
|
||||||
|
# 解析YAML
|
||||||
|
frontmatter = yaml.safe_load(frontmatter_content)
|
||||||
|
|
||||||
|
# 确保返回的是字典类型
|
||||||
|
if frontmatter is None:
|
||||||
|
frontmatter = {}
|
||||||
|
|
||||||
|
return frontmatter
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"文件 {file_path} 不存在")
|
||||||
|
return {}
|
||||||
|
except yaml.YAMLError as e:
|
||||||
|
print(f"解析文件 {file_path} 的frontmatter时出错: {e}")
|
||||||
|
return {}
|
||||||
|
except Exception as e:
|
||||||
|
print(f"处理文件 {file_path} 时出错: {e}")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def is_updated_since_last_check(frontmatter: Dict, file_path: str, last_check: datetime.datetime) -> bool:
|
||||||
|
"""
|
||||||
|
检查文件是否在上一次检查时间之后更新
|
||||||
|
|
||||||
|
Args:
|
||||||
|
frontmatter (dict): 文件的frontmatter属性
|
||||||
|
file_path (str): 文件路径
|
||||||
|
last_check (datetime.datetime): 上一次检查的时间
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 如果文件在上一次检查时间之后更新则返回True,否则返回False
|
||||||
|
"""
|
||||||
|
# 尝试从frontmatter获取updated时间
|
||||||
|
updated_value = frontmatter.get('updated')
|
||||||
|
|
||||||
|
# 如果frontmatter没有updated字段,使用文件的修改时间
|
||||||
|
if not updated_value:
|
||||||
|
try:
|
||||||
|
mtime = os.path.getmtime(file_path)
|
||||||
|
updated_dt = datetime.datetime.fromtimestamp(mtime)
|
||||||
|
except OSError as e:
|
||||||
|
print(f"无法获取文件 {file_path} 的修改时间: {e}")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
# 检查updated_value是否已经是datetime对象
|
||||||
|
if isinstance(updated_value, datetime.datetime):
|
||||||
|
updated_dt = updated_value
|
||||||
|
else:
|
||||||
|
# 解析updated字符串为datetime对象
|
||||||
|
try:
|
||||||
|
# 支持多种时间格式
|
||||||
|
date_formats = [
|
||||||
|
'%Y-%m-%d %H:%M:%S',
|
||||||
|
'%Y-%m-%d %H:%M',
|
||||||
|
'%Y-%m-%d',
|
||||||
|
'%Y/%m/%d %H:%M:%S',
|
||||||
|
'%Y/%m/%d %H:%M',
|
||||||
|
'%Y/%m/%d'
|
||||||
|
]
|
||||||
|
|
||||||
|
updated_dt = None
|
||||||
|
for fmt in date_formats:
|
||||||
|
try:
|
||||||
|
updated_dt = datetime.datetime.strptime(updated_value, fmt)
|
||||||
|
break
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if updated_dt is None:
|
||||||
|
print(f"文件 {file_path} 的updated时间格式不正确: {updated_value}")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(f"解析文件 {file_path} 的updated时间时出错: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 检查是否在上一次检查时间之后更新
|
||||||
|
return updated_dt >= last_check
|
||||||
|
|
||||||
|
|
||||||
|
def copy_file_to_destination(source_path: str, destination_dir: str, repo: Repo, frontmatter: Dict) -> bool:
|
||||||
|
"""
|
||||||
|
将文件复制到目标目录并提交Git变更
|
||||||
|
|
||||||
|
Args:
|
||||||
|
source_path (str): 源文件路径
|
||||||
|
destination_dir (str): 目标目录路径
|
||||||
|
repo (Repo): Git仓库对象
|
||||||
|
frontmatter (dict): 文件的frontmatter属性
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 复制和提交成功返回True,否则返回False
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 从配置文件获取同名文件处理策略
|
||||||
|
overwrite_strategy = config['DEFAULT'].get('overwrite_strategy', 'overwrite')
|
||||||
|
|
||||||
|
# 确保目标目录存在
|
||||||
|
if not os.path.exists(destination_dir):
|
||||||
|
os.makedirs(destination_dir, exist_ok=True)
|
||||||
|
print(f"创建目标目录: {destination_dir}")
|
||||||
|
|
||||||
|
# 获取文件名和目标路径
|
||||||
|
file_name = os.path.basename(source_path)
|
||||||
|
file_base, file_ext = os.path.splitext(file_name)
|
||||||
|
destination_path = os.path.join(destination_dir, file_name)
|
||||||
|
existsResult = FALSE
|
||||||
|
# 处理同名文件
|
||||||
|
if os.path.exists(destination_path):
|
||||||
|
existsResult = True
|
||||||
|
if overwrite_strategy == 'skip':
|
||||||
|
print(f"跳过已存在文件: {destination_path}")
|
||||||
|
return False
|
||||||
|
elif overwrite_strategy == 'rename':
|
||||||
|
# 生成带时间戳的新文件名
|
||||||
|
timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||||
|
new_file_name = f"{file_base}_{timestamp}{file_ext}"
|
||||||
|
destination_path = os.path.join(destination_dir, new_file_name)
|
||||||
|
print(f"文件已存在,重命名为: {new_file_name}")
|
||||||
|
# 默认overwrite策略,直接覆盖
|
||||||
|
|
||||||
|
# 复制文件,保留元数据
|
||||||
|
shutil.copy2(source_path, destination_path)
|
||||||
|
print(f"成功拷贝: {source_path} -> {destination_path}")
|
||||||
|
|
||||||
|
# 获取提交信息
|
||||||
|
title = frontmatter.get('title', file_name)
|
||||||
|
if existsResult:
|
||||||
|
commit_message = f"update: 📝 更新 《{title}》文章内容"
|
||||||
|
else:
|
||||||
|
commit_message = f"feat: 📝 新建《{title}》文章"
|
||||||
|
|
||||||
|
# 添加文件到Git暂存区
|
||||||
|
repo.git.add(".")
|
||||||
|
|
||||||
|
# 提交变更
|
||||||
|
repo.git.commit('-m', commit_message)
|
||||||
|
print(f"成功提交: {commit_message}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"拷贝或提交失败 {source_path}: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def check_and_process_files(repo: Repo) -> Dict:
|
||||||
|
"""
|
||||||
|
检查并处理指定目录下的所有Markdown文件,将上一次检查后更新的文件复制到目标目录并提交Git变更
|
||||||
|
|
||||||
|
Args:
|
||||||
|
repo (Repo): Git仓库对象
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 处理结果统计
|
||||||
|
"""
|
||||||
|
global last_check_time
|
||||||
|
|
||||||
|
# 从配置文件获取参数
|
||||||
|
source_dir = config['DEFAULT'].get('source_dir')
|
||||||
|
destination_dir = config['DEFAULT'].get('destination_dir')
|
||||||
|
overwrite_strategy = config['DEFAULT'].get('overwrite_strategy', 'overwrite')
|
||||||
|
|
||||||
|
# 替换为当前目录进行测试(如果默认目录不存在)
|
||||||
|
if not os.path.exists(source_dir):
|
||||||
|
source_dir = os.getcwd()
|
||||||
|
print(f"默认源目录不存在,使用当前目录进行测试: {source_dir}")
|
||||||
|
|
||||||
|
# 确保目标目录存在
|
||||||
|
if not os.path.exists(destination_dir):
|
||||||
|
os.makedirs(destination_dir, exist_ok=True)
|
||||||
|
print(f"创建目标目录: {destination_dir}")
|
||||||
|
|
||||||
|
stats = {
|
||||||
|
'total_files': 0,
|
||||||
|
'md_files': 0,
|
||||||
|
'with_frontmatter': 0,
|
||||||
|
'updated_since_last_check': 0,
|
||||||
|
'copied_successfully': 0,
|
||||||
|
'copy_failed': 0
|
||||||
|
}
|
||||||
|
|
||||||
|
current_time = datetime.datetime.now()
|
||||||
|
print(f"\n{'='*80}")
|
||||||
|
print(f"开始检查文件,时间: {current_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||||
|
print(f"上一次检查时间: {last_check_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||||
|
print(f"源目录: {source_dir}")
|
||||||
|
print(f"目标目录: {destination_dir}")
|
||||||
|
print(f"同名文件处理策略: {overwrite_strategy}")
|
||||||
|
print(f"{'='*80}")
|
||||||
|
|
||||||
|
# 遍历源目录下的所有文件,忽略以`.`开头的文件夹
|
||||||
|
for root, dirs, files in os.walk(source_dir):
|
||||||
|
# 过滤掉以`.`开头的文件夹
|
||||||
|
dirs[:] = [d for d in dirs if not d.startswith('.')]
|
||||||
|
|
||||||
|
for file in files:
|
||||||
|
# 过滤掉以`.`开头的文件
|
||||||
|
if file.startswith('.'):
|
||||||
|
continue
|
||||||
|
# 只处理Markdown文件
|
||||||
|
if not file.lower().endswith('.md'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
stats['total_files'] += 1
|
||||||
|
stats['md_files'] += 1
|
||||||
|
file_path = os.path.join(root, file)
|
||||||
|
|
||||||
|
# 解析frontmatter
|
||||||
|
frontmatter = parse_markdown_frontmatter(file_path)
|
||||||
|
|
||||||
|
if frontmatter:
|
||||||
|
stats['with_frontmatter'] += 1
|
||||||
|
|
||||||
|
# 检查是否在上一次检查时间之后更新
|
||||||
|
if is_updated_since_last_check(frontmatter, file_path, last_check_time):
|
||||||
|
stats['updated_since_last_check'] += 1
|
||||||
|
|
||||||
|
# 复制到目标目录并提交
|
||||||
|
if copy_file_to_destination(file_path, destination_dir, repo, frontmatter):
|
||||||
|
stats['copied_successfully'] += 1
|
||||||
|
else:
|
||||||
|
stats['copy_failed'] += 1
|
||||||
|
else:
|
||||||
|
# 对于没有frontmatter的文件,创建一个默认的frontmatter
|
||||||
|
default_frontmatter = {
|
||||||
|
'title': os.path.basename(file_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
# 使用文件修改时间判断
|
||||||
|
try:
|
||||||
|
mtime = os.path.getmtime(file_path)
|
||||||
|
updated_dt = datetime.datetime.fromtimestamp(mtime)
|
||||||
|
|
||||||
|
if updated_dt >= last_check_time:
|
||||||
|
stats['updated_since_last_check'] += 1
|
||||||
|
if copy_file_to_destination(file_path, destination_dir, repo, default_frontmatter):
|
||||||
|
stats['copied_successfully'] += 1
|
||||||
|
else:
|
||||||
|
stats['copy_failed'] += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f"无法处理文件 {file_path}: {e}")
|
||||||
|
|
||||||
|
# 更新最后检查时间
|
||||||
|
last_check_time = current_time
|
||||||
|
|
||||||
|
# 打印统计结果
|
||||||
|
print(f"\n{'='*80}")
|
||||||
|
print("处理结果统计:")
|
||||||
|
print(f"总文件数: {stats['total_files']}")
|
||||||
|
print(f"Markdown文件数: {stats['md_files']}")
|
||||||
|
print(f"包含frontmatter的文件数: {stats['with_frontmatter']}")
|
||||||
|
print(f"上一次检查后更新的文件数: {stats['updated_since_last_check']}")
|
||||||
|
print(f"成功复制的文件数: {stats['copied_successfully']}")
|
||||||
|
print(f"复制失败的文件数: {stats['copy_failed']}")
|
||||||
|
print(f"{'='*80}")
|
||||||
|
|
||||||
|
return stats
|
||||||
|
|
||||||
|
|
||||||
|
def load_config():
|
||||||
|
"""
|
||||||
|
从配置文件中读取配置,并为缺失的参数设置默认值
|
||||||
|
"""
|
||||||
|
global config, last_check_time
|
||||||
|
|
||||||
|
# 读取配置文件
|
||||||
|
config.read(CONFIG_FILE)
|
||||||
|
|
||||||
|
# 确保DEFAULT section存在
|
||||||
|
if 'DEFAULT' not in config:
|
||||||
|
config['DEFAULT'] = {}
|
||||||
|
|
||||||
|
# 设置默认值
|
||||||
|
default_config = {
|
||||||
|
'source_dir': '/opt/src',
|
||||||
|
'destination_dir': '/opt/doc/_post',
|
||||||
|
'overwrite_strategy': 'overwrite',
|
||||||
|
'remote_name': 'origin',
|
||||||
|
'branch': 'master'
|
||||||
|
}
|
||||||
|
|
||||||
|
# 更新配置文件中的缺失参数
|
||||||
|
for key, value in default_config.items():
|
||||||
|
if key not in config['DEFAULT'] or not config['DEFAULT'][key]:
|
||||||
|
config['DEFAULT'][key] = value
|
||||||
|
|
||||||
|
# 获取上一次检查时间
|
||||||
|
last_check_time_str = config['DEFAULT'].get('last_check_time')
|
||||||
|
if last_check_time_str:
|
||||||
|
last_check_time = datetime.datetime.strptime(last_check_time_str, '%Y-%m-%d %H:%M:%S')
|
||||||
|
else:
|
||||||
|
last_check_time = datetime.datetime.now()
|
||||||
|
# 将默认的上一次检查时间写入配置文件
|
||||||
|
config['DEFAULT']['last_check_time'] = last_check_time.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
print(f"从配置文件中读取配置成功")
|
||||||
|
print(f"上一次检查时间: {last_check_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||||
|
print(f"源目录: {config['DEFAULT'].get('source_dir')}")
|
||||||
|
print(f"目标目录: {config['DEFAULT'].get('destination_dir')}")
|
||||||
|
print(f"同名文件处理策略: {config['DEFAULT'].get('overwrite_strategy')}")
|
||||||
|
print(f"远程仓库名称: {config['DEFAULT'].get('remote_name')}")
|
||||||
|
print(f"分支名称: {config['DEFAULT'].get('branch')}")
|
||||||
|
|
||||||
|
|
||||||
|
def save_config():
|
||||||
|
"""
|
||||||
|
将配置写入配置文件,特别是更新上一次检查时间
|
||||||
|
"""
|
||||||
|
global config, last_check_time
|
||||||
|
|
||||||
|
# 更新上一次检查时间
|
||||||
|
config['DEFAULT']['last_check_time'] = last_check_time.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
# 写入配置文件
|
||||||
|
with open(CONFIG_FILE, 'w') as f:
|
||||||
|
config.write(f)
|
||||||
|
|
||||||
|
print(f"配置文件保存成功,上一次检查时间更新为: {last_check_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||||
|
|
||||||
|
|
||||||
|
def push_to_remote(repo: Repo) -> bool:
|
||||||
|
"""
|
||||||
|
将本地提交推送到远程仓库
|
||||||
|
|
||||||
|
Args:
|
||||||
|
repo (Repo): Git仓库对象
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 推送成功返回True,否则返回False
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 从配置文件获取远程仓库名称和分支名称
|
||||||
|
remote_name = config['DEFAULT'].get('remote_name', 'origin')
|
||||||
|
branch = config['DEFAULT'].get('branch', 'master')
|
||||||
|
|
||||||
|
# 检查远程仓库是否存在
|
||||||
|
if remote_name not in repo.remotes:
|
||||||
|
print(f"远程仓库 {remote_name} 不存在,无法推送")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 推送到远程仓库
|
||||||
|
repo.git.push(remote_name, branch)
|
||||||
|
print(f"成功推送到远程仓库 {remote_name} 的 {branch} 分支")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"推送失败: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def job():
|
||||||
|
"""
|
||||||
|
定时任务函数,执行文件检查和处理
|
||||||
|
"""
|
||||||
|
global last_check_time
|
||||||
|
|
||||||
|
# 从配置文件获取参数
|
||||||
|
source_dir = config['DEFAULT'].get('source_dir')
|
||||||
|
destination_dir = config['DEFAULT'].get('destination_dir')
|
||||||
|
|
||||||
|
# 替换为当前目录进行测试(如果默认目录不存在)
|
||||||
|
if not os.path.exists(source_dir):
|
||||||
|
source_dir = os.getcwd()
|
||||||
|
destination_dir = os.path.join(source_dir, 'recent_posts')
|
||||||
|
print(f"默认源目录不存在,使用当前目录进行测试: {source_dir}")
|
||||||
|
|
||||||
|
# 初始化或打开Git仓库
|
||||||
|
try:
|
||||||
|
# 检查目标目录是否已经是Git仓库
|
||||||
|
if os.path.exists(os.path.join(destination_dir, '.git')):
|
||||||
|
repo = Repo(destination_dir)
|
||||||
|
print(f"打开现有Git仓库: {destination_dir}")
|
||||||
|
else:
|
||||||
|
# 初始化新的Git仓库
|
||||||
|
repo = Repo.init(destination_dir)
|
||||||
|
print(f"初始化新Git仓库: {destination_dir}")
|
||||||
|
|
||||||
|
# 检查并处理文件
|
||||||
|
check_and_process_files(repo)
|
||||||
|
|
||||||
|
# 更新上一次检查时间
|
||||||
|
last_check_time = datetime.datetime.now()
|
||||||
|
|
||||||
|
# 保存配置,特别是更新上一次检查时间
|
||||||
|
save_config()
|
||||||
|
|
||||||
|
# 推送到远程仓库
|
||||||
|
push_to_remote(repo)
|
||||||
|
|
||||||
|
print("任务完成!")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Git操作失败: {e}")
|
||||||
|
print("任务失败!")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""
|
||||||
|
主函数,启动定时任务
|
||||||
|
"""
|
||||||
|
# 加载配置文件
|
||||||
|
load_config()
|
||||||
|
|
||||||
|
# 立即执行一次检查
|
||||||
|
print(f"\n立即执行第一次检查")
|
||||||
|
job()
|
||||||
|
|
||||||
|
# 创建调度器
|
||||||
|
scheduler = BlockingScheduler()
|
||||||
|
|
||||||
|
# 添加定时任务,每隔5分钟执行一次
|
||||||
|
scheduler.add_job(job, 'interval', minutes=5)
|
||||||
|
|
||||||
|
print(f"\n定时任务已启动,每隔5分钟执行一次")
|
||||||
|
print(f"下次执行时间: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||||
|
print(f"按 Ctrl+C 停止任务")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 启动调度器
|
||||||
|
scheduler.start()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print(f"\n定时任务已停止")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"定时任务执行出错: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
8
config.ini
Normal file
8
config.ini
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[DEFAULT]
|
||||||
|
source_dir = source
|
||||||
|
destination_dir = recent_posts
|
||||||
|
overwrite_strategy = overwrite
|
||||||
|
remote_name = origin
|
||||||
|
branch = master
|
||||||
|
last_check_time = 2026-01-10 15:13:57
|
||||||
|
|
||||||
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pyyaml>=6.0
|
||||||
|
gitpython>=3.1.0
|
||||||
|
apscheduler>=3.10.0
|
||||||
Reference in New Issue
Block a user