auto-sync: 2026-03-26 08:20:48
This commit is contained in:
Executable
+95
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 文件监控脚本
|
||||
# 实时监控目录变化,触发同步
|
||||
|
||||
PROJECT_DIR="/Users/chufeng/.openclaw/sanguo_projects/sanguo_quant_live"
|
||||
LOG_FILE="$PROJECT_DIR/file-watcher.log"
|
||||
SYNC_SCRIPT="$PROJECT_DIR/auto-sync.sh"
|
||||
LOCK_FILE="/tmp/sanguo_sync.lock"
|
||||
|
||||
# 确保脚本有执行权限
|
||||
chmod +x "$SYNC_SCRIPT"
|
||||
|
||||
echo "[$(date)] Starting file watcher in $PROJECT_DIR" >> "$LOG_FILE"
|
||||
echo "[$(date)] Watching for file changes..." >> "$LOG_FILE"
|
||||
|
||||
# 创建一个函数来执行同步
|
||||
run_sync() {
|
||||
# 检查锁文件,防止重复运行
|
||||
if [ -f "$LOCK_FILE" ]; then
|
||||
echo "[$(date)] Sync already in progress, skipping..." >> "$LOG_FILE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 创建锁文件
|
||||
touch "$LOCK_FILE"
|
||||
|
||||
echo "[$(date)] Detected file change, running sync..." >> "$LOG_FILE"
|
||||
|
||||
# 执行同步脚本
|
||||
"$SYNC_SCRIPT"
|
||||
sync_result=$?
|
||||
|
||||
if [ $sync_result -eq 0 ]; then
|
||||
echo "[$(date)] Sync completed successfully" >> "$LOG_FILE"
|
||||
else
|
||||
echo "[$(date)] Sync failed with code $sync_result" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# 删除锁文件
|
||||
rm -f "$LOCK_FILE"
|
||||
}
|
||||
|
||||
# 使用fswatch监控文件变化
|
||||
# fswatch是一个跨平台的文件系统监控工具
|
||||
# 如果没有安装fswatch,使用inotifywait或find命令替代
|
||||
|
||||
# 检查fswatch是否可用
|
||||
if command -v fswatch &> /dev/null; then
|
||||
echo "[$(date)] Using fswatch for file monitoring" >> "$LOG_FILE"
|
||||
# fswatch: -e 排除.git目录,-r 递归,-0 输出null分隔符
|
||||
fswatch -e "\.git" -e "\.log$" -r -0 "$PROJECT_DIR" | while read -d "" event
|
||||
do
|
||||
# 过滤掉一些不必要的文件类型
|
||||
if [[ ! "$event" =~ \.log$ ]] && [[ ! "$event" =~ \.tmp$ ]] && [[ ! "$event" =~ ~$ ]]; then
|
||||
run_sync
|
||||
# 添加1秒延迟避免频繁触发
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
elif command -v inotifywait &> /dev/null; then
|
||||
echo "[$(date)] Using inotifywait for file monitoring" >> "$LOG_FILE"
|
||||
# inotifywait: -r 递归,-m 持续监控,-e 事件类型
|
||||
inotifywait -r -m -e create,modify,delete,move "$PROJECT_DIR" --exclude "\.git" --format "%w%f" | while read path
|
||||
do
|
||||
# 过滤掉日志文件
|
||||
if [[ ! "$path" =~ \.log$ ]] && [[ ! "$path" =~ \.tmp$ ]] && [[ ! "$path" =~ ~$ ]]; then
|
||||
run_sync
|
||||
# 添加1秒延迟避免频繁触发
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "[$(date)] WARNING: fswatch and inotifywait not found, falling back to find polling" >> "$LOG_FILE"
|
||||
echo "[$(date)] This is less efficient but will work" >> "$LOG_FILE"
|
||||
|
||||
# 使用find命令进行轮询(每5秒检查一次)
|
||||
last_check_time=$(date +%s)
|
||||
|
||||
while true; do
|
||||
current_time=$(date +%s)
|
||||
|
||||
# 检查是否有文件在最近5秒内被修改
|
||||
# find命令查找最近修改的文件
|
||||
changed_files=$(find "$PROJECT_DIR" -type f ! -name "*.log" ! -name "*.tmp" ! -name "*~" ! -path "*/.git/*" -mtime -5s 2>/dev/null | head -10)
|
||||
|
||||
if [ -n "$changed_files" ]; then
|
||||
# 有文件变化,执行同步
|
||||
run_sync
|
||||
fi
|
||||
|
||||
# 等待5秒
|
||||
sleep 5
|
||||
done
|
||||
fi
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 重启文件监控器
|
||||
# ============================================
|
||||
|
||||
# 停止当前监控
|
||||
./stop-watcher.sh
|
||||
|
||||
# 等待一秒
|
||||
sleep 1
|
||||
|
||||
# 启动新监控
|
||||
./start-watcher.sh
|
||||
|
||||
# 显示状态
|
||||
./status-watcher.sh
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 重启文件监控器
|
||||
# ===========================================
|
||||
|
||||
./management/stop-watcher.sh
|
||||
|
||||
# 等待一秒
|
||||
sleep 1
|
||||
|
||||
./management/start-watcher.sh
|
||||
|
||||
./management/status-watcher.sh
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
简单的文件监控脚本
|
||||
使用轮询方式检查文件变化,触发同步
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import subprocess
|
||||
import logging
|
||||
import threading
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
# 配置
|
||||
PROJECT_DIR = "/Users/chufeng/.openclaw/sanguo_projects/sanguo_quant_live"
|
||||
LOG_FILE = os.path.join(PROJECT_DIR, "file-watcher.log")
|
||||
SYNC_SCRIPT = os.path.join(PROJECT_DIR, "auto-sync.sh")
|
||||
LOCK_FILE = "/tmp/sanguo_sync.lock"
|
||||
CHECK_INTERVAL = 60 # 检查间隔(秒)= 1 分钟
|
||||
IGNORE_EXTENSIONS = ['.log', '.tmp', '~']
|
||||
IGNORE_DIRS = ['.git']
|
||||
|
||||
# 设置日志
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='[%(asctime)s] %(message)s',
|
||||
handlers=[
|
||||
logging.FileHandler(LOG_FILE),
|
||||
logging.StreamHandler()
|
||||
]
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class FileWatcher:
|
||||
def __init__(self, directory):
|
||||
self.directory = Path(directory)
|
||||
self.last_modified = {}
|
||||
self.running = True
|
||||
|
||||
# 初始化文件状态
|
||||
self._init_file_states()
|
||||
|
||||
def _init_file_states(self):
|
||||
"""初始化文件修改时间记录"""
|
||||
for root, dirs, files in os.walk(self.directory):
|
||||
# 跳过忽略的目录
|
||||
dirs[:] = [d for d in dirs if d not in IGNORE_DIRS]
|
||||
|
||||
for file in files:
|
||||
# 跳过忽略的文件类型
|
||||
if any(file.endswith(ext) for ext in IGNORE_EXTENSIONS):
|
||||
continue
|
||||
|
||||
filepath = Path(root) / file
|
||||
try:
|
||||
self.last_modified[str(filepath)] = filepath.stat().st_mtime
|
||||
except (OSError, FileNotFoundError):
|
||||
pass
|
||||
|
||||
def _should_ignore(self, filepath):
|
||||
"""检查是否应该忽略该文件"""
|
||||
path_str = str(filepath)
|
||||
|
||||
# 检查文件扩展名
|
||||
if any(path_str.endswith(ext) for ext in IGNORE_EXTENSIONS):
|
||||
return True
|
||||
|
||||
# 检查目录
|
||||
for ignore_dir in IGNORE_DIRS:
|
||||
if f"/{ignore_dir}/" in path_str or path_str.endswith(f"/{ignore_dir}"):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def check_for_changes(self):
|
||||
"""检查文件变化"""
|
||||
changes_detected = False
|
||||
|
||||
for root, dirs, files in os.walk(self.directory):
|
||||
# 跳过忽略的目录
|
||||
dirs[:] = [d for d in dirs if d not in IGNORE_DIRS]
|
||||
|
||||
for file in files:
|
||||
filepath = Path(root) / file
|
||||
filepath_str = str(filepath)
|
||||
|
||||
# 检查是否应该忽略
|
||||
if self._should_ignore(filepath):
|
||||
continue
|
||||
|
||||
try:
|
||||
current_mtime = filepath.stat().st_mtime
|
||||
last_mtime = self.last_modified.get(filepath_str)
|
||||
|
||||
if last_mtime is None:
|
||||
# 新文件
|
||||
self.last_modified[filepath_str] = current_mtime
|
||||
changes_detected = True
|
||||
logger.info(f"New file detected: {filepath.relative_to(self.directory)}")
|
||||
elif current_mtime > last_mtime:
|
||||
# 文件被修改
|
||||
self.last_modified[filepath_str] = current_mtime
|
||||
changes_detected = True
|
||||
logger.info(f"File modified: {filepath.relative_to(self.directory)}")
|
||||
|
||||
except (OSError, FileNotFoundError):
|
||||
# 文件被删除
|
||||
if filepath_str in self.last_modified:
|
||||
del self.last_modified[filepath_str]
|
||||
changes_detected = True
|
||||
logger.info(f"File deleted: {filepath.relative_to(self.directory)}")
|
||||
|
||||
return changes_detected
|
||||
|
||||
def run_sync(self):
|
||||
"""运行同步脚本"""
|
||||
# 检查锁文件
|
||||
if os.path.exists(LOCK_FILE):
|
||||
logger.info("Sync already in progress, skipping...")
|
||||
return
|
||||
|
||||
# 创建锁文件
|
||||
try:
|
||||
with open(LOCK_FILE, 'w') as f:
|
||||
f.write(str(datetime.now()))
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
logger.info("Detected file change, running sync...")
|
||||
|
||||
# 运行同步脚本
|
||||
result = subprocess.run([SYNC_SCRIPT], capture_output=True, text=True)
|
||||
|
||||
if result.returncode == 0:
|
||||
logger.info("Sync completed successfully")
|
||||
else:
|
||||
logger.error(f"Sync failed with code {result.returncode}")
|
||||
if result.stderr:
|
||||
logger.error(f"Error output: {result.stderr}")
|
||||
|
||||
finally:
|
||||
# 删除锁文件
|
||||
try:
|
||||
os.remove(LOCK_FILE)
|
||||
except:
|
||||
pass
|
||||
|
||||
def start(self):
|
||||
"""开始监控"""
|
||||
logger.info(f"Starting file watcher in {self.directory}")
|
||||
logger.info(f"Check interval: {CHECK_INTERVAL} seconds")
|
||||
logger.info(f"Sync script: {SYNC_SCRIPT}")
|
||||
|
||||
try:
|
||||
while self.running:
|
||||
if self.check_for_changes():
|
||||
self.run_sync()
|
||||
# 同步后等待几秒避免频繁触发
|
||||
time.sleep(3)
|
||||
|
||||
time.sleep(CHECK_INTERVAL)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logger.info("File watcher stopped by user")
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error: {e}")
|
||||
raise
|
||||
|
||||
def stop(self):
|
||||
"""停止监控"""
|
||||
self.running = False
|
||||
|
||||
def main():
|
||||
# 确保同步脚本存在且可执行
|
||||
if not os.path.exists(SYNC_SCRIPT):
|
||||
logger.error(f"Sync script not found: {SYNC_SCRIPT}")
|
||||
sys.exit(1)
|
||||
|
||||
# 确保可执行
|
||||
if not os.access(SYNC_SCRIPT, os.X_OK):
|
||||
os.chmod(SYNC_SCRIPT, 0o755)
|
||||
|
||||
# 创建监控器
|
||||
watcher = FileWatcher(PROJECT_DIR)
|
||||
|
||||
# 开始监控
|
||||
watcher.start()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 启动简单文件监控脚本
|
||||
|
||||
PROJECT_DIR="/Users/chufeng/.openclaw/sanguo_projects/sanguo_quant_live"
|
||||
WATCHER_SCRIPT="$PROJECT_DIR/simple-file-watcher.py"
|
||||
PID_FILE="$PROJECT_DIR/simple-watcher.pid"
|
||||
LOG_FILE="$PROJECT_DIR/simple-watcher.log"
|
||||
|
||||
echo "Starting simple file watcher daemon..."
|
||||
|
||||
# 检查是否已经运行
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
pid=$(cat "$PID_FILE")
|
||||
if ps -p "$pid" > /dev/null 2>&1; then
|
||||
echo "Simple file watcher is already running with PID $pid"
|
||||
echo "To stop it, run: kill $pid && rm -f $PID_FILE"
|
||||
exit 0
|
||||
else
|
||||
echo "Stale PID file found, removing..."
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 确保Python脚本可执行
|
||||
chmod +x "$WATCHER_SCRIPT"
|
||||
|
||||
# 运行监控脚本(后台运行)
|
||||
echo "Starting watcher process..."
|
||||
nohup python3 "$WATCHER_SCRIPT" > /dev/null 2>&1 &
|
||||
watcher_pid=$!
|
||||
|
||||
# 保存PID
|
||||
echo $watcher_pid > "$PID_FILE"
|
||||
|
||||
echo "Simple file watcher started with PID $watcher_pid"
|
||||
echo "PID saved to: $PID_FILE"
|
||||
echo "Log file: $LOG_FILE"
|
||||
echo ""
|
||||
echo "To stop the watcher, run:"
|
||||
echo " kill $(cat $PID_FILE) && rm -f $PID_FILE"
|
||||
echo "or use: stop-simple-watcher.sh"
|
||||
echo ""
|
||||
echo "To view logs:"
|
||||
echo " tail -f $LOG_FILE"
|
||||
echo ""
|
||||
echo "Watcher is now monitoring: $PROJECT_DIR"
|
||||
echo "Files changed will trigger: $PROJECT_DIR/auto-sync.sh"
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 启动文件监控器
|
||||
# ============================================
|
||||
|
||||
# 检查是否已经运行
|
||||
if [ -f "../watcher.pid" ]; then
|
||||
PID=$(cat "../watcher.pid")
|
||||
if kill -0 $PID 2>/dev/null; then
|
||||
echo "✓ File watcher already running with PID $PID"
|
||||
exit 0
|
||||
else
|
||||
echo "✓ PID file found but process not running, starting..."
|
||||
rm -f "../watcher.pid"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 启动监控器
|
||||
cd "$(dirname "$0")"
|
||||
python3 simple-file-watcher.py > "../file-watcher.log" 2>&1 &
|
||||
PID=$!
|
||||
echo $PID > "../watcher.pid"
|
||||
|
||||
echo "✓ File watcher started with PID $PID"
|
||||
echo " Log: $(dirname "$0")/../file-watcher.log"
|
||||
echo " To stop: ./management/stop-watcher.sh"
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 检查简单文件监控脚本状态
|
||||
|
||||
PROJECT_DIR="/Users/chufeng/.openclaw/sanguo_projects/sanguo_quant_live"
|
||||
PID_FILE="$PROJECT_DIR/simple-watcher.pid"
|
||||
LOG_FILE="$PROJECT_DIR/simple-watcher.log"
|
||||
|
||||
echo "=== Simple File Watcher Status ==="
|
||||
echo "Project Directory: $PROJECT_DIR"
|
||||
echo ""
|
||||
|
||||
# 检查PID文件
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
pid=$(cat "$PID_FILE")
|
||||
echo "PID File: $PID_FILE"
|
||||
echo "Recorded PID: $pid"
|
||||
|
||||
if ps -p "$pid" > /dev/null 2>&1; then
|
||||
echo "Status: ✅ RUNNING (PID: $pid)"
|
||||
|
||||
# 获取进程信息
|
||||
echo ""
|
||||
echo "Process Info:"
|
||||
ps -p "$pid" -o pid,ppid,user,%cpu,%mem,etime,command
|
||||
|
||||
# 检查打开的文件
|
||||
echo ""
|
||||
echo "Open Files (lsof):"
|
||||
lsof -p "$pid" 2>/dev/null | head -10
|
||||
|
||||
else
|
||||
echo "Status: ❌ NOT RUNNING (stale PID)"
|
||||
echo "Note: PID file exists but process is not running"
|
||||
fi
|
||||
else
|
||||
echo "Status: ❌ NOT RUNNING"
|
||||
echo "Reason: PID file not found"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# 检查日志文件
|
||||
if [ -f "$LOG_FILE" ]; then
|
||||
log_size=$(stat -f%z "$LOG_FILE" 2>/dev/null || stat -c%s "$LOG_FILE" 2>/dev/null)
|
||||
echo "Log File: $LOG_FILE"
|
||||
echo "Log Size: $log_size bytes"
|
||||
|
||||
echo ""
|
||||
echo "=== Last 10 Log Entries ==="
|
||||
tail -10 "$LOG_FILE" 2>/dev/null || echo "(log file empty or unreadable)"
|
||||
else
|
||||
echo "Log File: Not found"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# 检查是否有其他监控进程
|
||||
echo "=== Other Watcher Processes ==="
|
||||
echo "Active simple-file-watcher.py processes:"
|
||||
ps aux | grep "simple-file-watcher.py" | grep -v grep
|
||||
|
||||
echo ""
|
||||
|
||||
echo "=== Quick Commands ==="
|
||||
echo "Start watcher: ./start-simple-watcher.sh"
|
||||
echo "Stop watcher: ./stop-simple-watcher.sh"
|
||||
echo "View logs: tail -f $LOG_FILE"
|
||||
echo ""
|
||||
|
||||
echo "=== Auto-sync Script ==="
|
||||
SYNC_SCRIPT="$PROJECT_DIR/auto-sync.sh"
|
||||
if [ -f "$SYNC_SCRIPT" ] && [ -x "$SYNC_SCRIPT" ]; then
|
||||
echo "✅ Sync script exists and is executable"
|
||||
else
|
||||
echo "❌ Sync script missing or not executable"
|
||||
fi
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 检查文件监控器状态
|
||||
# ============================================
|
||||
|
||||
if [ ! -f "../watcher.pid" ]; then
|
||||
echo "=== File Watcher Status ==="
|
||||
echo "Status: NOT RUNNING"
|
||||
echo "To start: ./management/start-watcher.sh"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PID=$(cat "../watcher.pid")
|
||||
|
||||
if kill -0 $PID 2>/dev/null; then
|
||||
echo "=== File Watcher Status ==="
|
||||
echo "Status: ✅ RUNNING"
|
||||
echo "PID: $PID"
|
||||
echo "Check interval: 60 seconds (1 minute)"
|
||||
echo "Log: file-watcher.log"
|
||||
echo "Project directory: /Users/chufeng/.openclaw/sanguo_projects/sanguo_quant_live"
|
||||
else
|
||||
echo "=== File Watcher Status ==="
|
||||
echo "Status: ❌ NOT RUNNING (PID file exists but process dead)"
|
||||
echo "To start: ./management/start-watcher.sh"
|
||||
rm -f "../watcher.pid"
|
||||
fi
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 停止简单文件监控脚本
|
||||
|
||||
PROJECT_DIR="/Users/chufeng/.openclaw/sanguo_projects/sanguo_quant_live"
|
||||
PID_FILE="$PROJECT_DIR/simple-watcher.pid"
|
||||
|
||||
echo "Stopping simple file watcher..."
|
||||
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
pid=$(cat "$PID_FILE")
|
||||
|
||||
if ps -p "$pid" > /dev/null 2>&1; then
|
||||
echo "Killing process with PID $pid..."
|
||||
kill "$pid"
|
||||
|
||||
# 等待进程结束
|
||||
sleep 1
|
||||
|
||||
if ps -p "$pid" > /dev/null 2>&1; then
|
||||
echo "Process still running, sending SIGKILL..."
|
||||
kill -9 "$pid"
|
||||
fi
|
||||
|
||||
echo "Process stopped"
|
||||
else
|
||||
echo "No running process found with PID $pid"
|
||||
fi
|
||||
|
||||
# 删除PID文件
|
||||
rm -f "$PID_FILE"
|
||||
echo "PID file removed: $PID_FILE"
|
||||
|
||||
else
|
||||
echo "PID file not found: $PID_FILE"
|
||||
echo "Trying to find and kill any running simple-file-watcher processes..."
|
||||
|
||||
# 查找并杀死相关进程
|
||||
pids=$(ps aux | grep "simple-file-watcher.py" | grep -v grep | awk '{print $2}')
|
||||
|
||||
if [ -n "$pids" ]; then
|
||||
echo "Found processes: $pids"
|
||||
for pid in $pids; do
|
||||
echo "Killing PID $pid..."
|
||||
kill "$pid" 2>/dev/null
|
||||
sleep 0.5
|
||||
if ps -p "$pid" > /dev/null 2>&1; then
|
||||
kill -9 "$pid" 2>/dev/null
|
||||
fi
|
||||
done
|
||||
echo "All simple file watcher processes stopped"
|
||||
else
|
||||
echo "No simple file watcher processes found"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Simple file watcher stopped successfully"
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 停止文件监控器
|
||||
# ============================================
|
||||
|
||||
if [ ! -f "../watcher.pid" ]; then
|
||||
echo "✓ No PID file found, watcher not running"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PID=$(cat "../watcher.pid")
|
||||
|
||||
if kill -0 $PID 2>/dev/null; then
|
||||
echo "✓ Stopping file watcher (PID $PID)"
|
||||
kill $PID
|
||||
rm -f "../watcher.pid"
|
||||
echo "✓ Stopped"
|
||||
else
|
||||
echo "✓ Process $PID not running, removing PID file"
|
||||
rm -f "../watcher.pid"
|
||||
fi
|
||||
Reference in New Issue
Block a user