如何编写后台运行同步任务脚本

wen 实用脚本 36

本文目录导读:

如何编写后台运行同步任务脚本

  1. Linux/Unix 系统 - Shell 脚本
  2. 使用 nohup + 日志管理
  3. Python 脚本方案
  4. 使用 systemd 管理(推荐)
  5. Docker 化运行
  6. 生产环境的最佳实践
  7. 监控和告警

Linux/Unix 系统 - Shell 脚本

基础后台运行方式

#!/bin/bash
# sync_task.sh
while true; do
    # 你的同步任务
    rsync -avz /source/path/ /destination/path/
    # 等待间隔(示例:每5分钟执行一次)
    sleep 300
done

运行方式

# 后台运行
nohup ./sync_task.sh > sync.log 2>&1 &
# 或使用 &
./sync_task.sh &

使用 nohup + 日志管理

#!/bin/bash
# sync_task_with_logs.sh
LOG_FILE="/var/log/sync_$(date +%Y%m%d).log"
sync_files() {
    echo "[$(date)] Starting sync..." >> $LOG_FILE
    # 执行同步命令
    rsync -avz --delete /source/ /destination/ 2>&1 | tee -a $LOG_FILE
    # 或使用其他同步工具
    # scp -r /source/* user@remote:/destination/
    # rclone sync /source remote:destination
    echo "[$(date)] Sync completed" >> $LOG_FILE
}
# 主循环
while true; do
    sync_files
    # 检查是否有停止标志文件
    if [ -f "/tmp/stop_sync" ]; then
        echo "Stop signal received. Exiting..." >> $LOG_FILE
        exit 0
    fi
    sleep 300  # 5分钟间隔
done

Python 脚本方案

#!/usr/bin/env python3
# sync_daemon.py
import os
import time
import logging
import subprocess
import signal
import sys
class SyncDaemon:
    def __init__(self, source, destination, interval=300):
        self.source = source
        self.destination = destination
        self.interval = interval
        self.running = True
        # 配置日志
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler('/var/log/sync_daemon.log'),
                logging.StreamHandler()
            ]
        )
    def sync(self):
        """执行同步任务"""
        try:
            # rsync 示例
            cmd = f"rsync -avz --delete {self.source} {self.destination}"
            result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
            if result.returncode == 0:
                logging.info("Sync completed successfully")
                if result.stdout:
                    logging.debug(result.stdout)
            else:
                logging.error(f"Sync failed: {result.stderr}")
        except Exception as e:
            logging.error(f"Sync error: {e}")
    def stop(self, signum, frame):
        """停止服务"""
        logging.info("Stopping sync daemon...")
        self.running = False
    def run(self):
        """主循环"""
        # 注册信号处理
        signal.signal(signal.SIGTERM, self.stop)
        signal.signal(signal.SIGINT, self.stop)
        logging.info(f"Starting sync daemon between {self.source} and {self.destination}")
        logging.info(f"Interval: {self.interval} seconds")
        while self.running:
            self.sync()
            # 等待指定间隔,但每秒检查是否应该停止
            for _ in range(self.interval):
                if not self.running:
                    break
                time.sleep(1)
        logging.info("Sync daemon stopped")
if __name__ == "__main__":
    # 使用示例
    daemon = SyncDaemon(
        source="/data/source/",
        destination="/data/destination/",
        interval=300  # 5分钟
    )
    daemon.run()

使用 systemd 管理(推荐)

创建 service 文件

# /etc/systemd/system/sync-daemon.service
[Unit]
Description=File Sync Daemon
After=network.target
[Service]
Type=simple
User=your_user
ExecStart=/usr/local/bin/sync_daemon.py
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target

使用方法

# 创建软链接
sudo ln -s /path/to/sync_daemon.service /etc/systemd/system/
# 重新加载 systemd
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start sync-daemon
# 设置开机自启
sudo systemctl enable sync-daemon
# 查看状态
sudo systemctl status sync-daemon
# 查看日志
sudo journalctl -u sync-daemon -f

Docker 化运行

Dockerfile

FROM alpine:latest
# 安装必要工具
RUN apk add --no-cache rsync openssh
# 创建同步脚本
COPY sync_script.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/sync_script.sh
# 启动脚本
CMD ["/usr/local/bin/sync_script.sh"]

运行

# 后台运行容器
docker run -d \
  --name sync-daemon \
  -v /host/source:/source:ro \
  -v /host/destination:/destination \
  your-sync-image

生产环境的最佳实践

综合脚本示例

#!/bin/bash
# 配置文件
CONFIG_FILE="/etc/sync-daemon.conf"
PID_FILE="/var/run/sync-daemon.pid"
LOG_FILE="/var/log/sync-daemon.log"
ERROR_LOG="/var/log/sync-daemon-error.log"
# 读取配置
source $CONFIG_FILE
# 函数:记录日志
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}
# 函数:记录错误
error() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >> $ERROR_LOG
}
# 函数:执行同步
do_sync() {
    if rsync -avz --delete \
        --log-file=$LOG_FILE \
        --exclude-from=$EXCLUDE_FILE \
        $SOURCE $DESTINATION; then
        log "Sync completed successfully"
        return 0
    else
        error "Sync failed with exit code $?"
        return 1
    fi
}
# 主程序
case "$1" in
    start)
        # 检查是否已在运行
        if [ -f $PID_FILE ]; then
            echo "Already running (PID: $(cat $PID_FILE))"
            exit 1
        fi
        # 后台执行
        (
            echo $$ > $PID_FILE
            log "Sync daemon started"
            while true; do
                do_sync
                # 发送心跳
                if [ $((SECONDS % 3600)) -eq 0 ]; then
                    log "Heartbeat - Service alive"
                fi
                sleep $INTERVAL
            done
        ) &
        echo "Started (PID: $!)"
        ;;
    stop)
        if [ -f $PID_FILE ]; then
            kill $(cat $PID_FILE) 2>/dev/null
            rm -f $PID_FILE
            log "Sync daemon stopped"
            echo "Stopped"
        else
            echo "Not running"
        fi
        ;;
    status)
        if [ -f $PID_FILE ] && kill -0 $(cat $PID_FILE) 2>/dev/null; then
            echo "Running (PID: $(cat $PID_FILE))"
        else
            echo "Not running"
        fi
        ;;
    *)
        echo "Usage: $0 {start|stop|status}"
        exit 1
        ;;
esac

监控和告警

# monitor_sync.py
import subprocess
import smtplib
from email.mime.text import MIMEText
import time
def check_sync():
    # 检查同步状态
    result = subprocess.run(
        "systemctl status sync-daemon",
        shell=True,
        capture_output=True,
        text=True
    )
    # 检查最近同步时间
    last_sync = subprocess.run(
        "stat -c %Y /var/log/sync-daemon.log",
        shell=True,
        capture_output=True,
        text=True
    )
    current_time = time.time()
    if last_sync.stdout:
        last_sync_time = float(last_sync.stdout.strip())
        if current_time - last_sync_time > 600:  # 10分钟没有同步
            send_alert(f"Sync hasn't run for 10 minutes")
  1. 简单场景:使用 nohup + shell 脚本
  2. 生产环境:使用 systemd 服务
  3. 需要灵活性:使用 Python 脚本
  4. 容器化部署:使用 Docker
  5. 关键考虑
    • 错误处理和重试机制
    • 日志记录
    • 资源限制
    • 监控告警
    • 优雅关闭

选择哪种方案取决于你的具体需求和环境。

抱歉,评论功能暂时关闭!