Files
hexo-deploy/test/v0.0.3/windows/log_rotation_test.ps1
2025-06-02 11:27:10 +08:00

756 lines
34 KiB
PowerShell
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
}