监控数据版本控制的脚本如何编写

wen 实用脚本 12

本文目录导读:

监控数据版本控制的脚本如何编写

  1. 基础文件版本控制脚本(Bash)
  2. Python版本的监控脚本
  3. 带Git集成的版本控制脚本
  4. 高级版本:带数据库的版本控制(Python)
  5. 使用建议

基础文件版本控制脚本(Bash)

#!/bin/bash
# 监控文件变化并保存版本
MONITOR_DIR="/path/to/monitor"
BACKUP_DIR="/path/to/backup"
VERSION_FILE="version.txt"
# 初始化版本号
if [ ! -f "$VERSION_FILE" ]; then
    echo "1" > "$VERSION_FILE"
fi
# 监控文件变化函数
monitor_changes() {
    inotifywait -m -r -e modify,create,delete,move "$MONITOR_DIR" |
    while read path action file; do
        # 获取当前版本号
        current_version=$(cat "$VERSION_FILE")
        new_version=$((current_version + 1))
        # 创建备份
        timestamp=$(date +"%Y%m%d_%H%M%S")
        backup_file="$BACKUP_DIR/${file}_v${new_version}_${timestamp}"
        cp "$path$file" "$backup_file"
        # 更新版本号
        echo "$new_version" > "$VERSION_FILE"
        # 记录变更日志
        echo "[$(date +"%Y-%m-%d %H:%M:%S")] $action: $file (Version: $new_version)" >> change_log.txt
    done
}
# 启动监控
monitor_changes

Python版本的监控脚本

#!/usr/bin/env python3
import os
import hashlib
import json
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import shutil
from datetime import datetime
class VersionControlHandler(FileSystemEventHandler):
    def __init__(self, monitor_dir, version_dir):
        self.monitor_dir = monitor_dir
        self.version_dir = version_dir
        self.version_db = os.path.join(version_dir, "version_db.json")
        self.load_version_db()
    def load_version_db(self):
        if os.path.exists(self.version_db):
            with open(self.version_db, 'r') as f:
                self.db = json.load(f)
        else:
            self.db = {}
    def save_version_db(self):
        with open(self.version_db, 'w') as f:
            json.dump(self.db, f, indent=2)
    def get_file_hash(self, filepath):
        """计算文件哈希值"""
        hasher = hashlib.md5()
        with open(filepath, 'rb') as f:
            buf = f.read()
            hasher.update(buf)
        return hasher.hexdigest()
    def create_version(self, filepath):
        """创建文件版本"""
        if not os.path.exists(filepath):
            return
        filename = os.path.basename(filepath)
        rel_path = os.path.relpath(filepath, self.monitor_dir)
        # 获取或初始化版本信息
        if rel_path not in self.db:
            self.db[rel_path] = {
                'versions': [],
                'current_version': 0
            }
        file_hash = self.get_file_hash(filepath)
        # 检查是否发生变化
        if self.db[rel_path]['versions']:
            last_version = self.db[rel_path]['versions'][-1]
            if last_version['hash'] == file_hash:
                return  # 文件未变化,跳过
        # 创建新版本
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        version_num = self.db[rel_path]['current_version'] + 1
        # 备份文件
        version_file = f"{filename}_v{version_num}_{timestamp}"
        version_path = os.path.join(self.version_dir, version_file)
        shutil.copy2(filepath, version_path)
        # 更新数据库
        version_info = {
            'version': version_num,
            'timestamp': timestamp,
            'hash': file_hash,
            'backup_file': version_file
        }
        self.db[rel_path]['versions'].append(version_info)
        self.db[rel_path]['current_version'] = version_num
        self.save_version_db()
        print(f"[{timestamp}] 新版本 {version_num} 已创建: {rel_path}")
    def on_modified(self, event):
        if not event.is_directory:
            self.create_version(event.src_path)
    def on_created(self, event):
        if not event.is_directory:
            self.create_version(event.src_path)
class VersionMonitor:
    def __init__(self, monitor_dir, version_dir):
        self.monitor_dir = monitor_dir
        self.version_dir = version_dir
        self.ensure_directories()
    def ensure_directories(self):
        os.makedirs(self.monitor_dir, exist_ok=True)
        os.makedirs(self.version_dir, exist_ok=True)
    def start_monitoring(self):
        event_handler = VersionControlHandler(self.monitor_dir, self.version_dir)
        observer = Observer()
        observer.schedule(event_handler, self.monitor_dir, recursive=True)
        observer.start()
        try:
            print(f"开始监控: {self.monitor_dir}")
            print(f"版本存储: {self.version_dir}")
            print("按 Ctrl+C 停止监控...")
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            observer.stop()
            print("\n监控已停止")
        observer.join()
