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,121 @@
# Linux 测试套件端口映射修改报告
## 📋 修改概述
**任务**: 将 Linux 测试套件中的 HTTP 端口映射从 8888 改为 8080
**完成日期**: 2025年6月1日
**状态**: ✅ **完成** - 所有测试通过
## 🔧 修改的文件
### 1. `/home/bhk/Desktop/dockerfiledir/test/v0.0.3/linux/run_test.sh`
```bash
# 修改前
HTTP_PORT=${3:-8888}
# 修改后
HTTP_PORT=${3:-8080}
```
### 2. `/home/bhk/Desktop/dockerfiledir/test/v0.0.3/linux/functional_test.sh`
```bash
# 修改前
HTTP_PORT=${2:-8888}
# 修改后
HTTP_PORT=${2:-8080}
```
### 3. `/home/bhk/Desktop/dockerfiledir/test/v0.0.3/linux/test_paths.sh`
```bash
# 修改前
DEFAULT_PORTS=(8888 2222)
# 修改后
DEFAULT_PORTS=(8080 2222)
```
## ✅ 验证结果
### 端口映射验证
- ✅ Docker 容器正确绑定到 `8080:80` 端口
- ✅ HTTP 服务可通过 http://localhost:8080 访问
- ✅ 健康检查端点 http://localhost:8080/health 正常工作
- ✅ SSH 端口 2222 保持不变
### 完整测试套件结果
```
测试时间: 2025年6月1日 01:50:37
总测试数: 5
通过测试: 5/5
失败测试: 0/5
成功率: 100%
总耗时: 145s
```
### 各模块测试结果
-**构建测试** (build_test.sh) - 通过
-**运行测试** (run_test.sh) - 通过 (使用8080端口)
-**功能测试** (functional_test.sh) - 通过 (验证8080端口HTTP服务)
-**日志轮转测试** (log_rotation_test.sh) - 通过
-**清理测试** (cleanup_test.sh) - 通过
## 🔍 技术细节
### Docker 运行命令示例
```bash
docker run -d \
--name hexo-test-v003 \
-p 8080:80 \ # 新的端口映射
-p 2222:22 \ # SSH端口保持不变
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Asia/Shanghai \
hexo-test:v0.0.3
```
### 访问地址更新
- **HTTP 访问**: http://localhost:8080 (原 8888)
- **健康检查**: http://localhost:8080/health (原 8888)
- **SSH 连接**: ssh -p 2222 hexo@localhost (保持不变)
## 📊 影响范围
### 自动处理的部分
- ✅ 所有使用 `$HTTP_PORT` 变量的地方都自动更新
- ✅ 容器端口映射自动更新到8080
- ✅ HTTP连接测试自动使用新端口
- ✅ 健康检查端点自动使用新端口
### 无需额外修改的部分
- ✅ 容器内部服务仍然运行在80端口
- ✅ SSH服务端口(2222)保持不变
- ✅ 日志轮转功能不受影响
- ✅ 测试脚本逻辑保持不变
## 🎯 验证步骤
1. **端口占用检查**: 确认8080端口可用
2. **容器启动**: 验证容器使用8080端口启动
3. **HTTP服务**: 测试HTTP服务通过8080端口访问
4. **功能测试**: 所有功能测试使用新端口
5. **完整套件**: 运行完整测试套件验证兼容性
## 📝 注意事项
- **向后兼容**: 可通过参数指定其他端口 `./run_test.sh hexo-test <port>`
- **环境隔离**: 修改只影响Linux测试套件Windows测试套件保持独立
- **文档更新**: 相关文档和README需要更新端口信息
## 🚀 后续建议
1. **文档更新**: 更新测试指南中的端口信息
2. **端口标准化**: 考虑在所有环境中统一使用8080端口
3. **配置管理**: 考虑将端口配置集中管理
---
**修改完成**: ✅ 所有测试通过
**端口映射**: 8888 → 8080
**测试验证**: 100% 成功率
**兼容性**: 完全兼容现有功能

318
test/v0.0.3/linux/README.md Normal file
View File

@@ -0,0 +1,318 @@
# Hexo Container v0.0.3 测试脚本使用说明 (Linux)
## 路径修正说明
本次更新修正了 `test/v0.0.3/linux` 目录下所有测试脚本的路径问题,确保脚本能够:
1. **正确调用对应文件** - 无论从哪个目录执行脚本
2. **正确生成文件** - 所有生成的文件都保存在测试目录及其子目录中
3. **使用相对路径** - 提高脚本的可移植性
## 修正的关键问题
### 1. 脚本工作目录统一
- 所有脚本现在都会自动切换到脚本所在目录作为工作目录
- 使用 `SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"` 获取脚本目录
- 使用 `cd "$SCRIPT_DIR"` 设置工作目录
### 2. 路径引用修正
- **Dockerfile 路径**: `../../../Dockerfile_v0.0.3` (相对于测试脚本目录)
- **日志目录**: `$SCRIPT_DIR/logs` (在测试脚本目录下)
- **测试数据**: `$SCRIPT_DIR/test_data` (在测试脚本目录下)
- **SSH 密钥**: `$SCRIPT_DIR/test_data/ssh_keys/test_key`
### 3. Docker 卷挂载路径修正
- 使用 `$SCRIPT_DIR` 构建绝对路径进行卷挂载
- 确保容器能正确访问主机文件
### 4. 端口配置更新
- 默认 HTTP 端口从 8888 更新为 8080
- 避免与常见服务的端口冲突
## 文件结构
```
test/v0.0.3/linux/
├── build_test.sh # 构建测试脚本
├── run_test.sh # 运行测试脚本
├── functional_test.sh # 功能测试脚本
├── log_rotation_test.sh # 日志轮转测试脚本 (v0.0.3新功能)
├── test_log_size_reset.sh # 🆕 日志大小重置专项测试脚本 (容器重启修复验证)
├── cleanup_test.sh # 清理测试脚本
├── start.sh # 一键测试套件
├── test_paths.sh # 路径验证脚本 (新增)
├── README.md # 使用说明文档 (新增)
├── logs/ # 测试日志目录 (自动创建)
└── test_data/ # 测试数据目录 (自动创建)
├── hexo_site/ # 测试站点文件
└── ssh_keys/ # SSH 密钥文件
```
## 使用方式
### 方式1: 从测试目录运行 (推荐)
```bash
cd "/path/to/dockerfiledir/test/v0.0.3/linux"
./start.sh
```
### 方式2: 从任意目录运行
```bash
/path/to/dockerfiledir/test/v0.0.3/linux/start.sh
```
### 方式3: 单独运行各个测试
```bash
cd "/path/to/dockerfiledir/test/v0.0.3/linux"
./build_test.sh # 构建镜像
./run_test.sh # 启动容器
./functional_test.sh # 功能测试
./log_rotation_test.sh # 日志轮转测试
./test_log_size_reset.sh # 🆕 日志大小重置测试 (容器重启修复验证)
./cleanup_test.sh # 清理环境
```
## 测试参数
### start.sh 参数
- `--clean-start`: 清理后重新开始测试
- `--help`: 显示帮助信息
### 各脚本参数
#### build_test.sh
```bash
./build_test.sh [TAG] [PLATFORM]
# TAG: 镜像标签 (默认: hexo-test:v0.0.3)
# PLATFORM: 平台架构 (默认: linux/amd64)
```
#### run_test.sh
```bash
./run_test.sh [TAG] [CONTAINER_NAME] [HTTP_PORT] [SSH_PORT] [PUID] [PGID] [TIMEZONE]
# TAG: 镜像标签 (默认: hexo-test:v0.0.3)
# CONTAINER_NAME: 容器名称 (默认: hexo-test-v003)
# HTTP_PORT: HTTP端口 (默认: 8080)
# SSH_PORT: SSH端口 (默认: 2222)
# PUID: 用户ID (默认: 1000)
# PGID: 组ID (默认: 1000)
# TIMEZONE: 时区 (默认: Asia/Shanghai)
```
#### functional_test.sh
```bash
./functional_test.sh [CONTAINER_NAME] [HTTP_PORT] [SSH_PORT]
# CONTAINER_NAME: 容器名称 (默认: hexo-test-v003)
# HTTP_PORT: HTTP端口 (默认: 8080)
# SSH_PORT: SSH端口 (默认: 2222)
```
#### log_rotation_test.sh
```bash
./log_rotation_test.sh [CONTAINER_NAME] [HTTP_PORT] [SSH_PORT] [OPTIONS]
# CONTAINER_NAME: 容器名称 (默认: hexo-test-v003)
# HTTP_PORT: HTTP端口 (默认: 8080)
# SSH_PORT: SSH端口 (默认: 2222)
# OPTIONS: --fast-test, --quick-gen, --log-threshold-mb N
```
#### test_log_size_reset.sh (🆕 容器重启修复验证)
```bash
./test_log_size_reset.sh [OPTIONS]
# --container-name NAME 容器名称 (默认: hexo-test-v003)
# --ssh-port PORT SSH端口 (默认: 2222)
# --target-size-kb SIZE 目标日志大小KB (默认: 25)
# --verbose 详细输出模式
# --help 显示帮助信息
```
此脚本专门验证容器重启时的日志监控修复功能,确保:
- 容器重启后不会重复输出旧的Git部署信息
- 日志位置跟踪文件正确工作
- 部署日志监控在重启后正常恢复
#### cleanup_test.sh
```bash
./cleanup_test.sh [CONTAINER_NAME] [IMAGE_TAG] [OPTIONS]
# CONTAINER_NAME: 容器名称 (默认: hexo-test-v003)
# IMAGE_TAG: 镜像标签 (默认: hexo-test:v0.0.3)
# OPTIONS: --remove-image, --remove-test-data, --remove-logs
```
### 使用示例
```bash
# 完整测试 (清理模式)
./start.sh --clean-start
# 自定义端口运行
./run_test.sh "hexo-test:v0.0.3" "my-hexo-test" 9999 3333
# 🆕 容器重启修复验证测试
./test_log_size_reset.sh
# 详细模式运行重启修复测试
./test_log_size_reset.sh --verbose
# 自定义目标大小测试
./test_log_size_reset.sh --target-size-kb 30
# 日志轮转快速测试
./log_rotation_test.sh --fast-test
# 彻底清理环境
./cleanup_test.sh --remove-image --remove-test-data --remove-logs
```
## 验证路径配置
运行路径验证脚本检查配置:
```bash
./test_paths.sh
```
此脚本会检查所有关键路径是否正确,并自动创建必需的目录。
## 系统要求
### 基本要求
- **操作系统**: Linux (Ubuntu 18.04+, Debian 10+, CentOS 7+)
- **Docker**: Docker Engine 20.10+
- **Shell**: Bash 4.0+
- **内存**: 至少 2GB 可用内存
- **磁盘**: 至少 5GB 可用磁盘空间
### 必需的系统工具
- `docker` - Docker 容器引擎
- `curl` - HTTP 客户端工具
- `ssh` - SSH 客户端
- `ssh-keygen` - SSH 密钥生成工具
- `netstat` - 网络状态查看工具
### 安装依赖 (Ubuntu/Debian)
```bash
# 更新包管理器
sudo apt-get update
# 安装 Docker
sudo apt-get install docker.io
# 安装其他工具
sudo apt-get install curl openssh-client net-tools
# 将用户添加到 docker 组
sudo usermod -aG docker $USER
newgrp docker
```
### 安装依赖 (CentOS/RHEL)
```bash
# 安装 Docker
sudo yum install docker
# 安装其他工具
sudo yum install curl openssh-clients net-tools
# 启动 Docker 服务
sudo systemctl start docker
sudo systemctl enable docker
# 将用户添加到 docker 组
sudo usermod -aG docker $USER
```
## 注意事项
1. **权限要求**: 确保有 Docker 使用权限(用户在 docker 组中)
2. **端口冲突**: 确保指定的端口未被占用
3. **SSH 密钥**: 测试脚本会自动生成 SSH 密钥对
4. **Docker 环境**: 确保 Docker 服务正在运行
5. **脚本权限**: 确保所有 .sh 文件有执行权限
## 故障排除
### 权限错误
```bash
# 设置脚本执行权限
chmod +x *.sh
# 检查 Docker 权限
docker version
```
### 路径不存在错误
```bash
# 运行路径验证
./test_paths.sh
```
### Docker 连接错误
```bash
# 检查 Docker 状态
sudo systemctl status docker
# 启动 Docker 服务
sudo systemctl start docker
```
### 端口占用错误
```bash
# 查看端口占用
netstat -tlnp | grep :8080
netstat -tlnp | grep :2222
# 杀死占用进程
sudo kill -9 <PID>
```
### 日志查看
```bash
# 查看最新测试日志
ls -la logs/ | tail -5
# 查看特定日志
tail -f logs/test_suite_*.log
# 搜索错误信息
grep -i error logs/*.log
```
## 高级用法
### 自定义配置
```bash
# 使用自定义镜像标签
export HEXO_IMAGE_TAG="my-hexo:custom"
./start.sh
# 使用自定义容器名称
export HEXO_CONTAINER_NAME="my-hexo-container"
./start.sh
```
### 批量测试
```bash
# 测试多个端口配置
for port in 8080 8081 8082; do
./run_test.sh "hexo-test:v0.0.3" "hexo-test-$port" $port $((port+1000))
./functional_test.sh "hexo-test-$port" $port $((port+1000))
./cleanup_test.sh "hexo-test-$port"
done
```
### 调试模式
```bash
# 启用详细输出
set -x
./start.sh
set +x
```
## 版本历史
### v0.0.3-linux-update (2025年5月30日)
- ✅ 修正了所有测试脚本的路径处理
- ✅ 统一了工作目录管理
- ✅ 更新了默认端口配置 (8888 → 8080)
- ✅ 添加了路径验证工具 `test_paths.sh`
- ✅ 改进了错误处理和日志记录
- ✅ 增强了脚本的可移植性和稳定性

