v0.0.3 published

This commit is contained in:
2025-06-02 11:27:10 +08:00
commit dca4f11e0d
61 changed files with 16453 additions and 0 deletions

View File

@@ -0,0 +1,755 @@
# Hexo Container v0.0.3 日志轮转测试脚本 (Windows)
# log_rotation_test.ps1
param(
[string]$ContainerName = "hexo-test-v003",
[int]$HttpPort = 8080,
[int]$SshPort = 2222,
[string]$SshKeyPath = ".\test_data\ssh_keys\test_key",
[int]$TestDeployments = 20,
[int]$LogSizeThresholdMB = 1,
[int]$TotalBatches = 10, # 添加可配置的批次数参数
[switch]$SkipLogGeneration = $false,
[switch]$QuickLogGen = $false,
[switch]$FastRotationTest = $false,
[switch]$CalledFromTestSuite = $false, # 新增参数,用于指示是否从主测试套件调用
[switch]$SshDebug = $false # 新增 SshDebug 参数控制SSH命令的详细程度
)
# 确保脚本在正确的目录下执行
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
Set-Location $ScriptDir
# 确保 SSH 密钥路径为绝对路径
$SshKeyPath = Join-Path $ScriptDir "test_data\ssh_keys\test_key"
Write-Host "=== Hexo Container v0.0.3 日志轮转测试 ===" -ForegroundColor Cyan
Write-Host "这个测试将验证 v0.0.3 版本的新日志轮转功能" -ForegroundColor Gray
# 创建日志目录
$LogDir = ".\logs"
if (-not (Test-Path $LogDir)) {
New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
}
# 函数清理重复的deployment.log文件
function Clear-DuplicateDeploymentLogs {
param([string]$ContainerName)
Write-Host "清理重复的deployment.log文件..." -ForegroundColor Yellow
$bashCommandRaw = @'
cd /var/log/container
LOG_FILE="deployment.log"
# Check if the log file exists and who owns it
if [ -f "$LOG_FILE" ]; then
OWNER=$(stat -c '%U' "$LOG_FILE")
echo "Found existing $LOG_FILE, owner is $OWNER"
if [ "$OWNER" = "root" ]; then
echo "File is owned by root, removing and recreating as hexo user..."
rm -f "$LOG_FILE"
su - hexo -c "touch /var/log/container/$LOG_FILE && chmod 664 /var/log/container/$LOG_FILE"
echo "$LOG_FILE recreated by hexo user."
elif [ "$OWNER" != "hexo" ]; then
echo "File owner is not hexo ($OWNER), attempting to chown to hexo..."
chown hexo:hexo "$LOG_FILE"
chmod 664 "$LOG_FILE"
echo "Permissions corrected for $LOG_FILE."
else
echo "$LOG_FILE is already owned by hexo. Ensuring correct permissions."
chmod 664 "$LOG_FILE"
fi
else
echo "$LOG_FILE not found, creating one as hexo user..."
su - hexo -c "touch /var/log/container/$LOG_FILE && chmod 664 /var/log/container/$LOG_FILE"
echo "$LOG_FILE created by hexo user."
fi
# Verify final state
echo "Final state of $LOG_FILE:"
ls -la "$LOG_FILE"
'@
$bashCommand = $bashCommandRaw.Replace("`r`n", "`n").Replace("`r", "`n")
docker exec $ContainerName bash -c $bashCommand
}
# 如果这是独立运行的日志轮转测试,清理旧的日志文件
# 判断逻辑:当脚本不是从主测试套件调用时
$IsStandaloneExecution = -not $CalledFromTestSuite
Write-Host "执行模式检测:" -ForegroundColor Magenta
Write-Host " CalledFromTestSuite: $CalledFromTestSuite" -ForegroundColor Gray
Write-Host " IsStandaloneExecution: $IsStandaloneExecution" -ForegroundColor Gray
if ($IsStandaloneExecution) {
Write-Host "=== 检测到独立执行或未指定调用来源,将清理旧的相关日志文件 ===" -ForegroundColor Cyan
$OldLogsDir = "$LogDir\old"
if (-not (Test-Path $OldLogsDir)) {
New-Item -ItemType Directory -Path $OldLogsDir -Force | Out-Null
Write-Host "创建旧日志归档目录: $OldLogsDir" -ForegroundColor Gray
}
# 检查 deployment.log 是否需要处理
function Test-DeploymentLogCompatibility {
param([string]$DeploymentLogPath)
if (-not (Test-Path $DeploymentLogPath)) {
return $false
}
try {
$fileSize = (Get-Item $DeploymentLogPath).Length
$fileSizeKB = [math]::Round($fileSize / 1024, 2)
Write-Host "检测到现有 deployment.log大小: $fileSizeKB KB" -ForegroundColor Gray
# 根据当前测试模式判断是否保留
if ($SkipLogGeneration) {
Write-Host "跳过日志生成模式:保留现有 deployment.log" -ForegroundColor Green
return $true
} elseif ($FastRotationTest) {
if ($fileSizeKB -ge 2 -and $fileSizeKB -le 10) {
Write-Host "检测到快速轮转测试模式的现有文件,保留使用" -ForegroundColor Green
return $true
}
} elseif ($QuickLogGen) {
if ($fileSizeKB -ge 10 -and $fileSizeKB -le 100) {
Write-Host "检测到快速日志生成模式的现有文件,保留使用" -ForegroundColor Green
return $true
}
} else {
if ($fileSizeKB -ge 300) {
Write-Host "检测到正常模式的现有文件,保留使用" -ForegroundColor Green
return $true
}
}
Write-Host "现有文件不符合当前测试模式要求,需要重新生成" -ForegroundColor Yellow
return $false
} catch {
Write-Host "检查 deployment.log 兼容性时出错: $($_.Exception.Message)" -ForegroundColor Yellow
return $false
}
}
# 检查 deployment.log 是否需要处理
$DeploymentLogPath = "$LogDir\\deployment.log"
# $KeepDeploymentLog = Test-DeploymentLogCompatibility -DeploymentLogPath $DeploymentLogPath # 这部分逻辑由 start.ps1 处理,独立运行时通常不保留
# 移动旧的日志文件到 old 文件夹 (仅处理 log_rotation_test 相关日志和 deployment.log)
$OldLogFiles = Get-ChildItem $LogDir -File | Where-Object {
($_.Name -like "log_rotation_test_*.log" -or $_.Name -like "log_rotation_test_report_*.txt" -or $_.Name -eq "deployment.log")
}
if ($OldLogFiles.Count -gt 0) {
Write-Host "归档 $($OldLogFiles.Count) 个旧日志文件到 old 文件夹..." -ForegroundColor Gray
foreach ($file in $OldLogFiles) {
$destPath = Join-Path $OldLogsDir $file.Name
Move-Item $file.FullName $destPath -Force
Write-Host " 移动: $($file.Name)" -ForegroundColor Gray
}
} else {
Write-Host "没有旧日志文件需要归档" -ForegroundColor Gray
}
# 处理容器内的 deployment.log
Write-Host "处理容器内的 deployment.log (独立执行模式)..." -ForegroundColor Gray
try {
$ContainerStatus = docker ps -f "name=$ContainerName" --format "{{.Names}}" 2>$null | Select-String $ContainerName
if ($ContainerStatus) {
# 在独立执行时,通常我们希望从一个干净的 deployment.log 开始测试轮转
Write-Host "发现运行中的容器,清空容器内的 deployment.log..." -ForegroundColor Gray
$cleanupCommandRaw = "echo '' > /var/log/container/deployment.log && chown hexo:hexo /var/log/container/deployment.log && chmod 664 /var/log/container/deployment.log"
$cleanupCommand = $cleanupCommandRaw.Replace("`r`n", "`n").Replace("`r", "`n")
docker exec $ContainerName sh -c $cleanupCommand 2>$null
if ($LASTEXITCODE -eq 0) {
Write-Host "容器内 deployment.log 已清空并设置权限" -ForegroundColor Green
} else {
Write-Host "清空容器内 deployment.log 失败" -ForegroundColor Yellow
}
} else {
Write-Host "容器未运行,无法处理容器内的 deployment.log" -ForegroundColor Yellow
}
} catch {
Write-Host "处理容器内 deployment.log 时出错: $($_.Exception.Message)" -ForegroundColor Yellow
}
} else {
Write-Host "=== 检测到通过测试套件调用,跳过旧文件清理和容器内 deployment.log 的预处理 ===" -ForegroundColor Yellow
Write-Host "注意: 日志文件清理和容器内 deployment.log 的初始状态将由主控脚本 start.ps1 负责" -ForegroundColor Gray
}
$TimeStamp = Get-Date -Format "yyyyMMdd_HHmmss"
$TestLog = "$LogDir\log_rotation_test_$TimeStamp.log"
# 检查容器是否运行
Write-Host "`n检查容器状态..." -ForegroundColor Yellow
$ContainerRunning = docker ps --filter "name=$ContainerName" --format "{{.Names}}" | Select-String $ContainerName
if (-not $ContainerRunning) {
Write-Host "ERROR: 容器 $ContainerName 未运行,请先运行 run_test.ps1" -ForegroundColor Red
exit 1
}
Write-Host "SUCCESS: 容器正在运行" -ForegroundColor Green
# 修复日志文件权限(在测试开始前)
Write-Host "`n修复日志文件权限..." -ForegroundColor Yellow
try {
# 确保日志目录存在且权限正确
$bashCommandMkdirRaw = @'
mkdir -p /var/log/container && chown hexo:hexo /var/log/container && chmod 755 /var/log/container
'@
$bashCommandMkdir = $bashCommandMkdirRaw.Replace("`r`n", "`n").Replace("`r", "`n")
docker exec $ContainerName bash -c $bashCommandMkdir
# 清理重复的deployment.log文件
Clear-DuplicateDeploymentLogs -ContainerName $ContainerName
if ($LASTEXITCODE -eq 0) {
Write-Host "SUCCESS: 日志文件权限已修复" -ForegroundColor Green
} else {
Write-Host "WARNING: 权限修复可能失败,但继续测试" -ForegroundColor Yellow
}
} catch {
Write-Host "WARNING: 权限修复时出错: $($_.Exception.Message)" -ForegroundColor Yellow
}
# 检查 SSH 密钥
if (-not (Test-Path $SshKeyPath)) {
Write-Host "ERROR: SSH 密钥不存在: $SshKeyPath" -ForegroundColor Red
Write-Host "请先运行 run_test.ps1 生成 SSH 密钥" -ForegroundColor Red
exit 1
}
# 额外的权限验证和修复
Write-Host "`n进行额外的权限验证和修复..." -ForegroundColor Yellow
try {
# 验证当前权限状态 - 使用LANG=C避免中文编码问题
$bashCommandLsRaw = @'
LANG=C ls -la /var/log/container/deployment.log 2>/dev/null || echo 'FILE_NOT_FOUND'
'@
$bashCommandLs = $bashCommandLsRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$currentPermissions = docker exec $ContainerName bash -c $bashCommandLs 2>$null
Write-Host "当前文件权限: $currentPermissions" -ForegroundColor Gray
# 静默修复权限(减少错误输出)
Write-Host "验证和修复权限..." -ForegroundColor Gray
$bashCommandFixRaw = @'
# 确保目录存在(静默执行)
mkdir -p /var/log/container >/dev/null 2>&1
chown hexo:hexo /var/log/container >/dev/null 2>&1
chmod 755 /var/log/container >/dev/null 2>&1
LOG_FILE="/var/log/container/deployment.log"
# 如果文件存在且是root拥有的则删除
if [ -f "$LOG_FILE" ]; then
OWNER=$(stat -c '%U' "$LOG_FILE" 2>/dev/null || echo "unknown")
if [ "$OWNER" = "root" ]; then
rm -f "$LOG_FILE" >/dev/null 2>&1
fi
fi
# 创建文件如果不存在 (确保以hexo用户创建)
if [ ! -f "$LOG_FILE" ]; then
su - hexo -c "touch $LOG_FILE" >/dev/null 2>&1
fi
# 设置正确的所有者和权限
chown hexo:hexo "$LOG_FILE" >/dev/null 2>&1
chmod 664 "$LOG_FILE" >/dev/null 2>&1
# 验证修复结果
if [ -f "$LOG_FILE" ]; then
echo "SUCCESS"
else
echo "FAILED"
fi
'@
$bashCommandFix = $bashCommandFixRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$permissionResult = docker exec $ContainerName bash -c $bashCommandFix 2>$null
if ($permissionResult -eq "SUCCESS") {
Write-Host "SUCCESS: 权限验证和修复完成" -ForegroundColor Green
} else {
Write-Host "FAILED: 权限修复失败,但测试将继续进行" -ForegroundColor Yellow
}
# 测试hexo用户的写入权限
Write-Host "测试hexo用户写入权限..." -ForegroundColor Gray
$bashCommandWriteTestRaw = @'
su - hexo -c 'echo "PERMISSION_TEST_$(date)" >> /var/log/container/deployment.log 2>/dev/null' && echo 'SUCCESS' || echo 'FAILED'
'@
$bashCommandWriteTest = $bashCommandWriteTestRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$testResult = docker exec $ContainerName bash -c $bashCommandWriteTest 2>$null
if ($testResult -eq "SUCCESS") {
Write-Host "SUCCESS: hexo用户可以正常写入日志文件" -ForegroundColor Green
} else {
Write-Host "FAILED: hexo用户无法写入日志文件这会影响测试结果" -ForegroundColor Yellow
}
# 静默检查SSH配置减少输出
Write-Host "验证hexo用户SSH配置..." -ForegroundColor Gray
$bashCommandSshCheckRaw = @'
# 静默设置SSH权限
su - hexo -c "mkdir -p /home/hexo/.ssh && chmod 700 /home/hexo/.ssh" >/dev/null 2>&1
su - hexo -c "touch /home/hexo/.ssh/authorized_keys && chmod 600 /home/hexo/.ssh/authorized_keys" >/dev/null 2>&1
# 验证SSH配置是否正确
if [ -d "/home/hexo/.ssh" ] && [ -f "/home/hexo/.ssh/authorized_keys" ]; then
echo "SUCCESS"
else
echo "FAILED"
fi
'@
$bashCommandSshCheck = $bashCommandSshCheckRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$sshResult = docker exec $ContainerName bash -c $bashCommandSshCheck 2>$null
if ($sshResult -eq "SUCCESS") {
Write-Host "SUCCESS: SSH配置验证完成" -ForegroundColor Green
} else {
Write-Host "FAILED: SSH配置验证失败" -ForegroundColor Yellow
}
} catch {
Write-Host "WARNING: 额外权限修复时出错: $($_.Exception.Message)" -ForegroundColor Yellow
}
# 函数:获取日志文件大小
function Get-LogFileSize {
param([string]$LogPath)
try {
$bashCommandStatRaw = "stat -c%s $LogPath 2>/dev/null; if [ `$? -ne 0 ]; then echo 0; fi"
$bashCommandStat = $bashCommandStatRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$SizeBytes = docker exec $ContainerName bash -c $bashCommandStat
if ($null -eq $SizeBytes -or $SizeBytes -eq "") {
return 0
}
return [int]$SizeBytes
} catch {
return 0
}
}
# 函数:获取日志文件列表
function Get-LogFileList {
try {
# 使用 LANG=C 强制英文输出,避免中文编码问题
# 修复:更精确的文件过滤,避免重复行和非预期匹配
$bashCommandLsLogsRaw = 'LANG=C ls -la /var/log/container/*.log* 2>/dev/null | sort -u || echo "No log files found"'
$bashCommandLsLogs = $bashCommandLsLogsRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$Files = docker exec $ContainerName bash -c $bashCommandLsLogs
return $Files
} catch {
return @()
}
}
# 函数:生成测试日志内容
function New-LogContent {
param([int]$Count)
Write-Host "生成 $Count 条测试日志..." -ForegroundColor Yellow
for ($i = 1; $i -le $Count; $i++) {
$CurrentTime = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
try {
$SshVerbosityArgs = ""
if ($SshDebug) {
$SshVerbosityArgs = "-vvv"
Write-Host "SshDebug is ON, using verbose SSH output." -ForegroundColor DarkGray
} else {
$SshVerbosityArgs = "-q -o LogLevel=ERROR"
}
# Construct the remote command part - use simpler approach
$LogEntry = "TEST_LOG_ENTRY_$i : $CurrentTime - Entry $i of $Count"
# Use Start-Process for better control over command execution
$ProcessArgs = @(
$SshVerbosityArgs -split ' '
"-p", $SshPort
"-i", $SshKeyPath
"-o", "ConnectTimeout=10"
"-o", "StrictHostKeyChecking=no"
"-o", "UserKnownHostsFile=/dev/null"
"hexo@localhost"
"echo '$LogEntry' >> /var/log/container/deployment.log"
) | Where-Object { $_ -ne "" }
if ($SshDebug) {
Write-Host "Executing SSH command: ssh $($ProcessArgs -join ' ')" -ForegroundColor DarkGray
}
$process = Start-Process -FilePath "ssh" -ArgumentList $ProcessArgs -Wait -PassThru -NoNewWindow -RedirectStandardOutput "stdout.tmp" -RedirectStandardError "stderr.tmp"
if ($process.ExitCode -ne 0) {
$sshError = if (Test-Path "stderr.tmp") { Get-Content "stderr.tmp" -Raw } else { "No error output" }
Write-Host "SSH command failed. Exit code: $($process.ExitCode)" -ForegroundColor Red
Write-Host "SSH output: $sshError" -ForegroundColor Red
} else {
if ($SshDebug) {
$sshOutput = if (Test-Path "stdout.tmp") { Get-Content "stdout.tmp" -Raw } else { "" }
if ($sshOutput) {
Write-Host "SSH output: $sshOutput" -ForegroundColor DarkGray
}
}
}
# Clean up temp files
Remove-Item "stdout.tmp", "stderr.tmp" -ErrorAction SilentlyContinue
if ($i % 10 -eq 0) {
Write-Host "已生成 $i/$Count 条日志" -ForegroundColor Gray
}
Start-Sleep -Milliseconds 10
} catch {
Write-Host "生成日志失败: $($_.Exception.Message)" -ForegroundColor Red
# Optionally, log the command that failed if SshDebug is on
if ($SshDebug) {
Write-Host "Failed SSH command with args: $($ProcessArgs -join ' ')" -ForegroundColor DarkGray
}
break
}
}
}
# 开始测试
"=== 日志轮转测试开始 $(Get-Date) ===" | Add-Content $TestLog
Write-Host "`n=== 步骤 1: 检查初始日志状态 ===" -ForegroundColor Cyan
$InitialLogFiles = Get-LogFileList
Write-Host "初始日志文件:" -ForegroundColor Gray
$InitialLogFiles | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
$InitialLogSize = Get-LogFileSize "/var/log/container/deployment.log"
Write-Host "部署日志初始大小: $($InitialLogSize / 1024) KB" -ForegroundColor Gray
"初始日志大小: $InitialLogSize bytes" | Add-Content $TestLog
Write-Host "`n=== 步骤 2: 检查日志轮转配置 ===" -ForegroundColor Cyan
# 检查日志轮转函数是否存在
$RotateFunctionCheckCommand = 'grep -q setup_log_rotation /root/start.sh; if [ $? -eq 0 ]; then echo FUNCTION_EXISTS; else echo FUNCTION_NOT_FOUND; fi'
$CleanRotateFunctionCheckCommand = $RotateFunctionCheckCommand.Replace("`r`n", "`n").Replace("`r", "`n")
$RotateFunctionCheck = docker exec $ContainerName bash -c $CleanRotateFunctionCheckCommand
if ($RotateFunctionCheck -eq "FUNCTION_EXISTS") {
Write-Host "SUCCESS: 日志轮转函数存在" -ForegroundColor Green
} else {
Write-Host "FAIL: 日志轮转函数不存在" -ForegroundColor Red
}
# 检查定期检查功能
$PeriodicCheckCommand = 'grep -q setup_log_rotation /root/start.sh; if [ $? -eq 0 ]; then echo PERIODIC_EXISTS; else echo PERIODIC_NOT_FOUND; fi'
$CleanPeriodicCheckCommand = $PeriodicCheckCommand.Replace("`r`n", "`n").Replace("`r", "`n")
$PeriodicCheck = docker exec $ContainerName bash -c $CleanPeriodicCheckCommand
if ($PeriodicCheck -eq "PERIODIC_EXISTS") {
Write-Host "SUCCESS: 定期日志检查功能存在" -ForegroundColor Green
} else {
Write-Host "FAIL: 定期日志检查功能不存在" -ForegroundColor Red
}
# 检查日志轮转配置文件
$LogrotateConfigCheckCommand = 'test -f /etc/logrotate.d/deployment; if [ $? -eq 0 ]; then echo CONFIG_EXISTS; else echo CONFIG_NOT_FOUND; fi'
$CleanLogrotateConfigCheckCommand = $LogrotateConfigCheckCommand.Replace("`r`n", "`n").Replace("`r", "`n")
$LogrotateConfigCheck = docker exec $ContainerName bash -c $CleanLogrotateConfigCheckCommand
if ($LogrotateConfigCheck -eq "CONFIG_EXISTS") {
Write-Host "SUCCESS: 日志轮转配置文件存在" -ForegroundColor Green
} else {
Write-Host "FAIL: 日志轮转配置文件不存在" -ForegroundColor Red
}
Write-Host "`n=== 步骤 3: 生成测试日志 ===" -ForegroundColor Cyan
# 调试信息:显示参数传递情况
Write-Host "参数调试信息:" -ForegroundColor Magenta
Write-Host " TotalBatches = $TotalBatches (来自参数)" -ForegroundColor Magenta
Write-Host " FastRotationTest = $FastRotationTest" -ForegroundColor Magenta
Write-Host " QuickLogGen = $QuickLogGen" -ForegroundColor Magenta
Write-Host " PSBoundParameters.ContainsKey('TotalBatches') = $($PSBoundParameters.ContainsKey('TotalBatches'))" -ForegroundColor Magenta
if ($FastRotationTest) {
Write-Host "快速轮转测试模式: 生成少量日志以快速验证轮转机制" -ForegroundColor Yellow
Write-Host "注意: 快速模式主要验证轮转机制,而非大文件轮转" -ForegroundColor Gray
# 快速轮转测试模式:生成更少的日志
$FastBatchSize = 50
# 只有在用户没有明确指定TotalBatches时才使用默认值
if ($PSBoundParameters.ContainsKey('TotalBatches') -eq $false) {
$TotalBatches = 3
Write-Host " 未指定TotalBatches使用快速模式默认值: $TotalBatches" -ForegroundColor Magenta
} else {
Write-Host " 使用用户指定的TotalBatches: $TotalBatches" -ForegroundColor Magenta
}
Write-Host "快速轮转测试: 将生成 $TotalBatches 批次,每批次 $FastBatchSize 条日志 (总计约$(($TotalBatches * $FastBatchSize * 211) / 1024)KB)" -ForegroundColor Gray
} elseif ($QuickLogGen) {
Write-Host "快速日志生成模式: 生成少量日志数据以验证日志轮转机制" -ForegroundColor Yellow
Write-Host "注意: 快速模式不会触发大文件轮转,但会验证日志写入和权限" -ForegroundColor Gray
# 快速日志生成模式如果没有指定TotalBatches参数则使用默认值5
if ($PSBoundParameters.ContainsKey('TotalBatches') -eq $false) {
$TotalBatches = 5
Write-Host " 未指定TotalBatches使用快速日志生成默认值: $TotalBatches" -ForegroundColor Magenta
} else {
Write-Host " 使用用户指定的TotalBatches: $TotalBatches" -ForegroundColor Magenta
}
$BatchSize = 100
Write-Host "快速日志生成: 将生成 $TotalBatches 批次,每批次 $BatchSize 条日志" -ForegroundColor Gray
} else {
Write-Host "目标: 生成超过 ${LogSizeThresholdMB}MB 的日志数据以触发轮转" -ForegroundColor Gray
Write-Host "注意: 针对测试环境,日志轮转阈值已设置为 20KB" -ForegroundColor Yellow
# 计算需要生成的日志条数实际测量每条约211字节20KB需要约95条日志
$LogEntrySize = 211 # 基于实际测量结果更新
$TargetBytes = 20 * 1024 # 20KB 固定目标,确保能触发轮转
$RequiredEntries = [Math]::Ceiling($TargetBytes / $LogEntrySize)
Write-Host "预计需要生成 $RequiredEntries 条日志以触发 20KB 轮转 (基于实际测量的 $LogEntrySize 字节/条)" -ForegroundColor Gray
# 分批生成日志 - 使用传入的TotalBatches参数默认为10个批次
$BatchSize = 100
# $TotalBatches 使用参数传入的值,不再重新赋值
Write-Host "将生成 $TotalBatches 个批次,每批次 $BatchSize 条日志" -ForegroundColor Gray
}
# 开始日志生成和轮转测试
if (-not $SkipLogGeneration) {
$TotalLogsGenerated = 0
for ($batch = 1; $batch -le $TotalBatches; $batch++) {
if ($FastRotationTest) {
$CurrentBatchSize = $FastBatchSize
} elseif ($QuickLogGen) {
$CurrentBatchSize = $BatchSize
} else {
# 固定每个批次大小为 100 条日志
$CurrentBatchSize = $BatchSize
}
Write-Host "批次 $batch/$TotalBatches : 生成 $CurrentBatchSize 条日志..." -ForegroundColor Yellow
# 记录批次开始前的日志行数
$bashCommandWcBeforeRaw = "LANG=C wc -l < /var/log/container/deployment.log 2>/dev/null || echo 0"
$bashCommandWcBefore = $bashCommandWcBeforeRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$LogCountBefore = docker exec $ContainerName bash -c $bashCommandWcBefore
New-LogContent -Count $CurrentBatchSize
# 记录批次结束后的日志行数
$bashCommandWcAfterRaw = "LANG=C wc -l < /var/log/container/deployment.log 2>/dev/null || echo 0"
$bashCommandWcAfter = $bashCommandWcAfterRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$LogCountAfter = docker exec $ContainerName bash -c $bashCommandWcAfter
$ActualLogsAdded = [int]$LogCountAfter - [int]$LogCountBefore
$TotalLogsGenerated += $ActualLogsAdded
Write-Host "实际添加日志: $ActualLogsAdded 条 (总计: $TotalLogsGenerated 条)" -ForegroundColor Gray
# 检查当前日志大小
$CurrentLogSize = Get-LogFileSize "/var/log/container/deployment.log"
Write-Host "当前日志大小: $($CurrentLogSize / 1024) KB" -ForegroundColor Gray
"批次 $batch 完成,当前日志大小: $CurrentLogSize bytes" | Add-Content $TestLog
# 检查是否需要触发日志轮转如果超过20KB
$ThresholdBytes = 20 * 1024 # 20KB
if ($CurrentLogSize -gt $ThresholdBytes) {
Write-Host "日志大小超过 20KB 阈值,尝试触发日志轮转..." -ForegroundColor Yellow
$bashCommandLogrotateRaw = "LANG=C logrotate -f /etc/logrotate.d/deployment"
$bashCommandLogrotate = $bashCommandLogrotateRaw.Replace("`r`n", "`n").Replace("`r", "`n")
docker exec $ContainerName bash -c $bashCommandLogrotate | Out-Null
Start-Sleep -Seconds 1
# 重新检查文件大小
$NewLogSize = Get-LogFileSize "/var/log/container/deployment.log"
Write-Host "轮转后日志大小: $($NewLogSize / 1024) KB" -ForegroundColor Gray
} # 检查是否触发了日志轮转(排除.lock文件
$bashCommandLsBackupRaw = "LANG=C ls -la /var/log/container/ | grep 'deployment\.log\.' | grep -v '\.lock' | grep -v '^-.*deployment\.log$'"
$bashCommandLsBackup = $bashCommandLsBackupRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$BackupFiles = docker exec $ContainerName bash -c $bashCommandLsBackup 2>$null
if ($BackupFiles) {
Write-Host "检测到备份文件,日志轮转已触发:" -ForegroundColor Green
$BackupFiles | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
}
# 为快速轮转测试在每个批次后短暂暂停
if ($FastRotationTest) {
Start-Sleep -Seconds 2
}
}
} else {
Write-Host "跳过日志生成步骤 (-SkipLogGeneration 已设置)" -ForegroundColor Yellow
}
Write-Host "`n=== 步骤 4: 验证日志轮转结果 ===" -ForegroundColor Cyan
# 检查最终日志状态
$FinalLogFiles = Get-LogFileList
Write-Host "最终日志文件:" -ForegroundColor Gray
$FinalLogFiles | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
$CurrentLogSize = Get-LogFileSize "/var/log/container/deployment.log"
Write-Host "最终日志大小: $($CurrentLogSize / 1024) KB" -ForegroundColor Gray
# 检查备份文件(排除.lock文件
$BackupFileCommandRaw = "LANG=C ls -la /var/log/container/ | grep 'deployment\.log\.' | grep -v '\.lock' | grep -v '^-.*deployment\.log$' | wc -l"
$BackupFileCommand = $BackupFileCommandRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$BackupFileCount = docker exec $ContainerName bash -c $BackupFileCommand 2>$null
Write-Host "备份文件数量: $BackupFileCount" -ForegroundColor Gray
# 详细分析日志轮转效果
Write-Host "`n=== 日志轮转分析报告 ===" -ForegroundColor Cyan
if (-not $SkipLogGeneration) {
Write-Host "总共生成日志条数: $TotalLogsGenerated" -ForegroundColor Gray
$EstimatedTotalSize = $TotalLogsGenerated * 211 # 基于实际测量的字节数
Write-Host "预估总数据量: $($EstimatedTotalSize / 1024) KB" -ForegroundColor Gray
}
# 获取所有日志文件的详细信息
# $bashCommandLsAll = ("LANG=C ls -la /var/log/container/deployment.log*" -replace "\\\\r\\\\n", "\\\\n") # Fix CRLF
$bashCommandLsAllRaw = "LANG=C ls -la /var/log/container/deployment.log*"
$bashCommandLsAll = $bashCommandLsAllRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$AllLogFiles = docker exec $ContainerName bash -c $bashCommandLsAll 2>$null
if ($AllLogFiles) {
Write-Host "所有相关日志文件:" -ForegroundColor Gray
$AllLogFiles | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
# 计算总的日志文件大小
$TotalLogSize = 0
$AllLogFiles | ForEach-Object {
if ($_ -match '\s+(\d+)\s+.*deployment\.log') {
$TotalLogSize += [int]$matches[1]
}
}
Write-Host "所有日志文件总大小: $($TotalLogSize / 1024) KB" -ForegroundColor Gray
}
# 测试评估
$TestResults = @()
# 测试1: 检查日志轮转函数
if ($RotateFunctionCheck -eq "FUNCTION_EXISTS") {
$TestResults += "日志轮转函数: PASS"
} else {
$TestResults += "日志轮转函数: FAIL"
}
# 测试2: 检查定期检查功能
if ($PeriodicCheck -eq "PERIODIC_EXISTS") {
$TestResults += "定期检查函数: PASS"
} else {
$TestResults += "定期检查函数: FAIL"
}
# 测试3: 检查配置文件
if ($LogrotateConfigCheck -eq "CONFIG_EXISTS") {
$TestResults += "轮转配置文件: PASS"
} else {
$TestResults += "轮转配置文件: FAIL"
}
# 测试4: 检查日志权限
$bashCommandPermCheckRaw = "LANG=C ls -la /var/log/container/deployment.log | awk '{print `$1, `$3, `$4}'"
$bashCommandPermCheck = $bashCommandPermCheckRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$LogPermissionCheck = docker exec $ContainerName bash -c $bashCommandPermCheck
Write-Host "日志文件权限: $LogPermissionCheck" -ForegroundColor Gray
if ($LogPermissionCheck -match "hexo.*hexo") {
$TestResults += "日志权限: PASS"
} else {
$TestResults += "日志权限: FAIL"
}
# 测试5: 检查备份文件命名(排除.lock文件
$bashCommandBackupNameRaw = "LANG=C ls /var/log/container/ | grep 'deployment\.log\.[0-9]' | grep -v '\.lock' | head -1"
$bashCommandBackupName = $bashCommandBackupNameRaw.Replace("`r`n", "`n").Replace("`r", "`n")
$BackupNamingCheck = docker exec $ContainerName bash -c $bashCommandBackupName 2>$null
if ($BackupNamingCheck) {
$TestResults += "备份文件命名: PASS"
} else {
$TestResults += "备份文件命名: FAIL - 没有找到正确命名的备份文件"
}
if (-not $FastRotationTest -and -not $QuickLogGen) {
# 测试6: 检查日志大小重置(仅在完整测试中)
if ($CurrentLogSize -lt $InitialLogSize -or $BackupFileCount -gt 0) {
$TestResults += "日志大小重置: PASS"
} else {
$TestResults += "日志大小重置: FAIL - 日志未被轮转"
}
} else {
$TestResults += "日志大小重置: SKIP - 快速测试模式"
}
# 计算成功率
$TotalTests = $TestResults.Count
$PassedTests = ($TestResults | Where-Object { $_ -match "PASS" }).Count
$SkippedTests = ($TestResults | Where-Object { $_ -match "SKIP" }).Count
$FailedTests = $TotalTests - $PassedTests - $SkippedTests
$SuccessRate = [Math]::Round(($PassedTests / $TotalTests) * 100, 2)
Write-Host "`n=== 测试结果汇总 ===" -ForegroundColor Cyan
Write-Host "总测试项: $TotalTests" -ForegroundColor Gray
Write-Host "通过: $PassedTests" -ForegroundColor Green
Write-Host "跳过: $SkippedTests" -ForegroundColor Yellow
Write-Host "失败: $FailedTests" -ForegroundColor Red
Write-Host "成功率: $SuccessRate%" -ForegroundColor Gray
Write-Host "`n详细结果:" -ForegroundColor Gray
$TestResults | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
# 保存测试报告
$TestMode = if ($FastRotationTest) { "快速轮转测试" } elseif ($QuickLogGen) { "快速日志生成" } else { "完整轮转测试" }
$PeriodicCheckResult = if ($TestResults | Where-Object { $_ -match "定期检查函数: PASS" }) { "通过" } else { "失败" }
$PermissionCheckResult = if ($TestResults | Where-Object { $_ -match "日志权限: PASS" }) { "通过" } else { "失败" }
$SizeControlCheckResult = if ($TestResults | Where-Object { $_ -match "日志大小重置: PASS" }) {
"通过"
} elseif ($TestResults | Where-Object { $_ -match "日志大小重置: SKIP" }) {
"跳过(快速测试模式)"
} else {
"失败"
}
$BackupNamingCheckResult = if ($TestResults | Where-Object { $_ -match "备份文件命名: PASS" }) { "通过" } else { "失败" }
$DetailedResults = $TestResults | ForEach-Object { $_ } | Out-String
$ReportContent = @"
=== Hexo Container v0.0.3 ===
: $(Get-Date)
: $ContainerName
: ${LogSizeThresholdMB}MB
: $TestMode
=== ===
: $TotalTests
: $PassedTests
: $SkippedTests
: $FailedTests
: $SuccessRate%
=== ===
$DetailedResults
=== ===
: $($InitialLogSize / 1024) KB
: $($CurrentLogSize / 1024) KB
: $BackupFileCount
=== v0.0.3 ===
- : $PeriodicCheckResult
- Git Hook : $PermissionCheckResult
- : $SizeControlCheckResult
- : $BackupNamingCheckResult
"@
$ReportFile = "$LogDir\log_rotation_test_report_$TimeStamp.txt"
$ReportContent | Out-File -FilePath $ReportFile -Encoding UTF8
Write-Host "`n详细测试日志: $TestLog" -ForegroundColor Gray
Write-Host "测试报告: $ReportFile" -ForegroundColor Gray
# 清理提示
Write-Host "`n=== 测试完成 ===" -ForegroundColor Cyan
Write-Host "日志轮转功能测试已完成。如需清理测试环境,请运行:" -ForegroundColor Gray
Write-Host " .\cleanup_test.ps1" -ForegroundColor Gray
# 根据测试结果设置退出代码
if ($FailedTests -eq 0) {
Write-Host "SUCCESS: 所有日志轮转测试通过!" -ForegroundColor Green
exit 0
} else {
Write-Host "WARNING: 部分日志轮转测试失败,请检查详细报告。" -ForegroundColor Yellow
exit 1
}