# 使用示例
if __name__ == "__main__":
    monitor = VersionMonitor(
        monitor_dir="/path/to/monitor",
        version_dir="/path/to/versions"
    )
    monitor.start_monitoring()

带Git集成的版本控制脚本

#!/bin/bash
# 使用Git进行版本控制
REPO_DIR="/path/to/monitor/repo"
GIT_REMOTE="origin"
BRANCH="main"
# 初始化Git仓库
init_git_repo() {
    if [ ! -d "$REPO_DIR/.git" ]; then
        cd "$REPO_DIR"
        git init
        git add .
        git commit -m "Initial commit"
        echo "Git仓库初始化完成"
    fi
}
# 检查文件变化
check_changes() {
    cd "$REPO_DIR"
    # 添加所有变化
    git add -A
    # 检查是否有变化
    if ! git diff --cached --quiet; then
        timestamp=$(date +"%Y-%m-%d %H:%M:%S")
        file_count=$(git diff --cached --name-only | wc -l)
        # 创建commit
        git commit -m "Auto-save: $timestamp - $file_count files changed"
        # 推送远程(可选)
        if [ -n "$GIT_REMOTE" ]; then
            git push "$GIT_REMOTE" "$BRANCH" 2>/dev/null || echo "推送失败,检查远程配置"
        fi
        echo "[$timestamp] 创建了新版本,包含 $file_count 个文件的更改"
    fi
}
# 监控主循环
monitor_loop() {
    init_git_repo
    echo "开始监控文件变化..."
    echo "按 Ctrl+C 停止监控"
    while true; do
        check_changes
        sleep 60  # 每60秒检查一次
    done
}
# 版本回滚函数
rollback_version() {
    cd "$REPO_DIR"
    if [ -z "$1" ]; then
        echo "请指定要回滚的commit哈希"
        echo "可用版本列表:"
        git log --oneline -10
        return 1
    fi
    git revert --no-commit "$1"
    git commit -m "Rollback to version $1"
    echo "已回滚到版本: $1"
}
# 主函数
main() {
    case "$1" in
        start)
            monitor_loop
            ;;
        rollback)
            rollback_version "$2"
            ;;
        history)
            cd "$REPO_DIR"
            git log --oneline --graph
            ;;
        *)
            echo "用法: $0 {start|rollback <commit>|history}"
            echo ""
            echo "选项:"
            echo "  start     启动文件监控"
            echo "  rollback  回滚到指定版本"
            echo "  history   查看版本历史"
            ;;
    esac
}
main "$@"

高级版本:带数据库的版本控制(Python)