View File

@@ -0,0 +1,118 @@
#!/bin/bash
# Hexo Container v0.0.3 构建测试脚本 (Linux)
# build_test.sh
# 确保脚本在正确的目录下执行
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# 参数设置
TAG=${1:-"hexo-test:v0.0.3"}
PLATFORM=${2:-"linux/amd64"}
echo "=== Hexo Container v0.0.3 构建测试 ==="
echo "镜像标签: $TAG"
echo "平台架构: $PLATFORM"
echo "工作目录: $SCRIPT_DIR"
# Dockerfile 路径 (相对于测试脚本目录)
DOCKERFILE_PATH="../../../Dockerfile_v0.0.3"
# 检查 Dockerfile 是否存在
if [ ! -f "$DOCKERFILE_PATH" ]; then
echo "❌ 错误: Dockerfile 不存在: $DOCKERFILE_PATH"
echo "完整路径: $(realpath "$DOCKERFILE_PATH" 2>/dev/null || echo "路径无法解析")"
exit 1
fi
# 创建日志目录 (在测试脚本目录下)
LOG_DIR="./logs"
mkdir -p "$LOG_DIR"
# 记录开始时间
START_TIME=$(LC_ALL=C date)
LOG_FILE="$LOG_DIR/build_$(date +%Y%m%d_%H%M%S).log"
echo "构建开始时间: $START_TIME"
echo "日志文件: $LOG_FILE"
# 执行构建
echo ""
echo "开始构建镜像..."
# 获取 Dockerfile 所在目录的绝对路径
DOCKERFILE_DIR="$(cd "$(dirname "$DOCKERFILE_PATH")" && pwd)"
DOCKERFILE_NAME=$(basename "$DOCKERFILE_PATH")
echo "Dockerfile 目录: $DOCKERFILE_DIR"
echo "Dockerfile 文件: $DOCKERFILE_NAME"
# 切换到 Dockerfile 所在目录进行构建
cd "$DOCKERFILE_DIR" || exit 1
BUILD_CMD="docker build -f $DOCKERFILE_NAME -t $TAG --platform $PLATFORM ."
echo "执行命令: $BUILD_CMD"
# 执行构建并记录日志
if $BUILD_CMD 2>&1 | tee "$SCRIPT_DIR/$LOG_FILE"; then
END_TIME=$(LC_ALL=C date)
# 计算构建时间
START_TIMESTAMP=$(date -d "$START_TIME" +%s)
END_TIMESTAMP=$(date -d "$END_TIME" +%s)
DURATION=$((END_TIMESTAMP - START_TIMESTAMP))
DURATION_MIN=$(echo "scale=2; $DURATION / 60" | bc 2>/dev/null || echo "$(($DURATION / 60))")
echo ""
echo "=== 构建成功 ==="
echo "构建结束时间: $END_TIME"
echo "构建耗时: ${DURATION_MIN} 分钟"
# 显示镜像信息
echo ""
echo "=== 镜像信息 ==="
docker images "$TAG"
# 显示镜像详细信息
echo ""
echo "=== 镜像详细信息 ==="
if command -v jq > /dev/null 2>&1; then
IMAGE_SIZE=$(docker inspect "$TAG" | jq -r '.[0].Size')
IMAGE_SIZE_MB=$(echo "scale=2; $IMAGE_SIZE / 1024 / 1024" | bc 2>/dev/null || echo "$(($IMAGE_SIZE / 1024 / 1024))")
IMAGE_CREATED=$(docker inspect "$TAG" | jq -r '.[0].Created')
IMAGE_ARCH=$(docker inspect "$TAG" | jq -r '.[0].Architecture')
echo "镜像大小: ${IMAGE_SIZE_MB} MB"
echo "创建时间: $IMAGE_CREATED"
echo "架构: $IMAGE_ARCH"
else
echo "镜像大小: $(docker inspect "$TAG" --format='{{.Size}}' | awk '{print int($1/1024/1024) " MB"}')"
echo "创建时间: $(docker inspect "$TAG" --format='{{.Created}}')"
echo "架构: $(docker inspect "$TAG" --format='{{.Architecture}}')"
fi
# 输出构建统计
echo ""
echo "=== 构建统计 ==="
LAYER_COUNT=$(grep -c "^Step [0-9]*/" "$SCRIPT_DIR/$LOG_FILE" 2>/dev/null || echo "未知")
echo "构建步骤数: $LAYER_COUNT"
cd "$SCRIPT_DIR"
exit 0
else
echo ""
echo "=== 构建失败 ==="
echo "详细日志请查看: $LOG_FILE"
# 显示最后几行日志
echo ""
echo "=== 最后10行构建日志 ==="
tail -10 "$SCRIPT_DIR/$LOG_FILE"
cd "$SCRIPT_DIR"
exit 1
fi
echo ""
echo "构建测试完成。"
echo "详细日志保存在: $LOG_FILE"

View File

