create-dwy 0.16.1 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/bin/index.js +1 -1
- package/package.json +1 -1
- package/src/sync-all.js +303 -59
- package/src/sync-global-skills.js +167 -0
- package/src/sync.js +21 -11
- package/templates/ai-tools/CHANGELOG.md +134 -0
- package/templates/ai-tools/VERSION +1 -1
- package/templates/ai-tools/rules/Android/dwy-android-core.md +65 -1
- package/templates/ai-tools/rules/Python/dwy-python-core.md +47 -0
- package/templates/ai-tools/rules/Vue/dwy-vue-core.md +55 -0
- package/templates/ai-tools/rules/iOS/dwy-swift-core.md +46 -0
- package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-oss-commercial-license.md +128 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/SKILL.md +65 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/assets/appstore-submission.yaml +43 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/references/api-workflow.md +17 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/references/in-app-purchase-review.md +16 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/references/screenshot-workflow.md +16 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/scripts/appstore_config.sh +140 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/SKILL.md +11 -8
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/android.md +2 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/backend-deploy.md +2 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/changelog.md +24 -4
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/frontend-deploy.md +2 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/generic-release.md +2 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/git-tag.md +82 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/harmony.md +2 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/ios.md +3 -2
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/monitor-notify.md +2 -2
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-semver/SKILL.md +1 -1
- package/templates/ai-tools/skills//345/237/272/347/241/200/345/272/223/dwy-eapi/references/tasks-integration-guide.md +2 -2
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/README.md +57 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/SKILL.md +147 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/references/api.md +43 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/references/config.example.yaml +33 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/global_config.py +89 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/setup_config.py +175 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/synthesize.py +339 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/SKILL.md +127 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/assets/cover-style-master-v1.png +0 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/references/platform-copy-examples.md +37 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/references/platform-posting-times.md +193 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0005-ideation/SKILL.md +42 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0005-ideation/templates/topic-backlog.template.md +50 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0005-ideation/templates//351/200/211/351/242/230/346/261/240.template.md +16 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0010-product/SKILL.md +106 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0010-product/templates/channel-profile.template.md +52 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0010-product/templates//344/272/247/345/223/201/345/215/241.template.md +132 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/SKILL.md +60 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/scripts/build_facts_html.py +430 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/scripts/generate_html.py +1287 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/scripts/generate_report.py +189 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/templates//344/272/213/345/256/236/350/265/204/346/226/231/345/272/223.template.md +55 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/SKILL.md +36 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates/README.md +10 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates//344/272/213/345/256/236.template.md +82 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates//345/215/225/351/233/206/346/226/207/346/241/243.template.md +175 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates//350/204/232/346/234/254.template.md +69 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates//351/252/250/346/236/266-v1.1.md +174 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0050-design/SKILL.md +55 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0060-assets/SKILL.md +29 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package/SKILL.md +42 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package/scripts/validate_shots.py +207 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package/shots.schema.json +186 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package//344/272/272/345/256/241/345/214/205.template.md +1 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package//344/272/272/345/256/241/350/257/264/346/230/216.md +15 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package//346/210/220/347/211/207/345/214/205.template.md +49 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0080-factory/SKILL.md +58 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-comic-kit/SKILL.md +424 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-comic-kit/evals.md +41 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-flow/CONTRACT.md +123 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-flow/SKILL.md +81 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-flow//346/211/247/350/241/214/346/270/205/345/215/225.template.md +60 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/SKILL.md +78 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/agents/openai.yaml +4 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/knowledge-town-paper-film-v1.json +80 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/AudioTracks.tsx +20 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/CaptionLayer.tsx +18 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/CueTimeline.ts +24 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/KnowledgeTownComposition.tsx +21 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/references/cinematic-direction.md +73 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/references/sticker-asset-production.md +30 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/references/style-guide.md +43 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/scripts/build_cue_timeline.py +75 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/scripts/validate_cue_timeline.py +68 -0
- package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/scripts/validate_style_preset.py +22 -0
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/SKILL.md +0 -511
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/checks-data.md +0 -126
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/checks-network.md +0 -88
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/checks-runtime.md +0 -195
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/security-doc-search.md +0 -179
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_base.sh +0 -39
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_capacity.sh +0 -278
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_db.sh +0 -147
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_docker.sh +0 -230
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_env.sh +0 -64
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_https.sh +0 -60
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_logs.sh +0 -209
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_nginx.sh +0 -100
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_resilience.sh +0 -157
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_secrets.sh +0 -265
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_services.sh +0 -94
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_ssh.sh +0 -56
- package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/run_all.sh +0 -105
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# 环境变量与文件权限检查
|
|
3
|
-
TARGET="$1"; shift
|
|
4
|
-
SSH_OPTS=("$@")
|
|
5
|
-
|
|
6
|
-
ssh "${SSH_OPTS[@]}" "${TARGET}" bash -s <<'REMOTE'
|
|
7
|
-
echo "--- 全局搜索 .env 文件位置 (限制深度,跳过 /proc /sys) ---"
|
|
8
|
-
sudo -n find /home /opt /srv /var/www /root /etc -maxdepth 6 -type f \
|
|
9
|
-
\( -name ".env" -o -name ".env.*" -o -name "*.env" \) \
|
|
10
|
-
! -name "*.example" ! -name "*.sample" ! -name "*.template" \
|
|
11
|
-
-printf "%M %u:%g %p (%s bytes)\n" 2>/dev/null \
|
|
12
|
-
|| find /home /opt /srv /var/www -maxdepth 6 -type f \
|
|
13
|
-
\( -name ".env" -o -name ".env.*" \) \
|
|
14
|
-
! -name "*.example" ! -name "*.sample" \
|
|
15
|
-
-printf "%M %u:%g %p (%s bytes)\n" 2>/dev/null \
|
|
16
|
-
|| echo "[!] 无 sudo,部分目录无法扫描"
|
|
17
|
-
|
|
18
|
-
echo ""
|
|
19
|
-
echo "--- nginx 静态根目录是否包含敏感文件 ---"
|
|
20
|
-
NGINX_DUMP=$(sudo -n nginx -T 2>/dev/null || nginx -T 2>/dev/null || true)
|
|
21
|
-
if [[ -n "$NGINX_DUMP" ]]; then
|
|
22
|
-
ROOTS=$(echo "$NGINX_DUMP" | awk '/^[[:space:]]*root /{print $2}' | tr -d ';' | sort -u)
|
|
23
|
-
for r in $ROOTS; do
|
|
24
|
-
echo ">> root = $r"
|
|
25
|
-
[[ -d "$r" ]] || { echo " [!] 目录不存在或不可读"; continue; }
|
|
26
|
-
for s in ".env" ".git" ".DS_Store" "package.json" "composer.json" "wp-config.php"; do
|
|
27
|
-
if [[ -e "$r/$s" ]]; then
|
|
28
|
-
echo " [!] 暴露: $r/$s"
|
|
29
|
-
fi
|
|
30
|
-
done
|
|
31
|
-
done
|
|
32
|
-
fi
|
|
33
|
-
|
|
34
|
-
echo ""
|
|
35
|
-
echo "--- 关键文件权限 ---"
|
|
36
|
-
for f in /etc/shadow /etc/passwd /etc/sudoers /etc/ssh/sshd_config /etc/nginx/nginx.conf; do
|
|
37
|
-
ls -l "$f" 2>/dev/null || echo " [i] $f 不可读"
|
|
38
|
-
done
|
|
39
|
-
|
|
40
|
-
echo ""
|
|
41
|
-
echo "--- 应用进程运行用户 (期望非 root) ---"
|
|
42
|
-
ps -eo user,pid,cmd --sort=user 2>/dev/null | grep -E "(node|python|uvicorn|gunicorn|java|php-fpm|fastapi|uwsgi)" | grep -v grep | head -20
|
|
43
|
-
|
|
44
|
-
echo ""
|
|
45
|
-
echo "--- sudo 免密配置 ---"
|
|
46
|
-
sudo -n cat /etc/sudoers 2>/dev/null | grep -v "^#" | grep -v "^$" | head -20 || echo "[i] 无 sudo 权限读取 /etc/sudoers"
|
|
47
|
-
sudo -n ls /etc/sudoers.d/ 2>/dev/null | head -10
|
|
48
|
-
|
|
49
|
-
echo ""
|
|
50
|
-
echo "--- 全局环境变量泄漏排查 (是否有密码/key 写在 /etc/environment 或 /etc/profile) ---"
|
|
51
|
-
for f in /etc/environment /etc/profile /etc/bash.bashrc; do
|
|
52
|
-
if [[ -r "$f" ]]; then
|
|
53
|
-
grep -iE "password|secret|token|api_key|apikey" "$f" 2>/dev/null \
|
|
54
|
-
| sed -E 's/(password|secret|token|api[_-]?key)([^=]*=)([^[:space:]]+)/\1\2<REDACTED>/gi' \
|
|
55
|
-
|| true
|
|
56
|
-
fi
|
|
57
|
-
done
|
|
58
|
-
|
|
59
|
-
echo ""
|
|
60
|
-
echo "--- crontab 中是否有可疑命令 ---"
|
|
61
|
-
sudo -n crontab -l 2>/dev/null | head -20 || crontab -l 2>/dev/null | head -20
|
|
62
|
-
echo "--- /etc/cron.d/ /etc/cron.daily/ ---"
|
|
63
|
-
ls /etc/cron.d/ /etc/cron.daily/ 2>/dev/null | head -20
|
|
64
|
-
REMOTE
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# HTTPS / SSL 证书检查
|
|
3
|
-
TARGET="$1"; shift
|
|
4
|
-
SSH_OPTS=("$@")
|
|
5
|
-
|
|
6
|
-
ssh "${SSH_OPTS[@]}" "${TARGET}" bash -s <<'REMOTE'
|
|
7
|
-
echo "--- 检测可能的 HTTPS 站点 (从 nginx 配置) ---"
|
|
8
|
-
DOMAINS=()
|
|
9
|
-
NGINX_DUMP=$(sudo -n nginx -T 2>/dev/null || nginx -T 2>/dev/null || true)
|
|
10
|
-
if [[ -n "$NGINX_DUMP" ]]; then
|
|
11
|
-
while IFS= read -r d; do
|
|
12
|
-
[[ -n "$d" && "$d" != "_" && "$d" != "localhost" ]] && DOMAINS+=("$d")
|
|
13
|
-
done < <(echo "$NGINX_DUMP" | awk '/server_name/ {for(i=2;i<=NF;i++) print $i}' | tr -d ';' | sort -u)
|
|
14
|
-
fi
|
|
15
|
-
|
|
16
|
-
if [[ ${#DOMAINS[@]} -eq 0 ]]; then
|
|
17
|
-
DOMAINS+=("localhost")
|
|
18
|
-
fi
|
|
19
|
-
|
|
20
|
-
echo "目标域名: ${DOMAINS[*]}"
|
|
21
|
-
|
|
22
|
-
for D in "${DOMAINS[@]}"; do
|
|
23
|
-
echo ""
|
|
24
|
-
echo "===== $D ====="
|
|
25
|
-
|
|
26
|
-
echo "--- HTTPS 可达性 ---"
|
|
27
|
-
HTTPS_CODE=$(curl -k -sS -o /dev/null -w "%{http_code}" --max-time 5 "https://$D" 2>/dev/null || echo "000")
|
|
28
|
-
HTTP_CODE=$(curl -sS -o /dev/null -w "%{http_code} -> %{redirect_url}" --max-time 5 "http://$D" 2>/dev/null || echo "000")
|
|
29
|
-
echo " https://$D -> HTTP $HTTPS_CODE"
|
|
30
|
-
echo " http://$D -> HTTP $HTTP_CODE"
|
|
31
|
-
|
|
32
|
-
echo "--- 证书信息 ---"
|
|
33
|
-
CERT=$(echo | timeout 5 openssl s_client -servername "$D" -connect "${D}:443" -showcerts 2>/dev/null </dev/null)
|
|
34
|
-
if [[ -z "$CERT" ]]; then
|
|
35
|
-
echo " [!] 无法获取证书 (可能未启用 HTTPS 或域名无 DNS)"
|
|
36
|
-
continue
|
|
37
|
-
fi
|
|
38
|
-
echo "$CERT" | openssl x509 -noout -subject -issuer -dates 2>/dev/null
|
|
39
|
-
|
|
40
|
-
echo "--- SAN ---"
|
|
41
|
-
echo "$CERT" | openssl x509 -noout -ext subjectAltName 2>/dev/null | grep -i "DNS:" | head -3
|
|
42
|
-
|
|
43
|
-
echo "--- 剩余天数 ---"
|
|
44
|
-
END=$(echo "$CERT" | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
|
|
45
|
-
if [[ -n "$END" ]]; then
|
|
46
|
-
END_TS=$(date -d "$END" +%s 2>/dev/null || date -j -f "%b %d %H:%M:%S %Y %Z" "$END" +%s 2>/dev/null)
|
|
47
|
-
NOW_TS=$(date +%s)
|
|
48
|
-
if [[ -n "$END_TS" ]]; then
|
|
49
|
-
DAYS=$(( (END_TS - NOW_TS) / 86400 ))
|
|
50
|
-
echo " 剩余 $DAYS 天 (过期时间: $END)"
|
|
51
|
-
fi
|
|
52
|
-
fi
|
|
53
|
-
|
|
54
|
-
echo "--- TLS 协议支持 ---"
|
|
55
|
-
for proto in tls1 tls1_1 tls1_2 tls1_3; do
|
|
56
|
-
R=$(echo | timeout 3 openssl s_client -"$proto" -connect "${D}:443" 2>&1 </dev/null | grep -E "Protocol|handshake failure|wrong version" | head -1)
|
|
57
|
-
printf " %-8s %s\n" "$proto" "$R"
|
|
58
|
-
done
|
|
59
|
-
done
|
|
60
|
-
REMOTE
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# 日志大小与防爆检查 (只读)
|
|
3
|
-
#
|
|
4
|
-
# 检查范围:
|
|
5
|
-
# - Docker 单容器 json-log 大小
|
|
6
|
-
# - Docker daemon log-opts 是否生效到具体容器
|
|
7
|
-
# - Nginx access/error log 大小 + logrotate 覆盖
|
|
8
|
-
# - systemd journal 占用 + SystemMaxUse 配置
|
|
9
|
-
# - 应用日志目录 (自动探测 /var/log/<svc>、/opt/*/logs、/home/*/logs)
|
|
10
|
-
# - 总日志占用 vs 根盘剩余, 估算撑天数
|
|
11
|
-
|
|
12
|
-
TARGET="$1"; shift
|
|
13
|
-
SSH_OPTS=("$@")
|
|
14
|
-
|
|
15
|
-
ssh "${SSH_OPTS[@]}" "${TARGET}" bash -s <<'REMOTE'
|
|
16
|
-
ROOT_FREE_MB=$(df -BM --output=avail / 2>/dev/null | tail -1 | tr -d ' M')
|
|
17
|
-
ROOT_FREE_MB=${ROOT_FREE_MB:-0}
|
|
18
|
-
NOW_TS=$(date +%s)
|
|
19
|
-
|
|
20
|
-
echo "--- 根盘可用 ---"
|
|
21
|
-
df -h / 2>/dev/null
|
|
22
|
-
echo "可用: ${ROOT_FREE_MB} MB"
|
|
23
|
-
|
|
24
|
-
# ============================================================
|
|
25
|
-
echo ""
|
|
26
|
-
echo "--- Docker 容器 json-log 大小 (单文件 Top 20) ---"
|
|
27
|
-
if command -v docker >/dev/null 2>&1; then
|
|
28
|
-
# 收集 daemon log-opts 用于关联判定
|
|
29
|
-
DAEMON_JSON=$(sudo -n cat /etc/docker/daemon.json 2>/dev/null \
|
|
30
|
-
|| cat /etc/docker/daemon.json 2>/dev/null || echo "")
|
|
31
|
-
DAEMON_MAX_SIZE=$(echo "$DAEMON_JSON" \
|
|
32
|
-
| grep -oE '"max-size"[[:space:]]*:[[:space:]]*"[^"]+"' \
|
|
33
|
-
| head -1 | grep -oE '"[^"]+"$' | tr -d '"')
|
|
34
|
-
echo "daemon.json log-opts max-size: ${DAEMON_MAX_SIZE:-(未配置)}"
|
|
35
|
-
echo ""
|
|
36
|
-
|
|
37
|
-
# 列出所有 json-log: <size> <path>
|
|
38
|
-
LOG_LIST=$(sudo -n find /var/lib/docker/containers -maxdepth 2 -name "*-json.log" \
|
|
39
|
-
-printf '%s %p\n' 2>/dev/null \
|
|
40
|
-
|| find /var/lib/docker/containers -maxdepth 2 -name "*-json.log" \
|
|
41
|
-
-printf '%s %p\n' 2>/dev/null)
|
|
42
|
-
|
|
43
|
-
if [[ -z "$LOG_LIST" ]]; then
|
|
44
|
-
echo "[i] 无法读取 /var/lib/docker/containers (需 sudo) 或无 json-log"
|
|
45
|
-
else
|
|
46
|
-
DOCKER_LOG_TOTAL_BYTES=0
|
|
47
|
-
# 排序+top 20, 反查容器名
|
|
48
|
-
while IFS=' ' read -r size path; do
|
|
49
|
-
[[ -z "$size" ]] && continue
|
|
50
|
-
DOCKER_LOG_TOTAL_BYTES=$(( DOCKER_LOG_TOTAL_BYTES + size ))
|
|
51
|
-
cid=$(basename "$(dirname "$path")")
|
|
52
|
-
cid_short="${cid:0:12}"
|
|
53
|
-
name=$(docker inspect -f '{{.Name}}' "$cid" 2>/dev/null | sed 's|^/||')
|
|
54
|
-
[[ -z "$name" ]] && name="<已删除>"
|
|
55
|
-
size_mb=$(( size / 1024 / 1024 ))
|
|
56
|
-
printf " %-32s %6d MB %s\n" "$name" "$size_mb" "$path"
|
|
57
|
-
|
|
58
|
-
# 单文件大小告警
|
|
59
|
-
if [[ "$size_mb" -ge 1024 ]] && [[ -z "$DAEMON_MAX_SIZE" ]]; then
|
|
60
|
-
echo " [!!!] CRITICAL: 单容器日志 ${size_mb} MB 且 daemon 无 log-opts 大小限制"
|
|
61
|
-
elif [[ "$size_mb" -ge 500 ]]; then
|
|
62
|
-
echo " [!!] HIGH: 单容器日志 ${size_mb} MB"
|
|
63
|
-
fi
|
|
64
|
-
done < <(echo "$LOG_LIST" | sort -rn | head -20)
|
|
65
|
-
|
|
66
|
-
DOCKER_LOG_TOTAL_MB=$(( DOCKER_LOG_TOTAL_BYTES / 1024 / 1024 ))
|
|
67
|
-
echo ""
|
|
68
|
-
echo "Docker json-log 合计: ${DOCKER_LOG_TOTAL_MB} MB"
|
|
69
|
-
fi
|
|
70
|
-
|
|
71
|
-
echo ""
|
|
72
|
-
echo "--- 各容器是否覆盖 logging driver (compose level 优先于 daemon level) ---"
|
|
73
|
-
docker ps -q 2>/dev/null | while read c; do
|
|
74
|
-
name=$(docker inspect -f '{{.Name}}' "$c" | sed 's|^/||')
|
|
75
|
-
lt=$(docker inspect -f '{{.HostConfig.LogConfig.Type}}' "$c" 2>/dev/null)
|
|
76
|
-
lc=$(docker inspect -f '{{json .HostConfig.LogConfig.Config}}' "$c" 2>/dev/null)
|
|
77
|
-
[[ -z "$lc" || "$lc" == "null" ]] && lc='{}'
|
|
78
|
-
printf " %-32s driver=%-12s opts=%s\n" "$name" "${lt:-?}" "$lc"
|
|
79
|
-
if [[ "$lt" == "json-file" && "$lc" == "{}" && -z "$DAEMON_MAX_SIZE" ]]; then
|
|
80
|
-
echo " [!!] HIGH: 容器无 logging.options 且 daemon 无 max-size, 日志可无限增长"
|
|
81
|
-
fi
|
|
82
|
-
done
|
|
83
|
-
else
|
|
84
|
-
echo "[i] Docker 未安装,跳过容器日志检查"
|
|
85
|
-
DOCKER_LOG_TOTAL_MB=0
|
|
86
|
-
fi
|
|
87
|
-
|
|
88
|
-
# ============================================================
|
|
89
|
-
echo ""
|
|
90
|
-
echo "--- Nginx 日志 ---"
|
|
91
|
-
if [[ -d /var/log/nginx ]]; then
|
|
92
|
-
ls -lh /var/log/nginx/ 2>/dev/null | head -20
|
|
93
|
-
NGINX_LOG_BYTES=$(sudo -n du -sb /var/log/nginx 2>/dev/null | awk '{print $1}' \
|
|
94
|
-
|| du -sb /var/log/nginx 2>/dev/null | awk '{print $1}')
|
|
95
|
-
NGINX_LOG_MB=$(( ${NGINX_LOG_BYTES:-0} / 1024 / 1024 ))
|
|
96
|
-
echo "合计: ${NGINX_LOG_MB} MB"
|
|
97
|
-
|
|
98
|
-
# access.log / error.log 单文件大小
|
|
99
|
-
for f in /var/log/nginx/access.log /var/log/nginx/error.log; do
|
|
100
|
-
[[ -f "$f" ]] || continue
|
|
101
|
-
sz_mb=$(( $(stat -c %s "$f" 2>/dev/null || echo 0) / 1024 / 1024 ))
|
|
102
|
-
if [[ "$sz_mb" -ge 500 ]]; then
|
|
103
|
-
echo "[!!] HIGH: $f 单文件 ${sz_mb} MB"
|
|
104
|
-
fi
|
|
105
|
-
done
|
|
106
|
-
|
|
107
|
-
# logrotate 覆盖
|
|
108
|
-
if [[ -f /etc/logrotate.d/nginx ]]; then
|
|
109
|
-
echo "[OK] /etc/logrotate.d/nginx 存在"
|
|
110
|
-
else
|
|
111
|
-
echo "[!!] HIGH: nginx 已部署但无 /etc/logrotate.d/nginx, 日志可能无限增长"
|
|
112
|
-
fi
|
|
113
|
-
else
|
|
114
|
-
echo "[i] /var/log/nginx 不存在, 跳过"
|
|
115
|
-
NGINX_LOG_MB=0
|
|
116
|
-
fi
|
|
117
|
-
|
|
118
|
-
# ============================================================
|
|
119
|
-
echo ""
|
|
120
|
-
echo "--- systemd journal 占用 ---"
|
|
121
|
-
if command -v journalctl >/dev/null 2>&1; then
|
|
122
|
-
JOURNAL_USAGE=$(journalctl --disk-usage 2>/dev/null | grep -oE '[0-9.]+[KMG]B?' | tail -1)
|
|
123
|
-
echo "journalctl --disk-usage: ${JOURNAL_USAGE:-?}"
|
|
124
|
-
# 转 MB (粗略)
|
|
125
|
-
case "$JOURNAL_USAGE" in
|
|
126
|
-
*G*) JOURNAL_MB=$(echo "$JOURNAL_USAGE" | sed 's/[GBb]//g' | awk '{print int($1*1024)}') ;;
|
|
127
|
-
*M*) JOURNAL_MB=$(echo "$JOURNAL_USAGE" | sed 's/[MBb]//g' | awk '{print int($1)}') ;;
|
|
128
|
-
*K*) JOURNAL_MB=0 ;;
|
|
129
|
-
*) JOURNAL_MB=0 ;;
|
|
130
|
-
esac
|
|
131
|
-
|
|
132
|
-
# SystemMaxUse 配置
|
|
133
|
-
SMU=$(grep -E "^[[:space:]]*SystemMaxUse" /etc/systemd/journald.conf 2>/dev/null \
|
|
134
|
-
| head -1 | awk -F= '{gsub(/[ \t]/,"",$2); print $2}')
|
|
135
|
-
echo "SystemMaxUse: ${SMU:-(未配置, 默认按磁盘 10% 自动控)}"
|
|
136
|
-
|
|
137
|
-
if [[ "$JOURNAL_MB" -ge 2048 && -z "$SMU" ]]; then
|
|
138
|
-
echo "[!!] HIGH: journal 已 ${JOURNAL_MB} MB 且未配 SystemMaxUse"
|
|
139
|
-
fi
|
|
140
|
-
else
|
|
141
|
-
JOURNAL_MB=0
|
|
142
|
-
fi
|
|
143
|
-
|
|
144
|
-
# ============================================================
|
|
145
|
-
echo ""
|
|
146
|
-
echo "--- 应用日志目录 (自动探测 Top 5) ---"
|
|
147
|
-
APP_LOG_TOTAL_MB=0
|
|
148
|
-
# 优先 sudo, 失败再退化; 不要用 OR fallback (du 退出码可能因部分不可读而非零, 会被双重执行)
|
|
149
|
-
APP_LOG_LIST=$(sudo -n du -smc /var/log/*/ /opt/*/logs /opt/*/log /home/*/logs /srv/*/logs 2>/dev/null \
|
|
150
|
-
| grep -v 'total$' | sort -rn | head -10)
|
|
151
|
-
if [[ -z "$APP_LOG_LIST" ]]; then
|
|
152
|
-
APP_LOG_LIST=$(du -smc /var/log/*/ /opt/*/logs /opt/*/log /home/*/logs /srv/*/logs 2>/dev/null \
|
|
153
|
-
| grep -v 'total$' | sort -rn | head -10)
|
|
154
|
-
fi
|
|
155
|
-
echo "$APP_LOG_LIST"
|
|
156
|
-
APP_LOG_TOTAL_MB=$(echo "$APP_LOG_LIST" | awk '{s+=$1} END{print s+0}')
|
|
157
|
-
|
|
158
|
-
# ============================================================
|
|
159
|
-
echo ""
|
|
160
|
-
echo "--- 日志总占用 vs 根盘剩余 (撑天数粗估) ---"
|
|
161
|
-
TOTAL_LOG_MB=$(( DOCKER_LOG_TOTAL_MB + NGINX_LOG_MB + JOURNAL_MB + APP_LOG_TOTAL_MB ))
|
|
162
|
-
echo "Docker json-log: ${DOCKER_LOG_TOTAL_MB} MB"
|
|
163
|
-
echo "Nginx 日志: ${NGINX_LOG_MB} MB"
|
|
164
|
-
echo "systemd journal: ${JOURNAL_MB} MB"
|
|
165
|
-
echo "应用日志合计: ${APP_LOG_TOTAL_MB} MB"
|
|
166
|
-
echo "日志合计: ${TOTAL_LOG_MB} MB"
|
|
167
|
-
echo "根盘可用: ${ROOT_FREE_MB} MB"
|
|
168
|
-
|
|
169
|
-
# 撑天数估算: 取所有 docker json-log 的 (size / 容器存活天数) 加总作为 daily growth
|
|
170
|
-
GROWTH_MB=0
|
|
171
|
-
if command -v docker >/dev/null 2>&1; then
|
|
172
|
-
for c in $(docker ps -q 2>/dev/null); do
|
|
173
|
-
cid_full=$(docker inspect -f '{{.Id}}' "$c" 2>/dev/null)
|
|
174
|
-
log_path="/var/lib/docker/containers/${cid_full}/${cid_full}-json.log"
|
|
175
|
-
sz=$(sudo -n stat -c %s "$log_path" 2>/dev/null || stat -c %s "$log_path" 2>/dev/null || echo 0)
|
|
176
|
-
started=$(docker inspect -f '{{.State.StartedAt}}' "$c" 2>/dev/null)
|
|
177
|
-
started_ts=$(date -d "$started" +%s 2>/dev/null || echo 0)
|
|
178
|
-
if [[ "$started_ts" -gt 0 && "$sz" -gt 0 ]]; then
|
|
179
|
-
age_sec=$(( NOW_TS - started_ts ))
|
|
180
|
-
[[ "$age_sec" -lt 60 ]] && age_sec=60 # 防除零, 至少按 1 分钟算
|
|
181
|
-
daily_bytes=$(( sz * 86400 / age_sec ))
|
|
182
|
-
daily_mb=$(( daily_bytes / 1024 / 1024 ))
|
|
183
|
-
GROWTH_MB=$(( GROWTH_MB + daily_mb ))
|
|
184
|
-
fi
|
|
185
|
-
done
|
|
186
|
-
fi
|
|
187
|
-
|
|
188
|
-
echo "估算 Docker 日志日均增量: ${GROWTH_MB} MB/day (基于容器存活时长)"
|
|
189
|
-
|
|
190
|
-
if [[ "$GROWTH_MB" -gt 0 && "$ROOT_FREE_MB" -gt 0 ]]; then
|
|
191
|
-
DAYS=$(( ROOT_FREE_MB / GROWTH_MB ))
|
|
192
|
-
echo "按当前增速预计可撑: ${DAYS} 天 (粗估, 仅算 docker json-log)"
|
|
193
|
-
if [[ "$DAYS" -lt 30 ]]; then echo "[!!!] CRITICAL: 不足 30 天, 必须立即配 log-opts 或扩盘"
|
|
194
|
-
elif [[ "$DAYS" -lt 90 ]]; then echo "[!!] HIGH: 不足 90 天, 建议尽快补 log-opts max-size"
|
|
195
|
-
else echo "[OK] 撑天数 >= 90 天"
|
|
196
|
-
fi
|
|
197
|
-
else
|
|
198
|
-
echo "[i] 无法估算日均增量 (容器刚起或无日志)"
|
|
199
|
-
fi
|
|
200
|
-
|
|
201
|
-
# ============================================================
|
|
202
|
-
echo ""
|
|
203
|
-
echo "--- 关键服务 logrotate 规则一览 (只读复述) ---"
|
|
204
|
-
for app in nginx postgresql redis docker rsyslog; do
|
|
205
|
-
if [[ -f "/etc/logrotate.d/$app" ]]; then
|
|
206
|
-
echo " [OK] /etc/logrotate.d/$app"
|
|
207
|
-
fi
|
|
208
|
-
done
|
|
209
|
-
REMOTE
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Nginx 配置检查 (只读)
|
|
3
|
-
TARGET="$1"; shift
|
|
4
|
-
SSH_OPTS=("$@")
|
|
5
|
-
|
|
6
|
-
ssh "${SSH_OPTS[@]}" "${TARGET}" bash -s <<'REMOTE'
|
|
7
|
-
if ! command -v nginx >/dev/null 2>&1; then
|
|
8
|
-
echo "[i] nginx 未安装,跳过"
|
|
9
|
-
exit 0
|
|
10
|
-
fi
|
|
11
|
-
|
|
12
|
-
echo "--- nginx version ---"
|
|
13
|
-
nginx -v 2>&1
|
|
14
|
-
NGINX_VERSION=$(nginx -v 2>&1 | sed -n 's#.*nginx/\([^ ]*\).*#\1#p' | head -1)
|
|
15
|
-
echo "nginx_version_normalized=${NGINX_VERSION:-unknown}"
|
|
16
|
-
echo "official_doc_headers=https://nginx.org/en/docs/http/ngx_http_headers_module.html"
|
|
17
|
-
echo "official_doc_ssl=https://nginx.org/en/docs/http/ngx_http_ssl_module.html"
|
|
18
|
-
if [[ -n "$NGINX_VERSION" ]]; then
|
|
19
|
-
echo "search_hint_1=nginx ${NGINX_VERSION} security advisory"
|
|
20
|
-
echo "search_hint_2=nginx ${NGINX_VERSION} CVE"
|
|
21
|
-
fi
|
|
22
|
-
|
|
23
|
-
echo ""
|
|
24
|
-
echo "--- nginx 进程运行用户 ---"
|
|
25
|
-
ps -eo user,pid,cmd | grep "[n]ginx: master" | head -1
|
|
26
|
-
|
|
27
|
-
echo ""
|
|
28
|
-
echo "--- nginx -T (effective config, 需 sudo 或 nginx 用户可读) ---"
|
|
29
|
-
NGINX_DUMP=$(sudo -n nginx -T 2>/dev/null || nginx -T 2>/dev/null || true)
|
|
30
|
-
if [[ -z "$NGINX_DUMP" ]]; then
|
|
31
|
-
echo "[!] 无法 dump nginx 配置,改读 /etc/nginx/"
|
|
32
|
-
ls -la /etc/nginx/ 2>/dev/null
|
|
33
|
-
echo "--- /etc/nginx/nginx.conf (head) ---"
|
|
34
|
-
head -80 /etc/nginx/nginx.conf 2>/dev/null
|
|
35
|
-
echo "--- sites-enabled / conf.d ---"
|
|
36
|
-
for d in /etc/nginx/sites-enabled /etc/nginx/conf.d; do
|
|
37
|
-
[[ -d "$d" ]] && ls -la "$d" 2>/dev/null
|
|
38
|
-
done
|
|
39
|
-
else
|
|
40
|
-
echo "$NGINX_DUMP" | grep -E "^# configuration file" | head -20
|
|
41
|
-
echo ""
|
|
42
|
-
echo "--- KEY DIRECTIVES (filtered from nginx -T) ---"
|
|
43
|
-
echo "$NGINX_DUMP" | grep -Ei "^[[:space:]]*(listen|server_name|return|rewrite|ssl_protocols|ssl_ciphers|ssl_prefer_server_ciphers|ssl_certificate|ssl_certificate_key|server_tokens|access_log|error_log|client_max_body_size|client_body_timeout|add_header|autoindex|location|root|alias|proxy_pass)" \
|
|
44
|
-
| grep -v "^[[:space:]]*#" | head -200
|
|
45
|
-
|
|
46
|
-
echo ""
|
|
47
|
-
echo "--- HSTS / Security Headers 检查 ---"
|
|
48
|
-
echo "$NGINX_DUMP" | grep -i "Strict-Transport-Security\|X-Frame-Options\|X-Content-Type-Options\|Content-Security-Policy\|Referrer-Policy" || echo "[!] 未找到任何安全 header"
|
|
49
|
-
|
|
50
|
-
echo ""
|
|
51
|
-
echo "--- HTTP→HTTPS 跳转检查 ---"
|
|
52
|
-
echo "$NGINX_DUMP" | awk '/listen[[:space:]]+80/,/}/' | grep -i "return\|rewrite" | head -10 || echo "[!] 80 端口可能未配置强制跳转"
|
|
53
|
-
|
|
54
|
-
echo ""
|
|
55
|
-
echo "--- server_tokens ---"
|
|
56
|
-
echo "$NGINX_DUMP" | grep -E "^[[:space:]]*server_tokens" || echo "[!] server_tokens 未显式配置 (默认 on,会暴露版本)"
|
|
57
|
-
|
|
58
|
-
echo ""
|
|
59
|
-
echo "--- access_log / error_log ---"
|
|
60
|
-
echo "$NGINX_DUMP" | grep -E "^[[:space:]]*(access_log|error_log)" | head -10
|
|
61
|
-
|
|
62
|
-
echo ""
|
|
63
|
-
echo "--- client_max_body_size (业务非上传 ≤ 10m) ---"
|
|
64
|
-
echo "$NGINX_DUMP" | grep -E "^[[:space:]]*client_max_body_size" || echo "[!] 未显式配置 client_max_body_size"
|
|
65
|
-
|
|
66
|
-
echo ""
|
|
67
|
-
echo "--- 限流配置 (limit_req / limit_conn 防 CC / 暴力请求) ---"
|
|
68
|
-
ZONE_DEFS=$(echo "$NGINX_DUMP" | grep -E "^[[:space:]]*limit_(req|conn)_zone" || true)
|
|
69
|
-
if [[ -z "$ZONE_DEFS" ]]; then
|
|
70
|
-
echo "[!] CRITICAL: 未发现任何 limit_req_zone / limit_conn_zone 定义,无 CC 攻击防护"
|
|
71
|
-
else
|
|
72
|
-
echo "已定义 zone:"
|
|
73
|
-
echo "$ZONE_DEFS"
|
|
74
|
-
echo ""
|
|
75
|
-
echo "应用位置 (limit_req / limit_conn):"
|
|
76
|
-
echo "$NGINX_DUMP" | grep -E "^[[:space:]]*limit_(req|conn)[[:space:]]" || echo "[!] zone 已定义但未在 server/location 中应用"
|
|
77
|
-
echo ""
|
|
78
|
-
LIMIT_STATUS=$(echo "$NGINX_DUMP" | grep -E "^[[:space:]]*limit_req_status" | head -1)
|
|
79
|
-
echo "limit_req_status: ${LIMIT_STATUS:-(默认 503,建议 429)}"
|
|
80
|
-
fi
|
|
81
|
-
|
|
82
|
-
echo ""
|
|
83
|
-
echo "--- 慢速攻击防护 (slowloris) ---"
|
|
84
|
-
for d in client_body_timeout client_header_timeout send_timeout keepalive_timeout; do
|
|
85
|
-
val=$(echo "$NGINX_DUMP" | grep -E "^[[:space:]]*${d}[[:space:]]" | head -1)
|
|
86
|
-
echo "${d}: ${val:-(未显式配置,使用默认)}"
|
|
87
|
-
done
|
|
88
|
-
fi
|
|
89
|
-
|
|
90
|
-
echo ""
|
|
91
|
-
echo "--- nginx 配置语法检查 ---"
|
|
92
|
-
sudo -n nginx -t 2>&1 || nginx -t 2>&1 || echo "[i] 无法执行 nginx -t"
|
|
93
|
-
|
|
94
|
-
echo ""
|
|
95
|
-
echo "--- 危险路径暴露快测 (本机回环) ---"
|
|
96
|
-
for path in "/.env" "/.git/HEAD" "/.git/config" "/admin" "/phpmyadmin" "/.DS_Store"; do
|
|
97
|
-
code=$(curl -k -s -o /dev/null -w "%{http_code}" --max-time 3 "https://localhost${path}" 2>/dev/null || echo "000")
|
|
98
|
-
printf " %-20s -> https://localhost HTTP %s\n" "$path" "$code"
|
|
99
|
-
done
|
|
100
|
-
REMOTE
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# 自愈能力 / 资源耗尽防护检查 (只读)
|
|
3
|
-
#
|
|
4
|
-
# 检查范围:
|
|
5
|
-
# B 类: 系统服务开机自启 (sshd / nginx / docker / postgres / redis / fail2ban / 自定义)
|
|
6
|
-
# D 类: 资源耗尽防护 (swap / ulimit / logrotate / 磁盘使用率 / 应用进程内存上限)
|
|
7
|
-
#
|
|
8
|
-
# 服务器意外重启后,这些配置决定了服务能否自动恢复;资源耗尽场景决定了
|
|
9
|
-
# 服务能否在异常下保住基本运行而不被全局拖垮。
|
|
10
|
-
|
|
11
|
-
TARGET="$1"; shift
|
|
12
|
-
SSH_OPTS=("$@")
|
|
13
|
-
|
|
14
|
-
ssh "${SSH_OPTS[@]}" "${TARGET}" bash -s <<'REMOTE'
|
|
15
|
-
echo "########## B. 系统服务开机自启 ##########"
|
|
16
|
-
|
|
17
|
-
# 默认必检清单
|
|
18
|
-
DEFAULT_SERVICES=(sshd ssh nginx docker docker.socket postgresql postgres redis redis-server fail2ban supervisor crond cron)
|
|
19
|
-
|
|
20
|
-
echo "--- 默认必检清单 ---"
|
|
21
|
-
for svc in "${DEFAULT_SERVICES[@]}"; do
|
|
22
|
-
# systemctl status 区分: not-found / disabled / enabled / static / masked
|
|
23
|
-
enabled=$(systemctl is-enabled "$svc" 2>/dev/null || echo "n/a")
|
|
24
|
-
active=$(systemctl is-active "$svc" 2>/dev/null || echo "n/a")
|
|
25
|
-
if [[ "$enabled" == "n/a" && "$active" == "n/a" ]]; then
|
|
26
|
-
continue # 该服务未安装,跳过
|
|
27
|
-
fi
|
|
28
|
-
case "$enabled" in
|
|
29
|
-
enabled|enabled-runtime|alias|static)
|
|
30
|
-
icon="[OK]" ;;
|
|
31
|
-
disabled)
|
|
32
|
-
icon="[!!!] CRITICAL: 已部署但未开机自启,服务器重启后不会启动" ;;
|
|
33
|
-
masked)
|
|
34
|
-
icon="[!!!] CRITICAL: 服务被 mask,无法启动" ;;
|
|
35
|
-
*)
|
|
36
|
-
icon="[?] enabled=$enabled" ;;
|
|
37
|
-
esac
|
|
38
|
-
printf " %-20s active=%-10s enabled=%-12s %s\n" "$svc" "$active" "$enabled" "$icon"
|
|
39
|
-
done
|
|
40
|
-
|
|
41
|
-
echo ""
|
|
42
|
-
echo "--- 自动探测: 当前 enabled 的所有 unit (供人工核对应用主进程是否在内) ---"
|
|
43
|
-
systemctl list-unit-files --type=service --state=enabled 2>/dev/null \
|
|
44
|
-
| awk 'NR>1 && $1 != "" {print " " $1}' \
|
|
45
|
-
| head -40 || echo "[i] 无法列出 unit-files"
|
|
46
|
-
|
|
47
|
-
echo ""
|
|
48
|
-
echo "--- 自动探测: 当前 running 但 disabled 的服务 (重启后会消失) ---"
|
|
49
|
-
running_services=$(systemctl list-units --type=service --state=running --no-pager --no-legend 2>/dev/null | awk '{print $1}')
|
|
50
|
-
for svc in $running_services; do
|
|
51
|
-
enabled=$(systemctl is-enabled "$svc" 2>/dev/null)
|
|
52
|
-
if [[ "$enabled" == "disabled" ]]; then
|
|
53
|
-
echo " [!!] $svc 正在运行但 disabled,重启后会丢失"
|
|
54
|
-
fi
|
|
55
|
-
done
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
echo ""
|
|
59
|
-
echo "########## D. 资源耗尽防护 ##########"
|
|
60
|
-
|
|
61
|
-
echo "--- 内存与 swap ---"
|
|
62
|
-
free -h 2>/dev/null || vmstat -s 2>/dev/null | head -10
|
|
63
|
-
SWAP_SIZE=$(awk '/SwapTotal/ {print $2}' /proc/meminfo 2>/dev/null)
|
|
64
|
-
if [[ -z "$SWAP_SIZE" || "$SWAP_SIZE" == "0" ]]; then
|
|
65
|
-
echo "[!] MEDIUM: 未配置 swap,内存吃紧时直接 OOM kill"
|
|
66
|
-
echo " 建议: 至少配置 1-2GB swap (fallocate / dd + mkswap + swapon + /etc/fstab)"
|
|
67
|
-
else
|
|
68
|
-
echo "[OK] swap 已配置: $((SWAP_SIZE / 1024)) MB"
|
|
69
|
-
fi
|
|
70
|
-
|
|
71
|
-
echo ""
|
|
72
|
-
echo "--- 根分区使用率 ---"
|
|
73
|
-
df -h / 2>/dev/null
|
|
74
|
-
ROOT_USE=$(df / --output=pcent 2>/dev/null | tail -1 | tr -d ' %')
|
|
75
|
-
if [[ -n "$ROOT_USE" ]]; then
|
|
76
|
-
if [[ "$ROOT_USE" -ge 90 ]]; then
|
|
77
|
-
echo "[!!!] CRITICAL: 根分区使用率 ${ROOT_USE}%, 即将写满"
|
|
78
|
-
elif [[ "$ROOT_USE" -ge 80 ]]; then
|
|
79
|
-
echo "[!] MEDIUM: 根分区使用率 ${ROOT_USE}%, 建议清理"
|
|
80
|
-
else
|
|
81
|
-
echo "[OK] 根分区使用率 ${ROOT_USE}%"
|
|
82
|
-
fi
|
|
83
|
-
fi
|
|
84
|
-
|
|
85
|
-
echo ""
|
|
86
|
-
echo "--- /var/log 与 /var/lib/docker 大小 ---"
|
|
87
|
-
sudo -n du -sh /var/log /var/lib/docker /var/lib/postgresql 2>/dev/null \
|
|
88
|
-
|| du -sh /var/log /var/lib/docker /var/lib/postgresql 2>/dev/null \
|
|
89
|
-
|| echo "[i] 部分目录不可读"
|
|
90
|
-
|
|
91
|
-
echo ""
|
|
92
|
-
echo "--- logrotate 配置 ---"
|
|
93
|
-
if [[ -f /etc/logrotate.conf ]]; then
|
|
94
|
-
echo "[OK] /etc/logrotate.conf 存在"
|
|
95
|
-
ls /etc/logrotate.d/ 2>/dev/null | head -20 | sed 's|^| |'
|
|
96
|
-
else
|
|
97
|
-
echo "[!] HIGH: /etc/logrotate.conf 不存在,日志可能无限增长"
|
|
98
|
-
fi
|
|
99
|
-
|
|
100
|
-
# 关键服务是否有 logrotate 规则
|
|
101
|
-
echo ""
|
|
102
|
-
echo "--- 关键服务 logrotate 规则 ---"
|
|
103
|
-
for app in nginx postgresql redis docker rsyslog; do
|
|
104
|
-
if [[ -f "/etc/logrotate.d/$app" ]]; then
|
|
105
|
-
echo " [OK] /etc/logrotate.d/$app"
|
|
106
|
-
else
|
|
107
|
-
if systemctl is-enabled "$app" >/dev/null 2>&1 || systemctl is-enabled "${app}-server" >/dev/null 2>&1; then
|
|
108
|
-
echo " [!] $app 已部署但无 logrotate 规则"
|
|
109
|
-
fi
|
|
110
|
-
fi
|
|
111
|
-
done
|
|
112
|
-
|
|
113
|
-
echo ""
|
|
114
|
-
echo "--- 文件描述符上限 (system + 关键服务) ---"
|
|
115
|
-
echo " 系统 fs.file-max: $(sysctl -n fs.file-max 2>/dev/null)"
|
|
116
|
-
echo " 系统 fs.nr_open: $(sysctl -n fs.nr_open 2>/dev/null)"
|
|
117
|
-
for app in nginx postgres redis-server; do
|
|
118
|
-
pid=$(pgrep -f "[${app:0:1}]${app:1}" | head -1)
|
|
119
|
-
if [[ -n "$pid" ]]; then
|
|
120
|
-
soft=$(awk '/Max open files/ {print $4}' /proc/$pid/limits 2>/dev/null)
|
|
121
|
-
hard=$(awk '/Max open files/ {print $5}' /proc/$pid/limits 2>/dev/null)
|
|
122
|
-
echo " $app (pid $pid): soft=$soft hard=$hard"
|
|
123
|
-
if [[ -n "$soft" && "$soft" -lt 4096 ]]; then
|
|
124
|
-
echo " [!] MEDIUM: ulimit -n 偏低 ($soft),高并发场景可能耗尽"
|
|
125
|
-
fi
|
|
126
|
-
fi
|
|
127
|
-
done
|
|
128
|
-
|
|
129
|
-
echo ""
|
|
130
|
-
echo "--- /etc/security/limits.conf 自定义条目 ---"
|
|
131
|
-
sudo -n grep -vE "^[[:space:]]*#|^[[:space:]]*$" /etc/security/limits.conf 2>/dev/null \
|
|
132
|
-
|| grep -vE "^[[:space:]]*#|^[[:space:]]*$" /etc/security/limits.conf 2>/dev/null \
|
|
133
|
-
|| echo "[i] limits.conf 不可读"
|
|
134
|
-
ls /etc/security/limits.d/ 2>/dev/null | sed 's|^| /etc/security/limits.d/|'
|
|
135
|
-
|
|
136
|
-
echo ""
|
|
137
|
-
echo "--- 内存压力指标 (PSI) ---"
|
|
138
|
-
if [[ -r /proc/pressure/memory ]]; then
|
|
139
|
-
cat /proc/pressure/memory
|
|
140
|
-
else
|
|
141
|
-
echo "[i] PSI 不可用 (内核 < 4.20 或未启用)"
|
|
142
|
-
fi
|
|
143
|
-
|
|
144
|
-
echo ""
|
|
145
|
-
echo "--- 关键容器内存上限 (避免容器吃掉宿主机) ---"
|
|
146
|
-
if command -v docker >/dev/null 2>&1; then
|
|
147
|
-
docker ps -q 2>/dev/null | while read c; do
|
|
148
|
-
name=$(docker inspect -f '{{.Name}}' "$c" 2>/dev/null | sed 's|^/||')
|
|
149
|
-
mem=$(docker inspect -f '{{.HostConfig.Memory}}' "$c" 2>/dev/null)
|
|
150
|
-
if [[ "$mem" == "0" ]]; then
|
|
151
|
-
echo " [!] $name 无内存上限,异常时可能耗尽宿主机"
|
|
152
|
-
else
|
|
153
|
-
echo " [OK] $name Memory=$((mem / 1024 / 1024)) MB"
|
|
154
|
-
fi
|
|
155
|
-
done
|
|
156
|
-
fi
|
|
157
|
-
REMOTE
|