#!/usr/bin/env python3
import os
import json
import sqlite3
import hashlib
from datetime import datetime
import difflib
import gzip
class DatabaseVersionControl:
    def __init__(self, db_path, monitor_dir):
        self.db_path = db_path
        self.monitor_dir = monitor_dir
        self.init_database()
    def init_database(self):
        """初始化SQLite数据库"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        # 创建文件表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS files (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                file_path TEXT UNIQUE,
                current_version INTEGER DEFAULT 0,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ''')
        # 创建版本表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS versions (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                file_id INTEGER,
                version_number INTEGER,
                file_hash TEXT,
                file_size INTEGER,
                content BLOB,
                diff_content TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY (file_id) REFERENCES files (id)
            )
        ''')
        # 创建变更日志表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS change_log (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                file_id INTEGER,
                version_number INTEGER,
                change_type TEXT,
                description TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY (file_id) REFERENCES files (id)
            )
        ''')
        conn.commit()
        conn.close()
    def get_file_hash(self, filepath):
        """计算文件哈希值"""
        hasher = hashlib.sha256()
        with open(filepath, 'rb') as f:
            for chunk in iter(lambda: f.read(4096), b''):
                hasher.update(chunk)
        return hasher.hexdigest()
    def compress_content(self, content):
        """压缩文件内容"""
        return gzip.compress(content.encode('utf-8'))
    def save_version(self, filepath):
        """保存文件版本"""
        if not os.path.exists(filepath):
            return
        rel_path = os.path.relpath(filepath, self.monitor_dir)
        file_hash = self.get_file_hash(filepath)
        file_size = os.path.getsize(filepath)
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        # 获取或创建文件记录
        cursor.execute('SELECT id, current_version FROM files WHERE file_path = ?', (rel_path,))
        result = cursor.fetchone()
        if result:
            file_id, current_version = result
            new_version = current_version + 1
        else:
            cursor.execute('INSERT INTO files (file_path) VALUES (?)', (rel_path,))
            file_id = cursor.lastrowid
            new_version = 1
        # 读取文件内容
        with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
            content = f.read()
        # 压缩内容
        compressed_content = self.compress_content(content)
        # 生成diff(如果有前一个版本)
        diff_content = None
        if new_version > 1:
            cursor.execute('''
                SELECT content FROM versions 
                WHERE file_id = ? AND version_number = ?
            ''', (file_id, new_version - 1))
            last_version = cursor.fetchone()
            if last_version:
                last_content = gzip.decompress(last_version[0]).decode('utf-8')
                diff = difflib.unified_diff(
                    last_content.splitlines(keepends=True),
                    content.splitlines(keepends=True),
                    fromfile=f'{rel_path} (v{new_version-1})',
                    tofile=f'{rel_path} (v{new_version})'
                )
                diff_content = ''.join(diff)
        # 保存版本
        cursor.execute('''
            INSERT INTO versions (file_id, version_number, file_hash, file_size, content, diff_content)
            VALUES (?, ?, ?, ?, ?, ?)
        ''', (file_id, new_version, file_hash, file_size, compressed_content, diff_content))
        # 更新文件信息
        cursor.execute('''
            UPDATE files SET current_version = ? WHERE id = ?
        ''', (new_version, file_id))
        # 记录变更日志
        change_type = 'create' if new_version == 1 else 'modify'
        description = f'文件 {rel_path} 创建了新版本 {new_version}'
        cursor.execute('''
            INSERT INTO change_log (file_id, version_number, change_type, description)
            VALUES (?, ?, ?, ?)
        ''', (file_id, new_version, change_type, description))
        conn.commit()
        conn.close()
        print(f"[{datetime.now()}] 版本 {new_version} 已保存: {rel_path}")
    def get_version_history(self, filepath, limit=10):
        """获取文件版本历史"""
        rel_path = os.path.relpath(filepath, self.monitor_dir)
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute('''
            SELECT v.version_number, v.file_size, v.file_hash, v.created_at
            FROM versions v
            JOIN files f ON v.file_id = f.id
            WHERE f.file_path = ?
            ORDER BY v.version_number DESC
            LIMIT ?
        ''', (rel_path, limit))
        history = cursor.fetchall()
        conn.close()
        return history
    def compare_versions(self, filepath, version1, version2):
        """比较两个版本"""
        rel_path = os.path.relpath(filepath, self.monitor_dir)
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        # 获取两个版本的内容
        cursor.execute('''
            SELECT v.content, v.version_number
            FROM versions v
            JOIN files f ON v.file_id = f.id
            WHERE f.file_path = ? AND v.version_number IN (?, ?)
            ORDER BY v.version_number
        ''', (rel_path, version1, version2))
        versions = cursor.fetchall()
        conn.close()
        if len(versions) != 2:
            print("无法获取指定版本")
            return
        content1 = gzip.decompress(versions[0][0]).decode('utf-8')
        content2 = gzip.decompress(versions[1][0]).decode('utf-8')
        # 生成差异
        diff = difflib.unified_diff(
            content1.splitlines(keepends=True),
            content2.splitlines(keepends=True),
            fromfile=f'{rel_path} (v{version1})',
            tofile=f'{rel_path} (v{version2})'
        )
        print(f"比较 {rel_path} 版本 {version1} 和 {version2}:")
        print(''.join(diff))
# 使用示例
if __name__ == "__main__":
    vc = DatabaseVersionControl(
        db_path="version_control.db",
        monitor_dir="/path/to/monitor"
    )
    # 保存版本
    vc.save_version("/path/to/monitor/example.txt")
    # 查看历史
    history = vc.get_version_history("/path/to/monitor/example.txt")
    print("版本历史:")
    for v in history:
        print(f"  版本 {v[0]}: 大小={v[1]}字节, 哈希={v[2][:16]}..., 时间={v[3]}")
    # 比较版本
    vc.compare_versions("/path/to/monitor/example.txt", 1, 2)

使用建议

  1. 选择合适的方法

    • 简单场景:使用Bash脚本
    • 中等复杂度:使用Python脚本
    • 需要版本回滚:使用Git集成
    • 需要数据分析和查询:使用数据库版本
  2. 配置要点

    • 设置合理的监控间隔
    • 配置存储空间限制
    • 实现旧版本自动清理机制
  3. 安全考虑

    • 备份文件权限设置
    • 敏感数据加密
    • 访问控制

这些脚本可以根据具体需求进行调整和扩展。

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