@@ -0,0 +1,357 @@
#!/bin/bash
# Hexo Container v0.0.3 清理测试脚本 (Linux)
# cleanup_test.sh
# 确保脚本在正确的目录下执行
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# 参数设置
CONTAINER_NAME=${1:-"hexo-test-v003"}
IMAGE_TAG=${2:-"hexo-test:v0.0.3"}
REMOVE_IMAGE=${3:-false}
REMOVE_TEST_DATA=${4:-false}
KEEP_LOGS=${5:-true}
echo "=== Hexo Container v0.0.3 清理测试 ==="
echo "工作目录: $SCRIPT_DIR"
# 解析命令行参数
while [[ $# -gt 0 ]]; do
case $1 in
--remove-image)
REMOVE_IMAGE=true
shift
;;
--remove-test-data)
REMOVE_TEST_DATA=true
shift
;;
--remove-logs)
KEEP_LOGS=false
shift
;;
-h|--help)
echo "用法: $0 [选项]"
echo "选项:"
echo " --remove-image 删除测试镜像"
echo " --remove-test-data 删除测试数据"
echo " --remove-logs 删除测试日志"
echo " -h, --help 显示此帮助信息"
exit 0
;;
*)
shift
;;
esac
done
echo "=== Hexo Container v0.0.3 测试环境清理 ==="
CLEANUP_RESULTS=()
# 函数:记录清理结果
add_cleanup_result() {
local action="$1"
local status="$2"
local message="$3"
CLEANUP_RESULTS+=("$action:$status:$message:$(date)")
}
echo ""
echo "=== 步骤 1: 停止并删除容器 ==="
# 检查容器是否存在并运行
if docker ps -a --filter "name=$CONTAINER_NAME" --format "{{.Names}}" | grep -q "$CONTAINER_NAME"; then
echo "发现容器: $CONTAINER_NAME"
# 停止容器
echo "停止容器..."
if docker stop "$CONTAINER_NAME" 2>/dev/null; then
echo "✅ 容器已停止"
add_cleanup_result "停止容器" "SUCCESS" ""
else
echo "⚠️ 容器停止失败或容器已停止"
add_cleanup_result "停止容器" "WARNING" "容器可能已停止"
fi
# 删除容器
echo "删除容器..."
if docker rm "$CONTAINER_NAME" 2>/dev/null; then
echo "✅ 容器已删除"
add_cleanup_result "删除容器" "SUCCESS" ""
else
echo "❌ 容器删除失败"
add_cleanup_result "删除容器" "ERROR" "删除命令执行失败"
fi
else
echo "✅ 容器不存在,无需删除"
add_cleanup_result "删除容器" "SKIPPED" "容器不存在"
fi
echo ""
echo "=== 步骤 2: 清理 Docker 镜像 ==="
if [ "$REMOVE_IMAGE" = true ]; then
# 检查镜像是否存在
if docker images --filter "reference=$IMAGE_TAG" --format "{{.Repository}}:{{.Tag}}" | grep -q "$IMAGE_TAG"; then
echo "删除测试镜像: $IMAGE_TAG"
if docker rmi "$IMAGE_TAG" 2>/dev/null; then
echo "✅ 测试镜像已删除"
add_cleanup_result "删除测试镜像" "SUCCESS" ""
else
echo "❌ 测试镜像删除失败"
add_cleanup_result "删除测试镜像" "ERROR" "镜像可能被其他容器使用"
fi
else
echo "✅ 测试镜像不存在,无需删除"
add_cleanup_result "删除测试镜像" "SKIPPED" "镜像不存在"
fi
# 清理悬挂镜像
echo "清理悬挂镜像..."
if docker image prune -f >/dev/null 2>&1; then
echo "✅ 悬挂镜像已清理"
add_cleanup_result "清理悬挂镜像" "SUCCESS" ""
else
echo "⚠️ 清理悬挂镜像失败"
add_cleanup_result "清理悬挂镜像" "WARNING" "清理命令执行失败"
fi
else
echo "⏭️ 跳过镜像删除 (使用 --remove-image 参数强制删除)"
add_cleanup_result "删除测试镜像" "SKIPPED" "用户选择保留"
fi
echo ""
echo "=== 步骤 3: 清理测试数据 ==="
if [ "$REMOVE_TEST_DATA" = true ]; then
TEST_DATA_DIR="./test_data"
if [ -d "$TEST_DATA_DIR" ]; then
echo "删除测试数据目录: $TEST_DATA_DIR"
if rm -rf "$TEST_DATA_DIR"; then
echo "✅ 测试数据已删除"
add_cleanup_result "删除测试数据" "SUCCESS" ""
else
echo "❌ 删除测试数据失败"
add_cleanup_result "删除测试数据" "ERROR" "权限不足或目录被占用"
fi
else
echo "✅ 测试数据目录不存在"
add_cleanup_result "删除测试数据" "SKIPPED" "目录不存在"
fi
else
echo "⏭️ 保留测试数据 (使用 --remove-test-data 参数强制删除)"
add_cleanup_result "删除测试数据" "SKIPPED" "用户选择保留"
fi
echo ""
echo "=== 步骤 4: 清理测试日志 ==="
if [ "$KEEP_LOGS" = false ]; then
LOGS_DIR="./logs"
if [ -d "$LOGS_DIR" ]; then
echo "删除测试日志目录: $LOGS_DIR"
if rm -rf "$LOGS_DIR"; then
echo "✅ 测试日志已删除"
add_cleanup_result "删除测试日志" "SUCCESS" ""
else
echo "❌ 删除测试日志失败"
add_cleanup_result "删除测试日志" "ERROR" "权限不足或目录被占用"
fi
else
echo "✅ 测试日志目录不存在"
add_cleanup_result "删除测试日志" "SKIPPED" "目录不存在"
fi
else
echo "⏭️ 保留测试日志 (日志文件保存在 ./logs 目录)"
add_cleanup_result "删除测试日志" "SKIPPED" "用户选择保留"
# 显示保留的日志文件
LOGS_DIR="./logs"
if [ -d "$LOGS_DIR" ]; then
LOG_FILES=$(find "$LOGS_DIR" -type f -name "*.log" -o -name "*.txt" | sort -t_ -k2 -r)
if [ -n "$LOG_FILES" ]; then
echo ""
echo "保留的日志文件:"
echo "$LOG_FILES" | while read -r file; do
size=$(du -h "$file" | cut -f1)
modified=$(stat -c %y "$file" 2>/dev/null || date -r "$file" 2>/dev/null || echo "未知时间")
echo " $(basename "$file") ($size) - $modified"
done
fi
fi
fi
echo ""
echo "=== 步骤 5: 清理 Docker 系统资源 ==="
# 清理未使用的网络
echo "清理未使用的 Docker 网络..."
if docker network prune -f >/dev/null 2>&1; then
echo "✅ 未使用的网络已清理"
add_cleanup_result "清理网络" "SUCCESS" ""
else
echo "⚠️ 网络清理失败"
add_cleanup_result "清理网络" "WARNING" "清理命令执行失败"
fi
# 清理未使用的卷
echo "清理未使用的 Docker 卷..."
if docker volume prune -f >/dev/null 2>&1; then
echo "✅ 未使用的卷已清理"
add_cleanup_result "清理卷" "SUCCESS" ""
else
echo "⚠️ 卷清理失败"
add_cleanup_result "清理卷" "WARNING" "清理命令执行失败"
fi
echo ""
echo "=== 步骤 6: 验证清理结果 ==="
# 检查容器是否已完全删除
if ! docker ps -a --filter "name=$CONTAINER_NAME" --format "{{.Names}}" | grep -q "$CONTAINER_NAME"; then
echo "✅ 容器清理验证通过"
else
REMAINING=$(docker ps -a --filter "name=$CONTAINER_NAME" --format "{{.Names}}")
echo "❌ 仍有容器残留: $REMAINING"
fi
# 检查镜像清理情况
if [ "$REMOVE_IMAGE" = true ]; then
if ! docker images --filter "reference=$IMAGE_TAG" --format "{{.Repository}}:{{.Tag}}" | grep -q "$IMAGE_TAG"; then
echo "✅ 镜像清理验证通过"
else
REMAINING=$(docker images --filter "reference=$IMAGE_TAG" --format "{{.Repository}}:{{.Tag}}")
echo "❌ 仍有镜像残留: $REMAINING"
fi
fi
# 显示当前 Docker 资源使用情况
echo ""
echo "=== Docker 资源使用情况 ==="
echo "容器数量:"
CONTAINER_COUNT=$(docker ps -a --format "table {{.Names}}\t{{.Status}}" | wc -l)
if [ $CONTAINER_COUNT -gt 1 ]; then
docker ps -a --format "table {{.Names}}\t{{.Status}}" | head -10
echo " 总计: $((CONTAINER_COUNT - 1)) 个容器"
else
echo " 无容器运行"
fi
echo ""
echo "镜像数量:"
IMAGE_COUNT=$(docker images --format "{{.Repository}}" | wc -l)
echo " 总计: $IMAGE_COUNT 个镜像"
echo ""
echo "磁盘使用:"
if command -v docker >/dev/null 2>&1; then
docker system df 2>/dev/null || echo " 无法获取磁盘使用信息"
fi
# 生成清理报告
echo ""
echo "=== 清理报告 ==="
SUCCESS_COUNT=0
WARNING_COUNT=0
ERROR_COUNT=0
SKIPPED_COUNT=0
TOTAL_ACTIONS=0
for result in "${CLEANUP_RESULTS[@]}"; do
TOTAL_ACTIONS=$((TOTAL_ACTIONS + 1))
status=$(echo "$result" | cut -d: -f2)
case $status in
SUCCESS) SUCCESS_COUNT=$((SUCCESS_COUNT + 1)) ;;
WARNING) WARNING_COUNT=$((WARNING_COUNT + 1)) ;;
ERROR) ERROR_COUNT=$((ERROR_COUNT + 1)) ;;
SKIPPED) SKIPPED_COUNT=$((SKIPPED_COUNT + 1)) ;;
esac
done
echo "清理操作统计:"
echo " 成功: $SUCCESS_COUNT"
echo " 警告: $WARNING_COUNT"
echo " 错误: $ERROR_COUNT"
echo " 跳过: $SKIPPED_COUNT"
echo " 总计: $TOTAL_ACTIONS"
# 详细清理结果
echo ""
echo "详细清理结果:"
for result in "${CLEANUP_RESULTS[@]}"; do
IFS=':' read -r action status message timestamp <<< "$result"
case $status in
SUCCESS) color="✅" ;;
WARNING) color="⚠️" ;;
ERROR) color="❌" ;;
SKIPPED) color="⏭️" ;;
*) color="" ;;
esac
if [ -n "$message" ]; then
echo " $color $action: $status - $message"
else
echo " $color $action: $status"
fi
done
# 保存清理报告
if [ "$KEEP_LOGS" = true ] && [ -d "./logs" ]; then
REPORT_CONTENT="=== Hexo Container v0.0.3 测试环境清理报告 ===
清理时间: $(date)
容器名称: $CONTAINER_NAME
镜像标签: $IMAGE_TAG
=== 清理参数 ===
删除镜像: $REMOVE_IMAGE
删除测试数据: $REMOVE_TEST_DATA
保留日志: $KEEP_LOGS
=== 清理统计 ===
成功: $SUCCESS_COUNT
警告: $WARNING_COUNT
错误: $ERROR_COUNT
跳过: $SKIPPED_COUNT
总计: $TOTAL_ACTIONS
=== 详细结果 ==="
for result in "${CLEANUP_RESULTS[@]}"; do
IFS=':' read -r action status message timestamp <<< "$result"
REPORT_CONTENT="$REPORT_CONTENT
$timestamp - $action: $status $message"
done
REPORT_FILE="./logs/cleanup_report_$(date +%Y%m%d_%H%M%S).txt"
echo "$REPORT_CONTENT" > "$REPORT_FILE"
echo ""
echo "清理报告已保存: $REPORT_FILE"
fi
# 使用建议
echo ""
echo "=== 使用建议 ==="
echo "重新开始测试请运行:"
echo " ./build_test.sh # 重新构建镜像"
echo " ./run_test.sh # 重新运行容器"
echo " ./functional_test.sh # 执行功能测试"
echo ""
echo "完全清理 (包括镜像和数据) 请运行:"
echo " ./cleanup_test.sh --remove-image --remove-test-data"
echo ""
echo "=== 清理完成 ==="
# 根据清理结果设置退出代码
if [ $ERROR_COUNT -eq 0 ]; then
echo "🎉 清理操作成功完成!"
exit 0
else
echo "⚠️ 清理过程中出现错误,请检查详细报告。"
exit 1
fi

View File

