Add Docker-based skills batch installer with multiple execution strategies
Includes PowerShell scripts for batch execution with different patterns: - Basic parallel execution (run-docker-batch.ps1) - Scheduled execution with delays (run-docker-batch-scheduled.ps1) - Wave-based execution with progressive concurrency (run-docker-waves.ps1) Each script supports anti-bot testing by generating unique client identities (device ID, UUID, user agent) for each container instance.
This commit is contained in:
46
skills-batch-installer/Dockerfile
Normal file
46
skills-batch-installer/Dockerfile
Normal file
@@ -0,0 +1,46 @@
|
||||
# Use Node.js 18+ as base image
|
||||
FROM node:18-alpine
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Install required tools
|
||||
RUN apk add --no-cache \
|
||||
git \
|
||||
curl \
|
||||
openssl \
|
||||
bash \
|
||||
bc \
|
||||
jq \
|
||||
wget \
|
||||
ca-certificates
|
||||
|
||||
# Copy scripts
|
||||
COPY install-skills-quick.sh /app/
|
||||
COPY http-load-test.sh /app/
|
||||
|
||||
# Make scripts executable
|
||||
RUN chmod +x /app/install-skills-quick.sh /app/http-load-test.sh
|
||||
|
||||
# Create logs directory
|
||||
RUN mkdir -p /app/logs
|
||||
|
||||
# Accept environment variables for anti-bot testing (different client identities)
|
||||
ENV DEVICE_ID=""
|
||||
ENV CLIENT_UUID=""
|
||||
ENV USER_AGENT=""
|
||||
ENV TARGET_URL=""
|
||||
ENV REQUEST_METHOD="GET"
|
||||
ENV TOTAL_REQUESTS="10"
|
||||
ENV CONCURRENT_REQUESTS="2"
|
||||
ENV REQUEST_DELAY_MIN="0.5"
|
||||
ENV REQUEST_DELAY_MAX="2"
|
||||
ENV TEST_TYPE="skills"
|
||||
|
||||
# Run the appropriate script based on TEST_TYPE
|
||||
CMD ["sh", "-c", "if [ \"$TEST_TYPE\" = \"http\" ]; then \
|
||||
/bin/bash /app/http-load-test.sh; \
|
||||
else \
|
||||
DEVICE_ID=$DEVICE_ID CLIENT_UUID=$CLIENT_UUID USER_AGENT=$USER_AGENT /bin/bash /app/install-skills-quick.sh; \
|
||||
fi && cat /app/logs/*.log 2>/dev/null | tail -100"]
|
||||
|
||||
190
skills-batch-installer/README.md
Normal file
190
skills-batch-installer/README.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# Docker 批量执行脚本
|
||||
|
||||
这个文件夹包含三个 PowerShell 脚本,用于 Docker 容器的批量执行和分布式反爬虫负载测试。
|
||||
|
||||
## 脚本概览
|
||||
|
||||
### 1. run-docker-batch.ps1 - 基础批量执行
|
||||
|
||||
最简单的批量执行脚本,同时运行指定数量的 Docker 容器。
|
||||
|
||||
**特性:**
|
||||
- 指定并发数量(同时运行多少个容器)
|
||||
- 指定总运行次数
|
||||
- 每个容器获得唯一的客户端身份信息
|
||||
- 实时进度显示
|
||||
|
||||
**参数:**
|
||||
```powershell
|
||||
-Total <int> # 总运行次数,默认值:20
|
||||
-Concurrency <int> # 并发数量,默认值:4
|
||||
-Image <string> # Docker 镜像名称,默认值:"skills-installer"
|
||||
```
|
||||
|
||||
**使用示例:**
|
||||
```powershell
|
||||
# 运行 20 次,4 个并发
|
||||
.\run-docker-batch.ps1
|
||||
|
||||
# 运行 50 次,8 个并发,使用自定义镜像
|
||||
.\run-docker-batch.ps1 -Total 50 -Concurrency 8 -Image "my-image"
|
||||
|
||||
# 快速测试:运行 2 次,1 个并发
|
||||
.\run-docker-batch.ps1 -Total 2 -Concurrency 1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. run-docker-batch-scheduled.ps1 - 批次执行(带延迟)
|
||||
|
||||
在基础批量执行的基础上增加了批次间延迟功能,模拟真实用户访问模式。
|
||||
|
||||
**特性:**
|
||||
- 基础的并发执行
|
||||
- 完成一批任务后,等待随机秒数
|
||||
- 可配置的延迟时间范围
|
||||
- 可选的随机化延迟
|
||||
- 完整的统计数据(成功率、执行时间)
|
||||
|
||||
**参数:**
|
||||
```powershell
|
||||
-Total <int> # 总运行次数,默认值:20
|
||||
-Concurrency <int> # 并发数量,默认值:4
|
||||
-MinDelaySeconds <int> # 最小延迟秒数,默认值:1
|
||||
-MaxDelaySeconds <int> # 最大延迟秒数,默认值:30
|
||||
-Image <string> # Docker 镜像名称,默认值:"skills-installer"
|
||||
-Randomize <bool> # 是否随机化延迟,默认值:$true
|
||||
```
|
||||
|
||||
**使用示例:**
|
||||
```powershell
|
||||
# 使用默认参数
|
||||
.\run-docker-batch-scheduled.ps1
|
||||
|
||||
# 100 次运行,4 个并发,5-15 秒延迟
|
||||
.\run-docker-batch-scheduled.ps1 -Total 100 -Concurrency 4 -MinDelaySeconds 5 -MaxDelaySeconds 15
|
||||
|
||||
# 不随机化延迟,固定为 10 秒间隔
|
||||
.\run-docker-batch-scheduled.ps1 -Total 50 -Concurrency 5 -MinDelaySeconds 10 -MaxDelaySeconds 10 -Randomize $false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. run-docker-waves.ps1 - 波次执行(动态并发)
|
||||
|
||||
最高级的脚本,分批处理任务,逐波增加并发数量,模拟渐进式的负载增加。
|
||||
|
||||
**特性:**
|
||||
- 波次执行:分批完成任务
|
||||
- 动态并发:每个波次增加并发数
|
||||
- 从低到高的并发扩展
|
||||
- 波次间的随机延迟
|
||||
- 详细的性能统计数据
|
||||
|
||||
**参数:**
|
||||
```powershell
|
||||
-TotalRuns <int> # 总运行次数,默认值:100
|
||||
-InitialConcurrency <int> # 初始并发数,默认值:2
|
||||
-MaxConcurrency <int> # 最大并发数,默认值:8
|
||||
-MinWaveDelaySeconds <int> # 波次间最小延迟,默认值:5
|
||||
-MaxWaveDelaySeconds <int> # 波次间最大延迟,默认值:60
|
||||
-Image <string> # Docker 镜像名称,默认值:"skills-installer"
|
||||
```
|
||||
|
||||
**使用示例:**
|
||||
```powershell
|
||||
# 使用默认参数
|
||||
.\run-docker-waves.ps1
|
||||
|
||||
# 200 次运行,初始 2 并发,最大 10 并发
|
||||
.\run-docker-waves.ps1 -TotalRuns 200 -InitialConcurrency 2 -MaxConcurrency 10
|
||||
|
||||
# 快速测试:30 次运行,初始 1 并发,最大 3 并发,短延迟
|
||||
.\run-docker-waves.ps1 -TotalRuns 30 -InitialConcurrency 1 -MaxConcurrency 3 -MinWaveDelaySeconds 1 -MaxWaveDelaySeconds 5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 使用场景
|
||||
|
||||
| 场景 | 推荐脚本 | 原因 |
|
||||
|------|---------|------|
|
||||
| 简单的并发测试 | `run-docker-batch.ps1` | 最轻量级,无延迟 |
|
||||
| 模拟真实用户访问 | `run-docker-batch-scheduled.ps1` | 批次间有停顿,更真实 |
|
||||
| 压力测试(渐进式负载) | `run-docker-waves.ps1` | 逐波增加压力,观察系统应对 |
|
||||
| 反爬虫绕过测试 | 任何脚本 | 所有脚本都生成唯一的客户端身份 |
|
||||
|
||||
## 运行前的准备
|
||||
|
||||
1. **安装 PowerShell**:需要 PowerShell 5.1 或更高版本
|
||||
2. **安装 Docker**:需要已安装 Docker 并能正常运行
|
||||
3. **准备镜像**:确保指定的 Docker 镜像已存在
|
||||
```powershell
|
||||
docker images # 查看已有镜像
|
||||
```
|
||||
|
||||
## 执行权限
|
||||
|
||||
如果脚本无法执行,可能需要调整执行策略:
|
||||
|
||||
```powershell
|
||||
# 仅对当前进程生效
|
||||
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
|
||||
|
||||
# 对当前用户生效
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
```
|
||||
|
||||
## 客户端身份信息
|
||||
|
||||
每个容器运行时会接收以下环境变量,用于模拟不同的客户端:
|
||||
|
||||
- `DEVICE_ID`:唯一的设备标识符(GUID)
|
||||
- `CLIENT_UUID`:唯一的客户端标识符(GUID)
|
||||
- `USER_AGENT`:随机分配的浏览器标识符
|
||||
|
||||
这些信息有助于绕过反爬虫检测。
|
||||
|
||||
## 输出说明
|
||||
|
||||
### 颜色编码
|
||||
- 🟢 **绿色**:成功、完成状态
|
||||
- 🔵 **青色**:部分标题、分隔符
|
||||
- 🟡 **黄色**:进度、配置信息、警告
|
||||
- 🔴 **红色**:失败、错误
|
||||
- 🟣 **紫色**:波次标记(仅 wave 脚本)
|
||||
|
||||
### 统计数据
|
||||
|
||||
脚本完成后会显示:
|
||||
- 总运行次数
|
||||
- 成功/失败的运行数
|
||||
- 成功率百分比
|
||||
- 总执行时间
|
||||
- 平均每次执行时间
|
||||
|
||||
## 故障排除
|
||||
|
||||
| 问题 | 解决方案 |
|
||||
|------|---------|
|
||||
| "找不到 Docker 命令" | 确保 Docker 已安装且在 PATH 中 |
|
||||
| 容器启动失败 | 检查镜像名称是否正确:`docker images` |
|
||||
| 权限被拒绝 | 使用管理员权限运行 PowerShell |
|
||||
| 脚本无法执行 | 调整执行策略(见上面的执行权限部分) |
|
||||
|
||||
## 快速开始
|
||||
|
||||
```powershell
|
||||
# 进入脚本目录
|
||||
cd scripts
|
||||
|
||||
# 测试运行(2 次,1 并发)
|
||||
.\run-docker-batch.ps1 -Total 2 -Concurrency 1 -Image "your-image-name"
|
||||
|
||||
# 实际运行
|
||||
.\run-docker-batch-scheduled.ps1 -Total 50 -Concurrency 4 -Image "your-image-name"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**更多信息**:查看根目录的 `AGENTS.md` 了解代码风格和开发指南。
|
||||
111
skills-batch-installer/install-skills-quick.ps1
Normal file
111
skills-batch-installer/install-skills-quick.ps1
Normal file
@@ -0,0 +1,111 @@
|
||||
# PowerShell script: Install skills with configurable interval in random temp directory
|
||||
|
||||
# Configuration
|
||||
$skillRepo = "https://github.com/fadinglight9291117/arkts_skills"
|
||||
$skills = @("harmonyos-build-deploy", "arkts-development")
|
||||
$intervalSeconds = 10 # 0 means execute immediately, otherwise wait (in seconds)
|
||||
$maxRuns = 1
|
||||
|
||||
Write-Host "================================================================" -ForegroundColor Cyan
|
||||
Write-Host "Skills Auto Installation Script (Temp Directory)" -ForegroundColor Green
|
||||
Write-Host "================================================================" -ForegroundColor Cyan
|
||||
Write-Host "Repository: $skillRepo" -ForegroundColor Yellow
|
||||
Write-Host "Skills: $($skills -join ', ')" -ForegroundColor Yellow
|
||||
if ($intervalSeconds -eq 0) {
|
||||
Write-Host "Interval: Immediate (no wait)" -ForegroundColor Yellow
|
||||
} else {
|
||||
Write-Host "Interval: $intervalSeconds seconds" -ForegroundColor Yellow
|
||||
}
|
||||
Write-Host "Max Runs: $maxRuns" -ForegroundColor Yellow
|
||||
Write-Host "Execution: In random temp directory, deleted after completion" -ForegroundColor Yellow
|
||||
Write-Host "================================================================`n" -ForegroundColor Cyan
|
||||
|
||||
# Counter
|
||||
$runCount = 0
|
||||
|
||||
# Loop
|
||||
while ($true) {
|
||||
$runCount++
|
||||
|
||||
# Check if max runs reached
|
||||
if ($maxRuns -and $runCount -gt $maxRuns) {
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
Write-Host "[$timestamp] Completed $maxRuns runs. Script exits." -ForegroundColor Cyan
|
||||
break
|
||||
}
|
||||
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
Write-Host "[$timestamp] [Run $runCount/$maxRuns] Starting skill installation..." -ForegroundColor Green
|
||||
|
||||
try {
|
||||
# Create random temp directory
|
||||
$randomId = [System.Guid]::NewGuid().ToString().Substring(0, 8)
|
||||
$tempDir = Join-Path -Path $env:TEMP -ChildPath "skills_test_$randomId"
|
||||
|
||||
Write-Host " -> Creating temp directory: $tempDir" -ForegroundColor Cyan
|
||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||
|
||||
# Change to temp directory
|
||||
Push-Location $tempDir
|
||||
Write-Host " OK Switched to temp directory" -ForegroundColor Green
|
||||
|
||||
# Install first skill
|
||||
Write-Host " -> Installing: harmonyos-build-deploy" -ForegroundColor Cyan
|
||||
& npx skills add $skillRepo --skill "harmonyos-build-deploy" --yes 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host " OK harmonyos-build-deploy installed" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " ERROR harmonyos-build-deploy failed" -ForegroundColor Red
|
||||
}
|
||||
|
||||
# Install second skill
|
||||
Write-Host " -> Installing: arkts-development" -ForegroundColor Cyan
|
||||
& npx skills add $skillRepo --skill "arkts-development" --yes 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host " OK arkts-development installed" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " ERROR arkts-development failed" -ForegroundColor Red
|
||||
}
|
||||
|
||||
# Remove skills
|
||||
Write-Host " -> Removing skills" -ForegroundColor Cyan
|
||||
foreach ($skill in $skills) {
|
||||
& npx skills remove $skill --yes 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -eq 0 -or $LASTEXITCODE -eq 1) {
|
||||
Write-Host " OK $skill removed" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " ERROR $skill removal failed" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
# Return to original directory
|
||||
Pop-Location
|
||||
Write-Host " -> Returned to original directory" -ForegroundColor Cyan
|
||||
|
||||
# Delete temp directory
|
||||
Write-Host " -> Deleting temp directory: $tempDir" -ForegroundColor Cyan
|
||||
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
if (-not (Test-Path $tempDir)) {
|
||||
Write-Host " OK Temp directory deleted" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " WARNING Temp directory still exists" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
Write-Host "[$timestamp] Run $runCount/$maxRuns completed`n" -ForegroundColor Green
|
||||
|
||||
} catch {
|
||||
Write-Host " ERROR: $_" -ForegroundColor Red
|
||||
# Ensure we return to original directory even if error occurs
|
||||
Pop-Location -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
# Wait for interval before next run (except on last run)
|
||||
if ($runCount -lt $maxRuns -and $intervalSeconds -gt 0) {
|
||||
Write-Host "Waiting $intervalSeconds seconds before next run..." -ForegroundColor Yellow
|
||||
Start-Sleep -Seconds $intervalSeconds
|
||||
}
|
||||
}
|
||||
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
Write-Host "`n[$timestamp] All tasks completed!" -ForegroundColor Green
|
||||
177
skills-batch-installer/run-docker-batch-scheduled.ps1
Normal file
177
skills-batch-installer/run-docker-batch-scheduled.ps1
Normal file
@@ -0,0 +1,177 @@
|
||||
param(
|
||||
[int]$Total = 20,
|
||||
[int]$Concurrency = 4,
|
||||
[int]$MinDelaySeconds = 1,
|
||||
[int]$MaxDelaySeconds = 30,
|
||||
[string]$Image = "skills-installer",
|
||||
[bool]$Randomize = $true
|
||||
)
|
||||
|
||||
if ($Total -lt 1) {
|
||||
Write-Error "Total must be >= 1"
|
||||
exit 1
|
||||
}
|
||||
if ($Concurrency -lt 1) {
|
||||
Write-Error "Concurrency must be >= 1"
|
||||
exit 1
|
||||
}
|
||||
if ($MinDelaySeconds -lt 0 -or $MaxDelaySeconds -lt 0) {
|
||||
Write-Error "Delay values must be >= 0"
|
||||
exit 1
|
||||
}
|
||||
if ($MinDelaySeconds -gt $MaxDelaySeconds) {
|
||||
Write-Error "MinDelaySeconds must be <= MaxDelaySeconds"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host "Distributed Anti-Bot Load Testing" -ForegroundColor Green
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host "Total Runs: $Total" -ForegroundColor Yellow
|
||||
Write-Host "Concurrency: $Concurrency" -ForegroundColor Yellow
|
||||
Write-Host "Delay Range: $MinDelaySeconds-$MaxDelaySeconds seconds" -ForegroundColor Yellow
|
||||
Write-Host "Randomization: $Randomize" -ForegroundColor Yellow
|
||||
Write-Host "Image: $Image" -ForegroundColor Yellow
|
||||
Write-Host "Start Time: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Yellow
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
$started = 0
|
||||
$completed = 0
|
||||
[System.Collections.ArrayList]$jobs = @()
|
||||
[System.Collections.ArrayList]$completedRuns = @()
|
||||
|
||||
function Start-RunJob {
|
||||
param([int]$Index, [string]$ImageName)
|
||||
|
||||
# Generate unique client identifiers for this run
|
||||
$deviceId = [System.Guid]::NewGuid().ToString()
|
||||
$clientUuid = [System.Guid]::NewGuid().ToString()
|
||||
$userAgents = @(
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15",
|
||||
"Mozilla/5.0 (Android 11; SM-G991B) AppleWebKit/537.36",
|
||||
"Mozilla/5.0 (iPad; CPU OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15"
|
||||
)
|
||||
$userAgent = $userAgents[$Index % $userAgents.Count]
|
||||
|
||||
Start-Job -Name "run-$Index" -ScriptBlock {
|
||||
param($i, $img, $devId, $clUuid, $ua)
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
Write-Host "[$timestamp] Run $i launched [Device: $($devId.Substring(0,8))... UUID: $($clUuid.Substring(0,8))...]" -ForegroundColor Green
|
||||
|
||||
# Run container with different client identities
|
||||
& docker run --rm `
|
||||
-e "DEVICE_ID=$devId" `
|
||||
-e "CLIENT_UUID=$clUuid" `
|
||||
-e "USER_AGENT=$ua" `
|
||||
$img 2>&1 | Out-Null
|
||||
|
||||
$exitCode = $LASTEXITCODE
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
if ($exitCode -eq 0) {
|
||||
Write-Host "[$timestamp] Run $i completed successfully" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[$timestamp] Run $i failed (exit code: $exitCode)" -ForegroundColor Red
|
||||
}
|
||||
return @{
|
||||
Index = $i
|
||||
ExitCode = $exitCode
|
||||
Timestamp = $timestamp
|
||||
DeviceId = $devId
|
||||
}
|
||||
} -ArgumentList $Index, $ImageName, $deviceId, $clientUuid, $userAgent
|
||||
}
|
||||
|
||||
function Get-RandomDelay {
|
||||
param([int]$Min, [int]$Max)
|
||||
if ($Min -eq 0 -and $Max -eq 0) {
|
||||
return 0
|
||||
}
|
||||
$random = Get-Random -Minimum $Min -Maximum ($Max + 1)
|
||||
return $random
|
||||
}
|
||||
|
||||
$batchCount = 0
|
||||
$startTime = Get-Date
|
||||
|
||||
while ($completed -lt $Total) {
|
||||
# Start new jobs if we have capacity
|
||||
while ($started -lt $Total -and $jobs.Count -lt $Concurrency) {
|
||||
$started++
|
||||
$job = Start-RunJob -Index $started -ImageName $Image
|
||||
$jobs.Add($job) | Out-Null
|
||||
}
|
||||
|
||||
# Wait for at least one job to complete
|
||||
if ($jobs.Count -gt 0) {
|
||||
$done = Wait-Job -Job $jobs[0]
|
||||
$result = Receive-Job -Job $done
|
||||
Remove-Job -Job $done
|
||||
$jobs.RemoveAt(0)
|
||||
$completed++
|
||||
|
||||
$completedRuns.Add($result) | Out-Null
|
||||
Write-Host "Progress: $completed/$Total completed" -ForegroundColor Yellow
|
||||
|
||||
# If more runs remain and we need to introduce delay
|
||||
if ($completed -lt $Total -and $completed % $Concurrency -eq 0) {
|
||||
if ($Randomize) {
|
||||
$delaySeconds = Get-RandomDelay -Min $MinDelaySeconds -Max $MaxDelaySeconds
|
||||
} else {
|
||||
$delaySeconds = $MinDelaySeconds
|
||||
}
|
||||
|
||||
if ($delaySeconds -gt 0) {
|
||||
$batchCount++
|
||||
$nextBatchTime = (Get-Date).AddSeconds($delaySeconds)
|
||||
Write-Host ""
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host "Batch $batchCount completed. Waiting $delaySeconds seconds..." -ForegroundColor Yellow
|
||||
Write-Host "Next batch will start at: $($nextBatchTime.ToString('HH:mm:ss'))" -ForegroundColor Yellow
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
Start-Sleep -Seconds $delaySeconds
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Wait for any remaining jobs
|
||||
while ($jobs.Count -gt 0) {
|
||||
$done = Wait-Job -Job $jobs[0]
|
||||
$result = Receive-Job -Job $done
|
||||
Remove-Job -Job $done
|
||||
$jobs.RemoveAt(0)
|
||||
$completed++
|
||||
}
|
||||
|
||||
$endTime = Get-Date
|
||||
$totalDuration = $endTime - $startTime
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host "Test Complete!" -ForegroundColor Green
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host "Total Runs: $Total" -ForegroundColor Yellow
|
||||
Write-Host "Batches: $batchCount" -ForegroundColor Yellow
|
||||
Write-Host "Start Time: $($startTime.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Yellow
|
||||
Write-Host "End Time: $($endTime.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Yellow
|
||||
$totalSeconds = [math]::Round($totalDuration.TotalSeconds, 2)
|
||||
Write-Host "Total Duration: $totalSeconds seconds" -ForegroundColor Yellow
|
||||
Write-Host "Average Time per Run: $([math]::Round($totalDuration.TotalSeconds / $Total, 2)) seconds" -ForegroundColor Yellow
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# Summary statistics
|
||||
$successCount = ($completedRuns | Where-Object { $_.ExitCode -eq 0 }).Count
|
||||
$failureCount = ($completedRuns | Where-Object { $_.ExitCode -ne 0 }).Count
|
||||
$successPercent = [math]::Round($successCount / $Total * 100, 2)
|
||||
|
||||
Write-Host "Success Rate: $successCount/$Total ($successPercent%)" -ForegroundColor Green
|
||||
if ($failureCount -gt 0) {
|
||||
Write-Host "Failures: $failureCount" -ForegroundColor Red
|
||||
}
|
||||
79
skills-batch-installer/run-docker-batch.ps1
Normal file
79
skills-batch-installer/run-docker-batch.ps1
Normal file
@@ -0,0 +1,79 @@
|
||||
param(
|
||||
[int]$Total = 20,
|
||||
[int]$Concurrency = 4,
|
||||
[string]$Image = "skills-installer"
|
||||
)
|
||||
|
||||
if ($Total -lt 1) {
|
||||
Write-Error "Total must be >= 1"
|
||||
exit 1
|
||||
}
|
||||
if ($Concurrency -lt 1) {
|
||||
Write-Error "Concurrency must be >= 1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "Starting $Total runs with concurrency $Concurrency" -ForegroundColor Cyan
|
||||
Write-Host "Image: $Image" -ForegroundColor Cyan
|
||||
Write-Host "Each container will use a different client identity for anti-bot testing" -ForegroundColor Yellow
|
||||
|
||||
$started = 0
|
||||
$completed = 0
|
||||
[System.Collections.ArrayList]$jobs = @()
|
||||
|
||||
function Start-RunJob {
|
||||
param([int]$Index, [string]$ImageName)
|
||||
|
||||
# Generate unique client identifiers for this run
|
||||
$deviceId = [System.Guid]::NewGuid().ToString()
|
||||
$clientUuid = [System.Guid]::NewGuid().ToString()
|
||||
$userAgents = @(
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15",
|
||||
"Mozilla/5.0 (Android 11; SM-G991B) AppleWebKit/537.36"
|
||||
)
|
||||
$userAgent = $userAgents[$Index % $userAgents.Count]
|
||||
|
||||
Start-Job -Name "run-$Index" -ScriptBlock {
|
||||
param($i, $img, $devId, $clUuid, $ua)
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
Write-Host "[$timestamp] Run $i start [Device: $($devId.Substring(0,8))... UUID: $($clUuid.Substring(0,8))...]" -ForegroundColor Green
|
||||
|
||||
# Run container with different client identities
|
||||
& docker run --rm `
|
||||
-e "DEVICE_ID=$devId" `
|
||||
-e "CLIENT_UUID=$clUuid" `
|
||||
-e "USER_AGENT=$ua" `
|
||||
$img 2>&1
|
||||
|
||||
$exitCode = $LASTEXITCODE
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
if ($exitCode -eq 0) {
|
||||
Write-Host "[$timestamp] Run $i success" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[$timestamp] Run $i failed (exit $exitCode)" -ForegroundColor Red
|
||||
}
|
||||
return $exitCode
|
||||
} -ArgumentList $Index, $ImageName, $deviceId, $clientUuid, $userAgent
|
||||
}
|
||||
|
||||
while ($completed -lt $Total) {
|
||||
while ($started -lt $Total -and $jobs.Count -lt $Concurrency) {
|
||||
$started++
|
||||
$job = Start-RunJob -Index $started -ImageName $Image
|
||||
$jobs.Add($job) | Out-Null
|
||||
}
|
||||
|
||||
if ($jobs.Count -gt 0) {
|
||||
$done = Wait-Job -Job $jobs[0]
|
||||
Receive-Job -Job $done | Out-Host
|
||||
Remove-Job -Job $done
|
||||
$jobs.RemoveAt(0)
|
||||
$completed++
|
||||
Write-Host "Progress: $completed/$Total completed" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "All runs completed with different client identities." -ForegroundColor Green
|
||||
133
skills-batch-installer/run-docker-waves.ps1
Normal file
133
skills-batch-installer/run-docker-waves.ps1
Normal file
@@ -0,0 +1,133 @@
|
||||
param(
|
||||
[int]$TotalRuns = 100,
|
||||
[int]$InitialConcurrency = 2,
|
||||
[int]$MaxConcurrency = 8,
|
||||
[int]$MinWaveDelaySeconds = 5,
|
||||
[int]$MaxWaveDelaySeconds = 60,
|
||||
[string]$Image = "skills-installer"
|
||||
)
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Wave-Based Distributed Anti-Bot Load Testing" -ForegroundColor Cyan
|
||||
Write-Host "==============================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "Configuration:" -ForegroundColor Yellow
|
||||
Write-Host " Total Runs: $TotalRuns" -ForegroundColor Yellow
|
||||
Write-Host " Initial Concurrency: $InitialConcurrency" -ForegroundColor Yellow
|
||||
Write-Host " Max Concurrency: $MaxConcurrency" -ForegroundColor Yellow
|
||||
Write-Host " Wave Delay Range: $MinWaveDelaySeconds-$MaxWaveDelaySeconds seconds" -ForegroundColor Yellow
|
||||
Write-Host " Docker Image: $Image" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
$startTime = Get-Date
|
||||
$completed = 0
|
||||
$waveNumber = 0
|
||||
[System.Collections.ArrayList]$allRuns = @()
|
||||
|
||||
function Start-RunJob {
|
||||
param([int]$Index, [string]$ImageName)
|
||||
|
||||
$deviceId = [System.Guid]::NewGuid().ToString()
|
||||
$clientUuid = [System.Guid]::NewGuid().ToString()
|
||||
$userAgents = @(
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
|
||||
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36',
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15',
|
||||
'Mozilla/5.0 (Android 11; SM-G991B) AppleWebKit/537.36'
|
||||
)
|
||||
$userAgent = $userAgents[$Index % $userAgents.Count]
|
||||
|
||||
Start-Job -Name "run-$Index" -ScriptBlock {
|
||||
param($i, $img, $devId, $clUuid, $ua)
|
||||
$runStartTime = Get-Date
|
||||
& docker run --rm `
|
||||
-e "DEVICE_ID=$devId" `
|
||||
-e "CLIENT_UUID=$clUuid" `
|
||||
-e "USER_AGENT=$ua" `
|
||||
$img 2>&1 | Out-Null
|
||||
|
||||
return @{
|
||||
Index = $i
|
||||
ExitCode = $LASTEXITCODE
|
||||
Duration = ((Get-Date) - $runStartTime).TotalSeconds
|
||||
DeviceId = $devId
|
||||
}
|
||||
} -ArgumentList $Index, $ImageName, $deviceId, $clientUuid, $userAgent
|
||||
}
|
||||
|
||||
[System.Collections.ArrayList]$jobs = @()
|
||||
$started = 0
|
||||
|
||||
while ($completed -lt $TotalRuns) {
|
||||
$waveNumber++
|
||||
|
||||
$currentConcurrency = [Math]::Min($InitialConcurrency + ($waveNumber - 1), $MaxConcurrency)
|
||||
$waveSize = [Math]::Min($currentConcurrency, $TotalRuns - $started)
|
||||
|
||||
Write-Host "[WAVE $waveNumber] Starting $waveSize concurrent runs" -ForegroundColor Magenta
|
||||
|
||||
$waveStartTime = Get-Date
|
||||
|
||||
for ($i = 0; $i -lt $waveSize; $i++) {
|
||||
if ($started -lt $TotalRuns) {
|
||||
$started++
|
||||
$job = Start-RunJob -Index $started -ImageName $Image
|
||||
$jobs.Add($job) | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
while ($jobs.Count -gt 0) {
|
||||
$done = Wait-Job -Job $jobs[0]
|
||||
$result = Receive-Job -Job $done
|
||||
Remove-Job -Job $done
|
||||
$jobs.RemoveAt(0)
|
||||
$completed++
|
||||
|
||||
$allRuns.Add($result) | Out-Null
|
||||
|
||||
$timestamp = Get-Date -Format "HH:mm:ss"
|
||||
Write-Host " [$timestamp] Run $($result.Index) done (Duration: $([Math]::Round($result.Duration, 2))s) | Progress: $completed/$TotalRuns" -ForegroundColor Green
|
||||
}
|
||||
|
||||
$waveEndTime = Get-Date
|
||||
$waveDuration = $waveEndTime - $waveStartTime
|
||||
|
||||
Write-Host "[WAVE $waveNumber COMPLETE] Duration: $([Math]::Round($waveDuration.TotalSeconds, 2))s" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
if ($completed -lt $TotalRuns) {
|
||||
$nextWaveDelay = Get-Random -Minimum $MinWaveDelaySeconds -Maximum ($MaxWaveDelaySeconds + 1)
|
||||
$nextWaveTime = (Get-Date).AddSeconds($nextWaveDelay)
|
||||
|
||||
Write-Host "[DELAY] Waiting $nextWaveDelay seconds before Wave $($waveNumber + 1)..." -ForegroundColor Yellow
|
||||
Write-Host " Next wave starts at: $($nextWaveTime.ToString('HH:mm:ss'))" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
Start-Sleep -Seconds $nextWaveDelay
|
||||
}
|
||||
}
|
||||
|
||||
$endTime = Get-Date
|
||||
$totalDuration = $endTime - $startTime
|
||||
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host "TEST COMPLETED" -ForegroundColor Green
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "Statistics:" -ForegroundColor Yellow
|
||||
Write-Host " Total Runs: $TotalRuns" -ForegroundColor Yellow
|
||||
Write-Host " Total Waves: $waveNumber" -ForegroundColor Yellow
|
||||
Write-Host " Total Duration: $([Math]::Round($totalDuration.TotalSeconds, 2)) seconds" -ForegroundColor Yellow
|
||||
Write-Host " Average per Run: $([Math]::Round($totalDuration.TotalSeconds / $TotalRuns, 2)) seconds" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
$successCount = ($allRuns | Where-Object { $_.ExitCode -eq 0 }).Count
|
||||
$failureCount = $TotalRuns - $successCount
|
||||
|
||||
Write-Host "Results:" -ForegroundColor Yellow
|
||||
Write-Host " Successful: $successCount/$TotalRuns" -ForegroundColor Green
|
||||
if ($failureCount -gt 0) {
|
||||
Write-Host " Failed: $failureCount/$TotalRuns" -ForegroundColor Red
|
||||
}
|
||||
Write-Host ""
|
||||
Reference in New Issue
Block a user