forked from Goko/JingTian-Rclone
feat: add Windows sync script
- Phase 1: One-way sync (Windows -> Server) for main folders - Phase 2: Bidirectional sync using rclone bisync for _LLM_Sync - Auto-detects rclone and BenjaminTeam folder paths - Comprehensive logging to %LOCALAPPDATA%\JingTian\logs - Supports verbose output with -VerboseOutput flag
This commit is contained in:
235
windows/sync.ps1
Normal file
235
windows/sync.ps1
Normal file
@@ -0,0 +1,235 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
JingTian rclone Sync Script
|
||||
|
||||
.DESCRIPTION
|
||||
Syncs the local BenjaminTeam folder with the remote Ubuntu server.
|
||||
- Main folders: One-way sync (Windows -> Server)
|
||||
- _LLM_Sync folder: Bidirectional sync
|
||||
|
||||
.PARAMETER LocalPath
|
||||
Path to the local BenjaminTeam folder.
|
||||
|
||||
.PARAMETER RclonePath
|
||||
Path to rclone.exe. Default: auto-detect
|
||||
|
||||
.PARAMETER LogDir
|
||||
Directory for log files. Default: %LOCALAPPDATA%\JingTian\logs
|
||||
|
||||
.PARAMETER Verbose
|
||||
Show detailed output during sync.
|
||||
#>
|
||||
|
||||
param(
|
||||
[string]$LocalPath = "",
|
||||
[string]$RclonePath = "",
|
||||
[string]$LogDir = "$env:LOCALAPPDATA\JingTian\logs",
|
||||
[switch]$VerboseOutput
|
||||
)
|
||||
|
||||
# Configuration
|
||||
$RemoteName = "jingtian-server"
|
||||
$RemotePath = "/data/jingtian/BenjaminTeam"
|
||||
$LLMSyncFolder = "_LLM_Sync"
|
||||
|
||||
# Find rclone if not specified
|
||||
if (-not $RclonePath -or -not (Test-Path $RclonePath)) {
|
||||
$possiblePaths = @(
|
||||
"$env:LOCALAPPDATA\rclone\rclone.exe",
|
||||
"C:\rclone\rclone.exe",
|
||||
"rclone.exe"
|
||||
)
|
||||
foreach ($path in $possiblePaths) {
|
||||
if (Test-Path $path) {
|
||||
$RclonePath = $path
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-not (Test-Path $RclonePath)) {
|
||||
Write-Error "rclone not found. Please run setup.ps1 first."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Find LocalPath if not specified (check common locations)
|
||||
if (-not $LocalPath -or -not (Test-Path $LocalPath)) {
|
||||
$searchPaths = @(
|
||||
"$env:USERPROFILE\Documents\BenjaminTeam",
|
||||
"$env:USERPROFILE\Documents\Benjamin Team",
|
||||
"D:\BenjaminTeam",
|
||||
"C:\BenjaminTeam"
|
||||
)
|
||||
foreach ($path in $searchPaths) {
|
||||
if (Test-Path $path) {
|
||||
$LocalPath = $path
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-not (Test-Path $LocalPath)) {
|
||||
Write-Error "BenjaminTeam folder not found. Please specify -LocalPath"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Setup logging
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
|
||||
$logFile = Join-Path $LogDir "sync.log"
|
||||
$detailLogFile = Join-Path $LogDir "sync_$timestamp.log"
|
||||
|
||||
if (-not (Test-Path $LogDir)) {
|
||||
New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
|
||||
}
|
||||
|
||||
function Write-Log {
|
||||
param([string]$Message, [string]$Level = "INFO")
|
||||
$ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logLine = "[$ts] [$Level] $Message"
|
||||
Add-Content -Path $logFile -Value $logLine
|
||||
|
||||
if ($VerboseOutput) {
|
||||
switch ($Level) {
|
||||
"ERROR" { Write-Host $logLine -ForegroundColor Red }
|
||||
"WARN" { Write-Host $logLine -ForegroundColor Yellow }
|
||||
"OK" { Write-Host $logLine -ForegroundColor Green }
|
||||
default { Write-Host $logLine }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# MAIN SYNC LOGIC
|
||||
# ============================================================
|
||||
|
||||
Write-Log "========== Sync Started =========="
|
||||
Write-Log "Local: $LocalPath"
|
||||
Write-Log "Remote: ${RemoteName}:${RemotePath}"
|
||||
|
||||
$syncErrors = @()
|
||||
$startTime = Get-Date
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Phase 1: One-way sync (Windows -> Server) for main folders
|
||||
# Excludes _LLM_Sync which is handled separately
|
||||
# ------------------------------------------------------------
|
||||
|
||||
Write-Log "Phase 1: Syncing main folders (Windows -> Server)..."
|
||||
|
||||
$rcloneArgs = @(
|
||||
"sync",
|
||||
$LocalPath,
|
||||
"${RemoteName}:${RemotePath}",
|
||||
"--exclude", "$LLMSyncFolder/**",
|
||||
"--transfers", "4",
|
||||
"--checkers", "8",
|
||||
"--contimeout", "60s",
|
||||
"--timeout", "300s",
|
||||
"--retries", "3",
|
||||
"--low-level-retries", "10",
|
||||
"--stats", "1m",
|
||||
"--stats-one-line",
|
||||
"--log-file", $detailLogFile,
|
||||
"--log-level", "INFO"
|
||||
)
|
||||
|
||||
if ($VerboseOutput) {
|
||||
$rcloneArgs += "--progress"
|
||||
}
|
||||
|
||||
try {
|
||||
$result = & $RclonePath @rcloneArgs 2>&1
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Log "Phase 1 complete: Main folders synced successfully" "OK"
|
||||
} else {
|
||||
Write-Log "Phase 1 warning: rclone exited with code $LASTEXITCODE" "WARN"
|
||||
$syncErrors += "Main folder sync had warnings (exit code: $LASTEXITCODE)"
|
||||
}
|
||||
} catch {
|
||||
Write-Log "Phase 1 error: $_" "ERROR"
|
||||
$syncErrors += "Main folder sync failed: $_"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Phase 2: Bidirectional sync for _LLM_Sync folder
|
||||
# Uses rclone bisync for true bidirectional sync
|
||||
# ------------------------------------------------------------
|
||||
|
||||
Write-Log "Phase 2: Syncing _LLM_Sync folder (bidirectional)..."
|
||||
|
||||
$llmLocalPath = Join-Path $LocalPath $LLMSyncFolder
|
||||
$llmRemotePath = "${RemoteName}:${RemotePath}/${LLMSyncFolder}"
|
||||
|
||||
# Ensure local _LLM_Sync exists
|
||||
if (-not (Test-Path $llmLocalPath)) {
|
||||
New-Item -ItemType Directory -Path $llmLocalPath -Force | Out-Null
|
||||
Write-Log "Created local _LLM_Sync folder"
|
||||
}
|
||||
|
||||
# Check if bisync has been initialized (look for .rclone-bisync directory)
|
||||
$bisyncStateDir = "$env:USERPROFILE\.cache\rclone\bisync"
|
||||
$bisyncStateFile = Join-Path $bisyncStateDir "*.lst"
|
||||
|
||||
# For first run, we need to use --resync to initialize
|
||||
$needsResync = $false
|
||||
if (-not (Test-Path $bisyncStateDir) -or -not (Get-ChildItem $bisyncStateFile -ErrorAction SilentlyContinue)) {
|
||||
Write-Log "First bisync run detected, will initialize with --resync"
|
||||
$needsResync = $true
|
||||
}
|
||||
|
||||
$bisyncArgs = @(
|
||||
"bisync",
|
||||
$llmLocalPath,
|
||||
$llmRemotePath,
|
||||
"--transfers", "4",
|
||||
"--checkers", "8",
|
||||
"--contimeout", "60s",
|
||||
"--timeout", "300s",
|
||||
"--retries", "3",
|
||||
"--log-file", $detailLogFile,
|
||||
"--log-level", "INFO"
|
||||
)
|
||||
|
||||
if ($needsResync) {
|
||||
$bisyncArgs += "--resync"
|
||||
$bisyncArgs += "--resync-mode", "newer"
|
||||
}
|
||||
|
||||
if ($VerboseOutput) {
|
||||
$bisyncArgs += "--progress"
|
||||
}
|
||||
|
||||
try {
|
||||
$result = & $RclonePath @bisyncArgs 2>&1
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Log "Phase 2 complete: _LLM_Sync folder synced successfully" "OK"
|
||||
} else {
|
||||
# bisync can return non-zero for various reasons, check output
|
||||
Write-Log "Phase 2 warning: bisync exited with code $LASTEXITCODE" "WARN"
|
||||
$syncErrors += "_LLM_Sync bisync had warnings (exit code: $LASTEXITCODE)"
|
||||
}
|
||||
} catch {
|
||||
Write-Log "Phase 2 error: $_" "ERROR"
|
||||
$syncErrors += "_LLM_Sync sync failed: $_"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Summary
|
||||
# ------------------------------------------------------------
|
||||
|
||||
$endTime = Get-Date
|
||||
$duration = $endTime - $startTime
|
||||
|
||||
Write-Log "========== Sync Completed =========="
|
||||
Write-Log "Duration: $($duration.TotalSeconds.ToString('F1')) seconds"
|
||||
|
||||
if ($syncErrors.Count -gt 0) {
|
||||
Write-Log "Completed with $($syncErrors.Count) warning(s):" "WARN"
|
||||
foreach ($err in $syncErrors) {
|
||||
Write-Log " - $err" "WARN"
|
||||
}
|
||||
exit 1
|
||||
} else {
|
||||
Write-Log "All syncs completed successfully" "OK"
|
||||
exit 0
|
||||
}
|
||||
Reference in New Issue
Block a user