@@ -0,0 +1,242 @@
#!/bin/bash
# Hexo Container v0.0.3 功能测试脚本 (Linux)
# functional_test.sh
# 确保脚本在正确的目录下执行
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# 参数设置
CONTAINER_NAME=${1:-"hexo-test-v003"}
HTTP_PORT=${2:-8080}
SSH_PORT=${3:-2222}
SSH_KEY_PATH="$SCRIPT_DIR/test_data/ssh_keys/test_key"
echo "=== Hexo Container v0.0.3 功能测试 ==="
echo "工作目录: $SCRIPT_DIR"
# 创建日志文件 (在测试脚本目录下)
LOG_DIR="./logs"
mkdir -p "$LOG_DIR"
TEST_LOG="$LOG_DIR/functional_test_$(date +%Y%m%d_%H%M%S).log"
TEST_RESULTS=()
# 测试函数
run_test() {
local test_name="$1"
local description="$2"
local test_command="$3"
echo ""
echo "=== $test_name ==="
echo "$description"
local start_time=$(date +%s)
local status
local message=""
if eval "$test_command"; then
local end_time=$(date +%s)
local duration=$((end_time - start_time))
echo "$test_name 通过 (${duration}s)"
status="PASS"
else
local end_time=$(date +%s)
local duration=$((end_time - start_time))
echo "$test_name 失败 (${duration}s)"
status="FAIL"
fi
TEST_RESULTS+=("$test_name:$status:$duration")
echo "$(date '+%Y-%m-%d %H:%M:%S') - $test_name - $status (${duration}s)" >> "$TEST_LOG"
}
# 检查容器是否运行
echo "检查容器状态..."
if ! docker ps --filter "name=$CONTAINER_NAME" --format "{{.Names}}" | grep -q "$CONTAINER_NAME"; then
echo "❌ 容器 $CONTAINER_NAME 未运行,请先运行 run_test.sh"
exit 1
fi
echo "✅ 容器正在运行"
# 测试 1: HTTP 服务基础测试
run_test "HTTP服务基础测试" "测试主页是否可以正常访问" \
"curl -f http://localhost:$HTTP_PORT --max-time 10 >/dev/null 2>&1"
# 测试 2: 健康检查端点测试
run_test "健康检查端点测试" "测试 /health 端点是否返回正确响应" \
"curl -f http://localhost:$HTTP_PORT/health --max-time 5 2>/dev/null | grep -q '^healthy$'"
# 测试 3: SSH 服务连接测试
run_test "SSH服务连接测试" "测试 SSH 服务是否可以正常连接" \
'if [ -f "$SSH_KEY_PATH" ]; then
docker exec "$CONTAINER_NAME" bash -c "mkdir -p /home/hexo/.ssh && cp /home/hexo/.ssh/test_key.pub /home/hexo/.ssh/authorized_keys && chown -R hexo:hexo /home/hexo/.ssh && chmod 600 /home/hexo/.ssh/authorized_keys" 2>/dev/null &&
ssh -p "$SSH_PORT" -i "$SSH_KEY_PATH" -o ConnectTimeout=10 -o StrictHostKeyChecking=no hexo@localhost "echo SSH连接成功" 2>/dev/null | grep -q "SSH连接成功"
else
echo "SSH 密钥不存在: $SSH_KEY_PATH" >&2
false
fi'
# 测试 4: Git 仓库初始化测试
run_test "Git仓库初始化测试" "检查 Git 裸仓库是否正确初始化" \
'docker exec "$CONTAINER_NAME" bash -c "test -d /home/hexo/hexo.git" 2>/dev/null'
# 测试 5: 部署钩子测试
run_test "部署钩子测试" "检查 Git post-receive 钩子是否正确配置" \
'docker exec "$CONTAINER_NAME" bash -c "test -f /home/hexo/hexo.git/hooks/post-receive && test -x /home/hexo/hexo.git/hooks/post-receive" 2>/dev/null'
# 测试 6: 文件权限测试
run_test "文件权限测试" "检查用户权限和目录访问权限" \
'docker exec "$CONTAINER_NAME" bash -c "su - hexo -s /bin/bash -c \"whoami && test -w /home/www/hexo\" 2>/dev/null | grep -q hexo"'
# 测试 7: 日志文件权限测试 (v0.0.3 新功能)
run_test "日志文件权限测试" "测试 hexo 用户对部署日志文件的写入权限 (v0.0.3 新功能)" \
'docker exec "$CONTAINER_NAME" bash -c "if [ ! -f /var/log/container/deployment.log ]; then touch /var/log/container/deployment.log && chown hexo:hexo /var/log/container/deployment.log; fi && ls -la /var/log/container/ | grep deployment.log | awk '\''{print \$3}'\'' | grep -q hexo && su - hexo -s /bin/bash -c '\''echo 测试写入 >> /var/log/container/deployment.log && echo 写入成功'\'' 2>/dev/null | grep -q \"写入成功\""'
# 测试 8: 模拟 Git 部署测试
run_test "模拟Git部署测试" "模拟 Git 推送部署并检查日志生成" \
'current_dir_before_git_ops_test8="$(pwd)";
TMP_REPO_PATH_TEST8="/tmp/test8_repo_$$";
rm -rf "$TMP_REPO_PATH_TEST8";
mkdir -p "$TMP_REPO_PATH_TEST8";
cd "$TMP_REPO_PATH_TEST8";
git init -q -b master;
git config user.email "test@example.com";
git config user.name "Test User";
echo "Test content for Test 8 on $(date)" > test_file.html;
git add test_file.html;
git commit -q -m "Commit for Test 8";
# Ensure authorized_keys is set up in the container for hexo user
docker exec "'"$CONTAINER_NAME"'" bash -c "mkdir -p /home/hexo/.ssh && echo '\''$(cat "'"$SSH_KEY_PATH.pub"'")'\'' > /home/hexo/.ssh/authorized_keys && chown -R hexo:hexo /home/hexo/.ssh && chmod 600 /home/hexo/.ssh/authorized_keys" >/dev/null 2>&1;
# Perform the git push
GIT_SSH_COMMAND="ssh -p '"$SSH_PORT"' -i '\''"'"$SSH_KEY_PATH"'"'\'' -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" git push -q ssh://hexo@localhost/home/hexo/hexo.git master -f;
PUSH_EC=$?;
if [ $PUSH_EC -eq 0 ]; then
echo "Git push for Test 8 successful, waiting 3s for hook...";
sleep 3;
# Verify deployment log and deployed file content
docker exec "'"$CONTAINER_NAME"'" bash -c "grep -q '\''=== Git Push Deployment Started ==='\'' /var/log/container/deployment.log && grep -q '\''Files checked out successfully'\'' /var/log/container/deployment.log && test -f /home/www/hexo/test_file.html && grep -q '\''Test content for Test 8 on'\'' /home/www/hexo/test_file.html";
VERIFY_EC=$?;
cd "$current_dir_before_git_ops_test8";
rm -rf "$TMP_REPO_PATH_TEST8";
exit $VERIFY_EC;
else
echo "Git push failed in Test 8 (EC: $PUSH_EC)";
# For debugging, show verbose SSH output if push fails
GIT_SSH_COMMAND="ssh -vvv -p '"$SSH_PORT"' -i '\''"'"$SSH_KEY_PATH"'"'\'' -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" git push ssh://hexo@localhost/home/hexo/hexo.git master -f;
cd "$current_dir_before_git_ops_test8";
rm -rf "$TMP_REPO_PATH_TEST8";
exit 1;
fi'
# 测试 9: 日志轮转功能测试 (v0.0.3 新功能)
run_test "日志轮转功能测试" "检查日志轮转功能是否正确配置 (v0.0.3 新功能)" \
'docker exec "$CONTAINER_NAME" bash -c "grep -q \\\\"rotate_log\\\\" /root/start.sh && grep -q \\\\"check_and_rotate_logs\\\\" /root/start.sh" 2>/dev/null'
# 测试 10: 容器资源使用测试
run_test "容器资源使用测试" "检查容器的 CPU 和内存限制设置" \
'docker exec "'"$CONTAINER_NAME"'" bash -c "if [ -f /sys/fs/cgroup/cpu/cpu.cfs_quota_us ] && [ -f /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then cpu_quota=\\\\\$(cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us); memory_limit=\\\\\$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes); [ \\\\\\"\\\\\\\$cpu_quota\\\\\\" -ne 0 ] && [ \\\\\\"\\\\\\\$memory_limit\\\\\\" -ne 0 ]; else false; fi"'
# 生成测试报告
echo ""
echo "=== 测试总结报告 ==="
PASSED_TESTS=0
FAILED_TESTS=0
TOTAL_TESTS=0
for result in "${TEST_RESULTS[@]}"; do
TOTAL_TESTS=$((TOTAL_TESTS + 1))
if echo "$result" | grep -q ":PASS:"; then
PASSED_TESTS=$((PASSED_TESTS + 1))
else
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
done
SUCCESS_RATE=$(echo "scale=1; $PASSED_TESTS * 100 / $TOTAL_TESTS" | bc 2>/dev/null || echo "0.0")
echo "总测试数: $TOTAL_TESTS"
echo "通过: $PASSED_TESTS"
echo "失败: $FAILED_TESTS"
echo "成功率: $SUCCESS_RATE%"
# 详细测试结果表格
echo ""
echo "=== 详细测试结果 ==="
printf "%-25s %-8s %-10s\n" "测试名称" "状态" "耗时(s)"
printf "%-25s %-8s %-10s\n" "------------------------" "--------" "----------"
for result in "${TEST_RESULTS[@]}"; do
IFS=':' read -r test_name status duration <<< "$result"
printf "%-25s %-8s %-10s\n" "$test_name" "$status" "$duration"
done
# 失败的测试详情
FAILED_TESTS_LIST=()
for result in "${TEST_RESULTS[@]}"; do
if echo "$result" | grep -q ":FAIL:"; then
test_name=$(echo "$result" | cut -d: -f1)
FAILED_TESTS_LIST+=("$test_name")
fi
done
if [ ${#FAILED_TESTS_LIST[@]} -gt 0 ]; then
echo ""
echo "=== 失败的测试 ==="
for failed_test in "${FAILED_TESTS_LIST[@]}"; do
echo "$failed_test"
done
fi
# 保存详细报告到文件
REPORT_CONTENT="=== Hexo Container v0.0.3 功能测试报告 ===
测试时间: $(date)
容器名称: $CONTAINER_NAME
HTTP 端口: $HTTP_PORT
SSH 端口: $SSH_PORT
=== 测试统计 ===
总测试数: $TOTAL_TESTS
通过: $PASSED_TESTS
失败: $FAILED_TESTS
成功率: $SUCCESS_RATE%
=== 详细结果 ===
$(for result in "${TEST_RESULTS[@]}"; do
IFS=':' read -r test_name status duration <<< "$result"
echo "$test_name: $status (${duration}s)"
done)
=== v0.0.3 新功能测试状态 ==="
# 查找新功能测试状态
for result in "${TEST_RESULTS[@]}"; do
if echo "$result" | grep -q "日志文件权限测试"; then
status=$(echo "$result" | cut -d: -f2)
echo "日志文件权限测试: $status"
fi
if echo "$result" | grep -q "日志轮转功能测试"; then
status=$(echo "$result" | cut -d: -f2)
echo "日志轮转功能测试: $status"
fi
done
REPORT_FILE="$LOG_DIR/functional_test_report_$(date +%Y%m%d_%H%M%S).txt"
echo "$REPORT_CONTENT" > "$REPORT_FILE"
echo ""
echo "详细测试日志: $TEST_LOG"
echo "测试报告: $REPORT_FILE"
# 根据测试结果设置退出代码
if [ $FAILED_TESTS -eq 0 ]; then
echo ""
echo "🎉 所有测试通过!"
exit 0
else
echo ""
echo "⚠️ 部分测试失败,请检查详细日志。"
exit 1
fi

View File

@@ -0,0 +1,397 @@
#!/bin/bash
# Docker Hexo Static Blog v0.0.3 - Linux Log Rotation Test Script
# 用于测试 v0.0.3 版本的日志轮转功能
set -e
# 确保脚本在正确的目录下执行
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 配置参数
CONTAINER_NAME=${1:-"hexo-test-v003"}
IMAGE_NAME="hexo-test"
IMAGE_TAG="v0.0.3"
SSH_KEY_PATH="$SCRIPT_DIR/test_data/ssh_keys/test_key"
LOG_DIR="$SCRIPT_DIR/logs"
TEST_DIR="$SCRIPT_DIR/test_data/log_rotation"
LOG_FILE="$LOG_DIR/log_rotation_test_$(date +%Y%m%d_%H%M%S).log"
# 创建日志目录
mkdir -p "$LOG_DIR"
echo "=== Hexo Container v0.0.3 日志轮转测试 ==="
echo "工作目录: $SCRIPT_DIR"
# 函数:记录日志
log() {
echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$LOG_FILE"
}
log_success() {
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] ✓${NC} $1" | tee -a "$LOG_FILE"
}
log_error() {
echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ✗${NC} $1" | tee -a "$LOG_FILE"
}
log_warning() {
echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] ⚠${NC} $1" | tee -a "$LOG_FILE"
}
# 函数:清理资源
cleanup() {
log "清理测试资源..."
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm "$CONTAINER_NAME" 2>/dev/null || true
sudo rm -rf "$TEST_DIR" 2>/dev/null || true
log_success "清理完成"
}
# 函数:清理现有容器
cleanup_existing_container() {
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log "发现现有容器 $CONTAINER_NAME,正在清理..."
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm "$CONTAINER_NAME" 2>/dev/null || true
log "现有容器已清理"
fi
}
# 函数:检查前置条件
check_prerequisites() {
log "检查前置条件..."
# 检查 Docker
if ! command -v docker &> /dev/null; then
log_error "Docker 未安装或不在 PATH 中"
exit 1
fi
# 检查 Docker 服务
if ! docker info &> /dev/null; then
log_error "Docker 服务未运行"
exit 1
fi
# 检查镜像
if ! docker image inspect "${IMAGE_NAME}:${IMAGE_TAG}" &> /dev/null; then
log_error "Docker 镜像 ${IMAGE_NAME}:${IMAGE_TAG} 不存在"
log "请先运行 build_test.sh 构建镜像"
exit 1
fi
log_success "前置条件检查通过"
}
# 函数:准备测试环境
prepare_test_environment() {
log "准备测试环境..."
# 创建测试目录
mkdir -p "$TEST_DIR"
mkdir -p "$TEST_DIR/logs"
mkdir -p "$TEST_DIR/hexo-blog"
# 创建初始日志文件以便测试
echo "Initial log entry" > "$TEST_DIR/logs/container.log"
echo "Initial ssh log entry" > "$TEST_DIR/logs/ssh.log"
log_success "测试环境准备完成"
}
# 函数:启动容器
start_container() {
log "启动测试容器..."
# 清理可能存在的同名容器
cleanup_existing_container
docker run -d \
--name "$CONTAINER_NAME" \
-p 4000:4000 \
-p 2222:22 \
-e PUID=1000 \
-e PGID=1000 \
-e LOG_ROTATION_ENABLED=true \
-e LOG_MAX_SIZE=1M \
-e LOG_BACKUP_COUNT=5 \
-v "$TEST_DIR/hexo-blog:/app/hexo-blog" \
-v "$TEST_DIR/logs:/var/log/container" \
"${IMAGE_NAME}:${IMAGE_TAG}"
# 等待容器启动
log "等待容器完全启动..."
sleep 10
# 检查容器状态
if ! docker ps | grep -q "$CONTAINER_NAME"; then
log_error "容器启动失败"
docker logs "$CONTAINER_NAME"
exit 1
fi
log_success "容器启动成功"
}
# 函数:测试基本日志轮转功能
test_basic_log_rotation() {
log "测试基本日志轮转功能..."
# 生成大量日志以触发轮转
for i in {1..1000}; do
echo "Test log entry $i - $(date) - This is a test message to fill up the log file for rotation testing" >> "$TEST_DIR/logs/container.log"
if [ $((i % 100)) -eq 0 ]; then
log "已写入 $i 条日志记录..."
fi
done
# 检查日志文件大小
log_size=$(stat -f%z "$TEST_DIR/logs/container.log" 2>/dev/null || stat -c%s "$TEST_DIR/logs/container.log" 2>/dev/null)
log "当前日志文件大小: $log_size 字节"
# 触发手动轮转测试
docker exec "$CONTAINER_NAME" bash -c "
if [ -f /usr/local/bin/rotate_log ]; then
/usr/local/bin/rotate_log /var/log/container/container.log
else
echo 'rotate_log function not found'
fi
"
sleep 5
# 检查轮转后的文件
if [ -f "$TEST_DIR/logs/container.log.1" ]; then
log_success "基本日志轮转功能正常 - 找到备份文件"
else
log_warning "未找到备份文件,可能日志未达到轮转阈值"
fi
}
# 函数:测试定期日志轮转
test_periodic_log_rotation() {
log "测试定期日志轮转功能..."
# 检查容器中的日志轮转配置
docker exec "$CONTAINER_NAME" bash -c "
echo '=== 检查日志轮转配置 ==='
env | grep LOG_
echo
echo '=== 检查监控进程 ==='
ps aux | grep -E '(monitor|check.*log)' | grep -v grep
echo
echo '=== 检查日志目录 ==='
ls -la /var/log/container/
"
# 模拟长时间运行,观察定期轮转
log "模拟30分钟周期的定期检查..."
# 生成持续的日志流
docker exec -d "$CONTAINER_NAME" bash -c "
while true; do
echo '$(date): Continuous log entry for rotation testing' >> /var/log/container/container.log
sleep 1
done
"
# 等待一段时间观察轮转
log "等待60秒观察日志轮转行为..."
sleep 60
# 检查轮转结果
rotation_files=$(ls "$TEST_DIR/logs/"*.log.* 2>/dev/null | wc -l)
if [ "$rotation_files" -gt 0 ]; then
log_success "找到 $rotation_files 个轮转后的日志文件"
ls -la "$TEST_DIR/logs/"
else
log_warning "未检测到轮转文件,可能需要更长时间或更多日志"
fi
}
# 函数:测试日志权限
test_log_permissions() {
log "测试日志文件权限..."
# 检查容器内的日志文件权限
docker exec "$CONTAINER_NAME" bash -c "
echo '=== 日志目录权限 ==='
ls -la /var/log/container/
echo
echo '=== 检查 hexo 用户权限 ==='
su - hexo -c 'echo \"Test write permission\" >> /var/log/container/test_permission.log'
if [ \$? -eq 0 ]; then
echo 'hexo 用户可以写入日志目录'
else
echo 'hexo 用户无法写入日志目录'
fi
echo
echo '=== 检查日志文件所有权 ==='
stat /var/log/container/*.log 2>/dev/null | grep -E '(Uid|Gid)'
"
# 测试 Git Hook 日志写入
if docker exec "$CONTAINER_NAME" test -f "/app/hexo-blog/.git/hooks/post-receive"; then
log "测试 Git Hook 日志写入权限..."
docker exec "$CONTAINER_NAME" bash -c "
su - hexo -c 'echo \"Test deployment log\" >> /var/log/container/deployment.log'
if [ \$? -eq 0 ]; then
echo 'Git Hook 日志写入权限正常'
else
echo 'Git Hook 日志写入权限有问题'
fi
"
fi
log_success "日志权限测试完成"
}
# 函数:测试日志备份和清理
test_log_backup_cleanup() {
log "测试日志备份和清理功能..."
# 创建多个旧的备份文件进行清理测试
for i in {1..10}; do
echo "Old backup log $i" > "$TEST_DIR/logs/container.log.$i"
# 设置不同的时间戳
touch -t "$(date -d "-$i days" +%Y%m%d%H%M)" "$TEST_DIR/logs/container.log.$i" 2>/dev/null || \
touch -d "-$i days" "$TEST_DIR/logs/container.log.$i" 2>/dev/null
done
log "创建了10个模拟备份文件"
# 执行清理
docker exec "$CONTAINER_NAME" bash -c "
if [ -f /usr/local/bin/cleanup_old_logs ]; then
/usr/local/bin/cleanup_old_logs /var/log/container/
else
echo 'cleanup_old_logs function not found'
fi
"
sleep 5
# 检查清理结果
remaining_backups=$(ls "$TEST_DIR/logs/"*.log.* 2>/dev/null | wc -l)
log "清理后剩余备份文件数量: $remaining_backups"
if [ "$remaining_backups" -le 5 ]; then
log_success "日志清理功能正常 - 保留了合理数量的备份"
else
log_warning "日志清理可能未按预期工作"
fi
}
# 函数:生成测试报告
generate_test_report() {
log "生成日志轮转测试报告..."
local report_file="$TEST_DIR/log_rotation_test_report.txt"
cat > "$report_file" << EOF
Docker Hexo Static Blog v0.0.3 - 日志轮转测试报告
======================================================
测试时间: $(date)
测试环境: Linux ($(uname -r))
镜像版本: ${IMAGE_NAME}:${IMAGE_TAG}
测试结果概要:
EOF
# 检查各项测试结果
echo "1. 容器运行状态:" >> "$report_file"
if docker ps | grep -q "$CONTAINER_NAME"; then
echo " ✓ 容器正常运行" >> "$report_file"
else
echo " ✗ 容器未运行" >> "$report_file"
fi
echo "2. 日志文件检查:" >> "$report_file"
if [ -f "$TEST_DIR/logs/container.log" ]; then
log_size=$(stat -c%s "$TEST_DIR/logs/container.log" 2>/dev/null)
echo " ✓ 主日志文件存在 (大小: $log_size 字节)" >> "$report_file"
else
echo " ✗ 主日志文件不存在" >> "$report_file"
fi
echo "3. 日志轮转文件:" >> "$report_file"
rotation_count=$(ls "$TEST_DIR/logs/"*.log.* 2>/dev/null | wc -l)
if [ "$rotation_count" -gt 0 ]; then
echo " ✓ 找到 $rotation_count 个轮转文件" >> "$report_file"
ls -la "$TEST_DIR/logs/"*.log.* >> "$report_file" 2>/dev/null
else
echo " - 未找到轮转文件(可能正常,取决于日志大小)" >> "$report_file"
fi
echo "4. 容器资源使用:" >> "$report_file"
docker stats "$CONTAINER_NAME" --no-stream >> "$report_file" 2>/dev/null || echo " 无法获取资源使用情况" >> "$report_file"
echo "5. 容器日志最后20行:" >> "$report_file"
docker logs --tail 20 "$CONTAINER_NAME" >> "$report_file" 2>&1
log_success "测试报告已生成: $report_file"
cat "$report_file"
}
# 主测试流程
main() {
log "开始 Docker Hexo Static Blog v0.0.3 日志轮转测试"
log "=============================================="
# 设置错误处理
trap cleanup EXIT
# 执行测试步骤
check_prerequisites
prepare_test_environment
start_container
test_basic_log_rotation
test_periodic_log_rotation
test_log_permissions
test_log_backup_cleanup
generate_test_report
log_success "日志轮转测试完成!"
log "测试结果和日志保存在: $TEST_DIR"
}
# 脚本参数处理
case "${1:-}" in
--help|-h)
echo "Docker Hexo Static Blog v0.0.3 - Linux 日志轮转测试脚本"
echo ""
echo "用法: $0 [选项]"
echo ""
echo "选项:"
echo " --help, -h 显示此帮助信息"
echo " --cleanup 仅执行清理操作"
echo ""
echo "示例:"
echo " $0 # 运行完整的日志轮转测试"
echo " $0 --cleanup # 清理测试资源"
exit 0
;;
--cleanup)
cleanup
exit 0
;;
"")
main
;;
*)
log_error "未知参数: $1"
echo "使用 --help 查看使用说明"
exit 1
;;
esac

View File

@@ -0,0 +1,199 @@
#!/bin/bash
# Hexo Container v0.0.3 运行测试脚本 (Linux)
# run_test.sh
# 确保脚本在正确的目录下执行
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# 参数设置
TAG=${1:-"hexo-test:v0.0.3"}
CONTAINER_NAME=${2:-"hexo-test-v003"}
HTTP_PORT=${3:-8080}
SSH_PORT=${4:-2222}
PUID=${5:-1000}
PGID=${6:-1000}
TIMEZONE=${7:-"Asia/Shanghai"}
echo "=== Hexo Container v0.0.3 运行测试 ==="
echo "工作目录: $SCRIPT_DIR"
# 创建日志目录 (在测试脚本目录下)
LOG_DIR="./logs"
mkdir -p "$LOG_DIR"
# 创建测试数据目录 (在测试脚本目录下)
TEST_DATA_DIR="./test_data"
HEXO_SITE_DIR="$TEST_DATA_DIR/hexo_site"
SSH_KEYS_DIR="$TEST_DATA_DIR/ssh_keys"
echo "创建测试数据目录..."
mkdir -p "$HEXO_SITE_DIR"
mkdir -p "$SSH_KEYS_DIR"
# 创建测试用的 HTML 文件
echo "创建测试网站文件..."
cat > "$HEXO_SITE_DIR/index.html" << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>Hexo v0.0.3 Test Site</title>
<meta charset="utf-8">
<style>
body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
.container { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
h1 { color: #333; border-bottom: 2px solid #007acc; padding-bottom: 10px; }
.info { background: #e7f3ff; padding: 15px; border-radius: 4px; margin: 15px 0; }
.status { display: inline-block; padding: 4px 8px; border-radius: 3px; color: white; background: #28a745; }
ul { list-style-type: none; padding: 0; }
li { padding: 8px; margin: 5px 0; background: #f8f9fa; border-left: 4px solid #007acc; }
</style>
</head>
<body>
<div class="container">
<h1>Hexo Container v0.0.3 测试站点</h1>
<div class="info">
<p><strong>测试时间:</strong> <span id="time"></span></p>
<p><strong>版本:</strong> <span class="status">v0.0.3</span></p>
<p><strong>状态:</strong> <span class="status">运行中</span></p>
</div>
<h2>v0.0.3 新功能测试</h2>
<ul>
<li>定期日志轮转 (每30分钟检查)</li>
<li>Git Hook 日志权限修复</li>
<li>增强的部署日志管理</li>
<li>智能日志文件大小控制</li>
<li>自动旧日志清理</li>
<li>时间戳备份文件生成</li>
</ul>
<h2>测试链接</h2>
<ul>
<li><a href="/health">健康检查端点</a></li>
<li>SSH 连接: ssh -p 2222 hexo@localhost</li>
</ul>
</div>
<script>
document.getElementById('time').textContent = new Date().toLocaleString('zh-CN');
</script>
</body>
</html>
EOF
# 生成 SSH 密钥对 (如果不存在)
SSH_KEY_PATH="$SSH_KEYS_DIR/test_key"
if [ ! -f "$SSH_KEY_PATH" ]; then
echo "生成 SSH 密钥对..."
if ssh-keygen -t rsa -b 4096 -f "$SSH_KEY_PATH" -N "" -q; then
echo "[SUCCESS] SSH 密钥生成成功"
else
echo "[FAIL] SSH 密钥生成失败"
fi
fi
# 停止并删除已存在的容器
echo "清理旧容器..."
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm "$CONTAINER_NAME" 2>/dev/null || true
# 检查端口是否被占用
if netstat -tlnp 2>/dev/null | grep -q ":$HTTP_PORT "; then
echo "[WARNING] 警告: 端口 $HTTP_PORT 已被占用"
fi
if netstat -tlnp 2>/dev/null | grep -q ":$SSH_PORT "; then
echo "[WARNING] 警告: 端口 $SSH_PORT 已被占用"
fi
# 构建 Docker 运行命令
echo ""
echo "启动容器..."
DOCKER_CMD="docker run -d \
--name $CONTAINER_NAME \
-p $HTTP_PORT:80 \
-p $SSH_PORT:22 \
-e PUID=$PUID \
-e PGID=$PGID \
-e TZ=$TIMEZONE \
-e HTTP_PORT=80 \
-e SSH_PORT=22 \
-v $SCRIPT_DIR/test_data/hexo_site:/home/www/hexo \
-v $SCRIPT_DIR/test_data/ssh_keys:/home/hexo/.ssh \
-v $SCRIPT_DIR/logs:/var/log/container \
$TAG"
echo "执行命令:"
echo "$DOCKER_CMD"
# 执行 Docker 运行命令
if CONTAINER_ID=$($DOCKER_CMD); then
echo ""
echo "=== 容器启动成功 ==="
echo "容器 ID: $CONTAINER_ID"
echo "容器名称: $CONTAINER_NAME"
# 等待容器启动
echo ""
echo "等待容器完全启动 (增加等待时间)..."
sleep 30 # MODIFIED: Increased sleep time to 30 seconds
# 检查容器状态
echo ""
echo "=== 容器状态 ==="
docker ps --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# 显示访问信息
echo ""
echo "=== 访问信息 ==="
LOCAL_IP=$(hostname -I | awk '{print $1}')
echo "HTTP 访问地址: http://$LOCAL_IP:$HTTP_PORT"
echo "健康检查地址: http://$LOCAL_IP:$HTTP_PORT/health"
echo "SSH 连接命令: ssh -p $SSH_PORT -i test_data/ssh_keys/test_key hexo@$LOCAL_IP"
# 显示容器日志
echo ""
echo "=== 容器启动日志 (最后20行) ==="
docker logs "$CONTAINER_NAME" --tail 20
# 基础健康检查
echo ""
echo "=== 基础健康检查 ==="
sleep 5
# 健康检查
if curl -f "http://localhost:$HTTP_PORT/health" --max-time 10 >/dev/null 2>&1; then
echo "[SUCCESS] 健康检查通过"
else
echo "[FAIL] 健康检查失败"
fi
# HTTP 服务检查
if curl -f "http://localhost:$HTTP_PORT" --max-time 10 >/dev/null 2>&1; then
echo "[SUCCESS] HTTP 服务正常"
else
echo "[FAIL] HTTP 服务异常"
fi
echo ""
echo "=== 运行测试完成 ==="
echo "容器已成功启动并运行。使用以下命令进行进一步测试:"
echo " ./functional_test.sh # 功能测试"
echo " ./log_rotation_test.sh # 日志轮转测试"
echo " ./cleanup_test.sh # 清理测试环境"
exit 0
else
echo ""
echo "=== 容器启动失败 ==="
echo "[ERROR] Docker 容器启动失败"
# 尝试显示错误日志
if docker logs "$CONTAINER_NAME" 2>/dev/null; then
echo ""
echo "=== 容器错误日志 ==="
docker logs "$CONTAINER_NAME"
fi
exit 1
fi

556
test/v0.0.3/linux/start.sh Normal file
View File

@@ -0,0 +1,556 @@
#!/bin/bash
# Docker Hexo Static Blog v0.0.3 - Linux Complete Test Suite Startup Script
# 完整测试套件启动脚本
# set -e # Re-enabled for production use
# 颜色定义 (Corrected for echo -e and printf)
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 配置参数
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
DOCKERFILE_DIR="$(cd "$SCRIPT_DIR/../../../" && pwd)"
LOG_DIR="$SCRIPT_DIR/logs"
# SUITE_LOG is defined in main after mkdir -p LOG_DIR
# 测试脚本数组
TESTS=(
"build_test.sh:构建测试"
"run_test.sh:运行测试"
"functional_test.sh:功能测试"
"log_rotation_test.sh:日志轮转测试"
"cleanup_test.sh:清理测试"
)
# 函数:显示横幅
show_banner() {
echo -e "${CYAN}"
echo " ╔══════════════════════════════════════════════════════════════╗"
echo " ║ Docker Hexo Static Blog v0.0.3 ║"
echo " ║ 完整测试套件 (Linux) ║"
echo " ║ ║"
echo " ║ • 自动化构建和部署测试 ║"
echo " ║ • 功能完整性验证 ║"
echo " ║ • 日志轮转和权限测试 ║"
echo " ║ • 安全配置验证 ║"
echo " ║ • 性能监控 ║"
echo " ╚══════════════════════════════════════════════════════════════╝"
echo -e "${NC}"
}
# 函数:记录日志
log() {
echo -e "${BLUE}[$(LC_ALL=C date '+%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$SUITE_LOG"
local tee_status=${PIPESTATUS[1]}
if [ $tee_status -ne 0 ]; then
echo -e "${RED}CRITICAL: tee in log failed (status $tee_status) writing to $SUITE_LOG${NC}" >&2
fi
return 0
}
log_success() {
echo -e "${GREEN}[$(LC_ALL=C date '+%Y-%m-%d %H:%M:%S')] ✓${NC} $1" | tee -a "$SUITE_LOG"
local tee_status=${PIPESTATUS[1]}
if [ $tee_status -ne 0 ]; then
echo -e "${RED}CRITICAL: tee in log_success failed (status $tee_status) writing to $SUITE_LOG${NC}" >&2
fi
return 0
}
log_error() {
echo -e "${RED}[$(LC_ALL=C date '+%Y-%m-%d %H:%M:%S')] ✗${NC} $1" | tee -a "$SUITE_LOG"
local tee_status=${PIPESTATUS[1]}
if [ $tee_status -ne 0 ]; then
# Avoid using log_error here to prevent recursion if SUITE_LOG is the problem
echo -e "${RED}CRITICAL: tee in log_error failed (status $tee_status) writing to $SUITE_LOG${NC}" >&2
fi
return 0
}
log_warning() {
echo -e "${YELLOW}[$(LC_ALL=C date '+%Y-%m-%d %H:%M:%S')] ⚠${NC} $1" | tee -a "$SUITE_LOG"
local tee_status=${PIPESTATUS[1]}
if [ $tee_status -ne 0 ]; then
echo -e "${RED}CRITICAL: tee in log_warning failed (status $tee_status) writing to $SUITE_LOG${NC}" >&2
fi
return 0
}
log_step() {
echo -e "${CYAN}[$(LC_ALL=C date '+%Y-%m-%d %H:%M:%S')] ▶${NC} $1" | tee -a "$SUITE_LOG"
local tee_status=${PIPESTATUS[1]}
if [ $tee_status -ne 0 ]; then
echo -e "${RED}CRITICAL: tee in log_step failed (status $tee_status) writing to $SUITE_LOG${NC}" >&2
fi
return 0
}
# 函数:显示进度条
show_progress() {
local current=$1
local total=$2
local width=50
local percentage=$((current * 100 / total))
local filled=$((current * width / total))
local empty=$((width - filled))
printf "\r${CYAN}进度: [${NC}" # Corrected format string
printf "%*s" "$filled" | tr ' ' '=' # Corrected tr command and quoted variable
printf "%*s" "$empty" | tr ' ' ' ' # Corrected tr command and quoted variable
printf "${CYAN}] %d%% (%d/%d)${NC}" "$percentage" "$current" "$total" # Quoted variables
}
# 函数:检查前置条件
check_prerequisites() {
log_step "检查测试前置条件..."
local errors=0
# 检查 Docker
if ! command -v docker &> /dev/null; then
log_error "Docker 未安装或不在 PATH 中"
((errors++))
fi
# 检查 Docker 服务
if ! docker info &> /dev/null; then
log_error "Docker 服务未运行"
((errors++))
fi
# 检查 Dockerfile
if [ ! -f "$DOCKERFILE_DIR/Dockerfile_v0.0.3" ]; then
log_error "Dockerfile_v0.0.3 不存在于 $DOCKERFILE_DIR"
((errors++))
fi
# 检查测试脚本
for test_info in "${TESTS[@]}"; do
script_name="${test_info%%:*}"
if [ ! -f "$SCRIPT_DIR/$script_name" ]; then
log_error "测试脚本不存在: $script_name"
((errors++))
elif [ ! -x "$SCRIPT_DIR/$script_name" ]; then
log_warning "测试脚本没有执行权限: $script_name (将自动修复)"
chmod +x "$SCRIPT_DIR/$script_name"
fi
done
if [ $errors -gt 0 ]; then
log_error "发现 $errors 个前置条件问题,无法继续测试"
exit 1 # Exit if prerequisites fail
fi
log_success "前置条件检查通过"
}
# 函数:准备测试环境
prepare_test_environment() {
log_step "准备测试环境..."
# 创建日志目录 (already created in main, but ensure it)
mkdir -p "$LOG_DIR"
# 清理旧的测试资源(可选)
if [ "${CLEAN_START:-false}" = "true" ]; then
log "清理旧的测试资源..."
# Allow these commands to fail without exiting the script immediately
docker stop hexo-blog-test 2>/dev/null || true
docker rm hexo-blog-test 2>/dev/null || true
docker rmi hexo-test:v0.0.3 2>/dev/null || true # Ensure correct image name used elsewhere
fi
# 设置测试脚本权限
chmod +x "$SCRIPT_DIR"/*.sh
log_success "测试环境准备完成"
}
# 函数:运行单个测试
run_test() {
local test_info="$1"
local script_name="${test_info%%:*}"
local test_description="${test_info##*:}"
log_step "执行测试: $test_description ($script_name)"
local test_log="$LOG_DIR/${script_name%.sh}.log"
local start_time
start_time=$(LC_ALL=C date +%s)
# 执行测试脚本
# The actual script ($script_name) should handle its own set -e behavior.
# If it fails, its non-zero exit code will be caught here.
if LC_ALL=C bash "$SCRIPT_DIR/$script_name" > "$test_log" 2>&1; then
local end_time
end_time=$(LC_ALL=C date +%s)
local duration=$((end_time - start_time))
log_success "$test_description 测试通过 (耗时: ${duration}s)"
return 0 # Test script succeeded
else
local exit_code=$? # Capture exit code of the failing script
local end_time
end_time=$(LC_ALL=C date +%s)
local duration=$((end_time - start_time))
log_error "$test_description 测试失败 (退出码: $exit_code, 耗时: ${duration}s)"
log_error "详细日志: $test_log"
# 显示失败的最后几行
echo -e "${RED}错误详情 (最后10行):${NC}"
tail -10 "$test_log" | sed \'s/^/ /\' # Ensure sed doesn\'t cause issues
return 1 # Test script failed
fi
}
# 函数:运行所有测试
run_all_tests() {
log_step "开始执行完整测试套件..."
local total_tests=${#TESTS[@]}
local passed_tests=0
local failed_tests=0
local suite_start_time
suite_start_time=$(LC_ALL=C date +%s)
echo "" # Newline before progress
for i in "${!TESTS[@]}"; do
local current=$((i + 1))
show_progress $current $total_tests
echo "" # Newline after progress bar, before test execution logs
if run_test "${TESTS[$i]}"; then
((passed_tests++))
else
((failed_tests++))
if [ "${CONTINUE_ON_FAILURE:-true}" = "true" ]; then # Default to true
log_warning "测试失败,但继续执行剩余测试..."
else
log_error "测试失败,停止执行"
break # Exit loop
fi
fi
echo "" # Newline after test result
done
local suite_end_time
suite_end_time=$(LC_ALL=C date +%s)
local total_duration=$((suite_end_time - suite_start_time))
# Final progress update to 100% if all tests run
if [ $failed_tests -eq 0 ] || [ "${CONTINUE_ON_FAILURE:-true}" = "true" ]; then
show_progress $total_tests $total_tests
echo "" # Newline after final progress
fi
echo ""
log_step "测试套件执行完成"
log "总耗时: ${total_duration}s"
log "通过测试: $passed_tests/$total_tests"
log "失败测试: $failed_tests/$total_tests"
# 生成测试报告
generate_test_report $passed_tests $failed_tests $total_duration
if [ $failed_tests -eq 0 ]; then
log_success "所有测试都通过了!🎉"
return 0 # Overall success
else
log_error "$failed_tests 个测试失败"
return 1 # Overall failure
fi
}
# 函数:生成测试报告
generate_test_report() {
local passed=$1
local failed=$2
local duration=$3
local total=$((passed + failed))
local success_rate=0
if [ $total -gt 0 ]; then
success_rate=$(( passed * 100 / total ))
fi
local report_file="$LOG_DIR/test_suite_report.txt"
log_step "生成测试报告..."
# Use cat with explicit EOF marker
cat > "$report_file" <<-EOF
Docker Hexo Static Blog v0.0.3 - 完整测试套件报告 (Linux)
========================================================
测试时间: $(LC_ALL=C date)
测试环境: Linux ($(uname -r))
Docker 版本: $(docker --version)
测试位置: $SCRIPT_DIR
测试结果概要:
- 总测试数: $total
- 通过测试: $passed
- 失败测试: $failed
- 成功率: $success_rate%
- 总耗时: ${duration}s
详细测试结果:
EOF
for test_info in "${TESTS[@]}"; do
local script_name="${test_info%%:*}"
local test_description="${test_info##*:}"
local test_log_file="$LOG_DIR/${script_name%.sh}.log" # Renamed to avoid conflict
echo "- $test_description:" >> "$report_file"
if [ -f "$test_log_file" ]; then
# Check for success markers more robustly
# Assuming test scripts output specific success strings or exit 0
# For now, rely on the run_test logic that populates passed/failed counts
# This report section can be enhanced if tests output specific markers
if grep -q -E "SUCCESS|成功|✓|测试通过" "$test_log_file" 2>/dev/null || \
( [ -s "$test_log_file" ] && ! grep -q -E "FAIL|失败|✗|测试失败" "$test_log_file" 2>/dev/null && \
grep -q "构建成功" "$test_log_file" 2>/dev/null ) ; then # Example for build_test
echo " 状态: ✓ 通过" >> "$report_file"
elif grep -q -E "FAIL|失败|✗|测试失败" "$test_log_file" 2>/dev/null; then
echo " 状态: ✗ 失败" >> "$report_file"
else
# If log exists but no clear pass/fail, mark as indeterminate or check exit code if stored
echo " 状态: ? 结果未知 (检查日志)" >> "$report_file"
fi
echo " 日志: $test_log_file" >> "$report_file"
else
echo " 状态: ? 未执行或日志丢失" >> "$report_file"
fi
echo "" >> "$report_file"
done
# 添加系统信息
echo "系统信息:" >> "$report_file"
echo "- 操作系统: $(uname -s)" >> "$report_file"
echo "- 内核版本: $(uname -r)" >> "$report_file"
echo "- 架构: $(uname -m)" >> "$report_file"
# Ensure free and df commands don't fail due to locale
echo "- 可用内存: $(LC_ALL=C free -h | grep '^Mem:' | awk '{print $7}')" >> "$report_file"
echo "- 磁盘空间: $(LC_ALL=C df -h . | tail -1 | awk '{print $4}')" >> "$report_file"
log_success "测试报告已生成: $report_file"
}
# 函数:显示帮助信息
show_help() {
cat <<-EOF
Docker Hexo Static Blog v0.0.3 - Linux 完整测试套件
用法: $0 [选项]
选项:
--help, -h 显示此帮助信息
--clean-start 清理旧资源后开始测试 (设置 CLEAN_START=true)
--stop-on-failure 第一个测试失败时停止 (设置 CONTINUE_ON_FAILURE=false)
--list 列出所有可用的测试
--test <script_name> 只运行指定的测试脚本 (例如: build_test.sh)
--report-only 只生成报告,不运行测试 (需要现有日志)
环境变量:
CLEAN_START=true 等同于 --clean-start
CONTINUE_ON_FAILURE=false 等同于 --stop-on-failure
示例:
$0 # 运行完整测试套件
$0 --clean-start # 清理后运行测试
$0 --test build_test.sh # 只运行构建测试
测试脚本:
EOF
for test_info in "${TESTS[@]}"; do
local script_name="${test_info%%:*}"
local test_description="${test_info##*:}"
printf " %-25s %s\\n" "$script_name" "$test_description"
done
}
# 函数:列出测试
list_tests() {
echo "可用的测试脚本:"
echo ""
for i in "${!TESTS[@]}"; do
local test_info="${TESTS[$i]}"
local script_name="${test_info%%:*}"
local test_description="${test_info##*:}"
printf "%d. %-25s - %s\\n" $((i + 1)) "$script_name" "$test_description"
done
}
# 函数:运行单个指定测试
run_single_test() {
local target_script="$1"
# Find the test_info for the target_script
local found_test_info=""
for test_info_item in "${TESTS[@]}"; do
local script_name_item="${test_info_item%%:*}"
if [ "$script_name_item" = "$target_script" ]; then
found_test_info="$test_info_item"
break
fi
done
if [ -z "$found_test_info" ]; then
log_error "未找到测试脚本: $target_script"
echo "可用的测试脚本:"
list_tests # Call list_tests function
return 1
fi
# Prepare environment for single test run
# Note: SUITE_LOG might not be set if main() isn't fully run.
# For simplicity, single test runs will log to their own file and console.
# More robust single test logging would require initializing SUITE_LOG.
mkdir -p "$LOG_DIR" # Ensure log dir exists
export SUITE_LOG="$LOG_DIR/single_test_run_$(date +%Y%m%d_%H%M%S).log" # Temporary suite log for this run
echo "Running single test: $target_script. Main log: $SUITE_LOG" > "$SUITE_LOG"
log_step "运行单个测试: $target_script"
# check_prerequisites # Optional: run for single test
prepare_test_environment # Run prepare, it handles CLEAN_START
run_test "$found_test_info"
local test_exit_code=$?
if [ $test_exit_code -eq 0 ]; then
log_success "$target_script 测试通过"
else
log_error "$target_script 测试失败"
fi
return $test_exit_code
}
# 主函数
main() {
# Ensure LOG_DIR exists before SUITE_LOG is defined
mkdir -p "$LOG_DIR"
# Define SUITE_LOG here so all log functions can use it
# This was previously in the parameter parsing block for main call
export SUITE_LOG="$LOG_DIR/test_suite_$(LC_ALL=C date +%Y%m%d_%H%M%S).log"
show_banner
log "Docker Hexo Static Blog v0.0.3 完整测试套件启动"
log "================================================"
log "脚本位置: $SCRIPT_DIR"
log "Dockerfile 位置: $DOCKERFILE_DIR"
log "日志位置: $LOG_DIR (主套件日志: $SUITE_LOG)"
check_prerequisites
prepare_test_environment # Handles CLEAN_START logic
run_all_tests
# run_all_tests returns 0 for all pass, 1 for any failure
return $? # Propagate the exit status of run_all_tests
}
# --- Main script execution starts here ---
# Default behavior: continue on failure
export CONTINUE_ON_FAILURE="${CONTINUE_ON_FAILURE:-true}"
# Default behavior: don't clean start unless specified
export CLEAN_START="${CLEAN_START:-false}"
# Argument parsing
if [ $# -eq 0 ]; then
main
exit $? # Exit with main's status
fi
while [ $# -gt 0 ]; do
case "$1" in
--help|-h)
show_help
exit 0
;;
--list)
list_tests
exit 0
;;
--clean-start)
export CLEAN_START=true
# If it's the only arg, run main. If others follow, they'll be processed.
shift
if [ $# -eq 0 ]; then main; exit $?; fi
;;
--stop-on-failure)
export CONTINUE_ON_FAILURE=false
shift
if [ $# -eq 0 ]; then main; exit $?; fi
;;
--test)
if [ -z "$2" ]; then
# Temporarily set SUITE_LOG for this error message if not already set
export SUITE_LOG="${SUITE_LOG:-$LOG_DIR/error_$(date +%Y%m%d_%H%M%S).log}"
mkdir -p "$(dirname "$SUITE_LOG")"
log_error "请指定要运行的测试脚本名称 (例如: build_test.sh)"
show_help
exit 1
fi
run_single_test "$2"
exit $? # Exit with single test's status
;;
--report-only)
# Ensure SUITE_LOG is defined for logging within generate_test_report
export SUITE_LOG="${SUITE_LOG:-$LOG_DIR/report_only_$(date +%Y%m%d_%H%M%S).log}"
mkdir -p "$(dirname "$SUITE_LOG")"
if [ -d "$LOG_DIR" ] && [ "$(find "$LOG_DIR" -name \'*.log\' -print -quit)" ]; then
# Dummy values for passed/failed/duration as we are only generating report from existing logs
generate_test_report 0 0 0
exit $?
else
log_error "没有找到测试日志目录 $LOG_DIR 或日志文件以生成报告。"
exit 1
fi
;;
*)
# If main hasn't run yet due to options, run it now.
# This handles the case where options like --clean-start are given,
# and then the script is expected to run the full suite.
if ! ps -p $$ -o comm= | grep -q "start.sh"; then # Basic check if main was already invoked
main
exit $?
else
# If options were processed and we still have an unknown one, it's an error.
export SUITE_LOG="${SUITE_LOG:-$LOG_DIR/error_$(date +%Y%m%d_%H%M%S).log}"
mkdir -p "$(dirname "$SUITE_LOG")"
log_error "未知参数: $1"
show_help
exit 1
fi
;;
esac
# shift # Shift only if argument was consumed and not an exit/main call
done
# If loop finishes and main hasn't been called (e.g. only options like --clean-start were set)
# This logic might be complex depending on desired option interactions.
# A common pattern is to set flags and have one call to main() at the end.
# The current structure calls main or exits within the case statement for most paths.
# If we reach here, it implies options were processed that set flags, and now main should run.
if [ "${#BASH_SOURCE[@]}" -eq 1 ] && [ -z "${_MAIN_CALLED_VIA_OPTIONS:-}" ]; then
# Check if main was called by an option that then shifted out all args
# This is a fallback if options like --clean-start are given,
# and the parameter parsing was modified to call main if --clean-start is the only arg.
# So this path might not be strictly needed anymore.
: # Do nothing, main should have been called or script exited.
fi
# Final exit status should be from main or specific option handlers.
# Bash scripts exit with the status of the last command if not specified.
# The explicit `exit $?` after main calls ensures this.

View File

@@ -0,0 +1,88 @@
#!/bin/bash
# Docker Hexo Static Blog v0.0.3 - Linux Complete Test Suite Startup Script (Simplified)
# 完整测试套件启动脚本 (简化版)
# 配置参数
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
DOCKERFILE_DIR="$(cd "$SCRIPT_DIR/../../../" && pwd)"
LOG_DIR="$SCRIPT_DIR/logs"
# 测试脚本数组
TESTS=(
"build_test.sh"
"run_test.sh"
"functional_test.sh"
"log_rotation_test.sh"
"cleanup_test.sh"
)
# 创建日志目录
mkdir -p "$LOG_DIR"
SUITE_LOG="$LOG_DIR/test_suite_$(date +%Y%m%d_%H%M%S).log"
echo "=== Docker Hexo Static Blog v0.0.3 - Linux 完整测试套件 ===" | tee "$SUITE_LOG"
echo "开始时间: $(date)" | tee -a "$SUITE_LOG"
echo "脚本位置: $SCRIPT_DIR" | tee -a "$SUITE_LOG"
echo "Dockerfile 位置: $DOCKERFILE_DIR" | tee -a "$SUITE_LOG"
echo "日志位置: $LOG_DIR" | tee -a "$SUITE_LOG"
echo "" | tee -a "$SUITE_LOG"
# 清理旧资源(如果指定)
if [ "${1:-}" = "--clean-start" ]; then
echo "清理旧的测试资源..." | tee -a "$SUITE_LOG"
docker stop hexo-test-v003 2>/dev/null || true
docker rm hexo-test-v003 2>/dev/null || true
docker rmi hexo-test:v0.0.3 2>/dev/null || true
fi
# 设置测试脚本权限
chmod +x "$SCRIPT_DIR"/*.sh
# 运行测试
passed_tests=0
failed_tests=0
total_tests=${#TESTS[@]}
for i in "${!TESTS[@]}"; do
current=$((i + 1))
script_name="${TESTS[$i]}"
echo "[$current/$total_tests] 运行测试: $script_name" | tee -a "$SUITE_LOG"
test_log="$LOG_DIR/${script_name%.sh}_$(date +%Y%m%d_%H%M%S).log"
# 运行测试脚本
if bash "$SCRIPT_DIR/$script_name" > "$test_log" 2>&1; then
echo "$script_name 测试通过" | tee -a "$SUITE_LOG"
((passed_tests++))
else
echo "$script_name 测试失败" | tee -a "$SUITE_LOG"
echo " 详细日志: $test_log" | tee -a "$SUITE_LOG"
echo " 最后10行错误:" | tee -a "$SUITE_LOG"
tail -10 "$test_log" | sed 's/^/ /' | tee -a "$SUITE_LOG"
((failed_tests++))
# 默认继续执行其他测试
if [ "${CONTINUE_ON_FAILURE:-true}" != "true" ]; then
echo "测试失败,停止执行" | tee -a "$SUITE_LOG"
break
fi
fi
echo "" | tee -a "$SUITE_LOG"
done
# 生成最终报告
echo "=== 测试套件执行完成 ===" | tee -a "$SUITE_LOG"
echo "结束时间: $(date)" | tee -a "$SUITE_LOG"
echo "通过测试: $passed_tests/$total_tests" | tee -a "$SUITE_LOG"
echo "失败测试: $failed_tests/$total_tests" | tee -a "$SUITE_LOG"
if [ $failed_tests -eq 0 ]; then
echo "🎉 所有测试都通过了!" | tee -a "$SUITE_LOG"
exit 0
else
echo "❌ 有 $failed_tests 个测试失败" | tee -a "$SUITE_LOG"
exit 1
fi

View File

@@ -0,0 +1,277 @@
#!/bin/bash
# Hexo Container v0.0.3 路径验证脚本 (Linux)
# test_paths.sh - 验证测试环境的路径配置
# 确保脚本在正确的目录下执行
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
echo -e "${CYAN}=== Hexo Container v0.0.3 路径验证工具 (Linux) ===${NC}"
echo -e "${BLUE}工作目录: $SCRIPT_DIR${NC}"
echo ""
# 验证结果数组
declare -a RESULTS=()
# 验证函数
check_path() {
local description="$1"
local path="$2"
local should_exist="$3" # true/false
local create_if_missing="$4" # true/false
echo -n "检查 $description... "
if [ "$should_exist" = "true" ]; then
if [ -e "$path" ]; then
echo -e "${GREEN}✓ 存在${NC}"
RESULTS+=("PASS: $description")
return 0
else
if [ "$create_if_missing" = "true" ]; then
mkdir -p "$path" 2>/dev/null
if [ -d "$path" ]; then
echo -e "${YELLOW}✓ 已创建${NC}"
RESULTS+=("CREATED: $description")
return 0
else
echo -e "${RED}✗ 创建失败${NC}"
RESULTS+=("FAIL: $description - 创建失败")
return 1
fi
else
echo -e "${RED}✗ 不存在${NC}"
RESULTS+=("FAIL: $description - 路径不存在: $path")
return 1
fi
fi
else
if [ -e "$path" ]; then
echo -e "${YELLOW}! 存在 (不应该存在)${NC}"
RESULTS+=("WARN: $description - 意外存在")
return 0
else
echo -e "${GREEN}✓ 不存在 (正确)${NC}"
RESULTS+=("PASS: $description")
return 0
fi
fi
}
echo -e "${YELLOW}=== 关键路径验证 ===${NC}"
# 1. 验证 Dockerfile
check_path "Dockerfile_v0.0.3" "../../../Dockerfile_v0.0.3" true false
# 2. 验证和创建测试目录结构
echo ""
echo -e "${YELLOW}=== 测试目录结构验证 ===${NC}"
check_path "日志目录" "./logs" false true
check_path "测试数据目录" "./test_data" false true
check_path "Hexo 站点目录" "./test_data/hexo_site" false true
check_path "SSH 密钥目录" "./test_data/ssh_keys" false true
# 3. 验证测试脚本
echo ""
echo -e "${YELLOW}=== 测试脚本验证 ===${NC}"
SCRIPTS=(
"start.sh"
"build_test.sh"
"run_test.sh"
"functional_test.sh"
"log_rotation_test.sh"
"cleanup_test.sh"
)
for script in "${SCRIPTS[@]}"; do
check_path "测试脚本: $script" "./$script" true false
if [ -f "./$script" ]; then
if [ -x "./$script" ]; then
echo -e " ${GREEN}✓ 可执行权限${NC}"
else
echo -e " ${YELLOW}! 设置可执行权限${NC}"
chmod +x "./$script"
fi
fi
done
# 4. 验证系统依赖
echo ""
echo -e "${YELLOW}=== 系统依赖验证 ===${NC}"
COMMANDS=(
"docker:Docker"
"curl:HTTP 客户端"
"ssh:SSH 客户端"
"ssh-keygen:SSH 密钥生成"
)
for cmd_info in "${COMMANDS[@]}"; do
cmd=$(echo "$cmd_info" | cut -d':' -f1)
desc=$(echo "$cmd_info" | cut -d':' -f2)
echo -n "检查 $desc ($cmd)... "
if command -v "$cmd" > /dev/null 2>&1; then
version=$(${cmd} --version 2>&1 | head -n1 || echo "版本未知")
echo -e "${GREEN}✓ 可用${NC} ($version)"
RESULTS+=("PASS: $desc")
else
echo -e "${RED}✗ 未找到${NC}"
RESULTS+=("FAIL: $desc - 命令未找到")
fi
done
# 5. 验证网络端口
echo ""
echo -e "${YELLOW}=== 网络端口验证 ===${NC}"
DEFAULT_PORTS=(8080 2222)
for port in "${DEFAULT_PORTS[@]}"; do
echo -n "检查端口 $port... "
if netstat -tlnp 2>/dev/null | grep -q ":$port "; then
echo -e "${YELLOW}! 已被占用${NC}"
RESULTS+=("WARN: 端口 $port 已被占用")
else
echo -e "${GREEN}✓ 可用${NC}"
RESULTS+=("PASS: 端口 $port")
fi
done
# 6. 创建基本测试文件
echo ""
echo -e "${YELLOW}=== 创建基本测试文件 ===${NC}"
# 创建测试网站首页
TEST_INDEX="./test_data/hexo_site/index.html"
if [ ! -f "$TEST_INDEX" ]; then
echo -n "创建测试网站首页... "
cat > "$TEST_INDEX" << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>Hexo v0.0.3 Test Site - Linux</title>
<meta charset="utf-8">
<style>
body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
.container { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
h1 { color: #333; border-bottom: 2px solid #007acc; padding-bottom: 10px; }
.info { background: #e7f3ff; padding: 15px; border-radius: 4px; margin: 15px 0; }
.status { display: inline-block; padding: 4px 8px; border-radius: 3px; color: white; background: #28a745; }
</style>
</head>
<body>
<div class="container">
<h1>Hexo Container v0.0.3 测试站点 (Linux)</h1>
<div class="info">
<p><span class="status">运行中</span> 测试环境已就绪</p>
<p><strong>平台:</strong> Linux</p>
<p><strong>版本:</strong> v0.0.3</p>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
console.log('Hexo v0.0.3 测试页面加载完成');
});
</script>
</body>
</html>
EOF
echo -e "${GREEN}✓ 完成${NC}"
RESULTS+=("CREATED: 测试网站首页")
else
echo -e "测试网站首页... ${GREEN}✓ 已存在${NC}"
RESULTS+=("PASS: 测试网站首页")
fi
# 生成 SSH 密钥对
SSH_KEY_PATH="./test_data/ssh_keys/test_key"
if [ ! -f "$SSH_KEY_PATH" ]; then
echo -n "生成 SSH 密钥对... "
if ssh-keygen -t rsa -b 4096 -f "$SSH_KEY_PATH" -N "" -q 2>/dev/null; then
echo -e "${GREEN}✓ 完成${NC}"
RESULTS+=("CREATED: SSH 密钥对")
else
echo -e "${RED}✗ 失败${NC}"
RESULTS+=("FAIL: SSH 密钥对生成失败")
fi
else
echo -e "SSH 密钥对... ${GREEN}✓ 已存在${NC}"
RESULTS+=("PASS: SSH 密钥对")
fi
# 显示结果汇总
echo ""
echo -e "${CYAN}=== 验证结果汇总 ===${NC}"
PASS_COUNT=0
FAIL_COUNT=0
WARN_COUNT=0
CREATED_COUNT=0
for result in "${RESULTS[@]}"; do
case "$result" in
PASS:*)
echo -e "${GREEN}${NC} ${result#PASS: }"
((PASS_COUNT++))
;;
FAIL:*)
echo -e "${RED}${NC} ${result#FAIL: }"
((FAIL_COUNT++))
;;
WARN:*)
echo -e "${YELLOW}!${NC} ${result#WARN: }"
((WARN_COUNT++))
;;
CREATED:*)
echo -e "${BLUE}+${NC} ${result#CREATED: }"
((CREATED_COUNT++))
;;
esac
done
echo ""
echo -e "${CYAN}=== 统计信息 ===${NC}"
echo -e "通过: ${GREEN}$PASS_COUNT${NC}"
echo -e "创建: ${BLUE}$CREATED_COUNT${NC}"
echo -e "警告: ${YELLOW}$WARN_COUNT${NC}"
echo -e "失败: ${RED}$FAIL_COUNT${NC}"
# 提供建议
echo ""
echo -e "${CYAN}=== 建议 ===${NC}"
if [ $FAIL_COUNT -gt 0 ]; then
echo -e "${RED}存在失败项,请检查并修复后再运行测试。${NC}"
echo ""
echo "常见解决方案:"
echo "1. 安装 Docker: sudo apt-get install docker.io"
echo "2. 安装 curl: sudo apt-get install curl"
echo "3. 安装 ssh: sudo apt-get install openssh-client"
echo "4. 设置脚本权限: chmod +x *.sh"
exit 1
elif [ $WARN_COUNT -gt 0 ]; then
echo -e "${YELLOW}存在警告项,建议检查但不影响测试运行。${NC}"
echo ""
echo "如果端口被占用,可以在运行测试时指定其他端口。"
exit 0
else
echo -e "${GREEN}所有检查都通过了!测试环境已就绪。${NC}"
echo ""
echo "你现在可以运行:"
echo " ./start.sh # 完整测试套件"
echo " ./build_test.sh # 仅构建测试"
echo " ./run_test.sh # 仅运行测试"
echo " ./functional_test.sh # 仅功能测试"
exit 0
fi