chore: 整理项目结构,清理归档文件,更新部署配置
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# /itdesk/ 500 错误诊断脚本
|
||||
# 在生产服务器 10.90.5.110 上跑(PuTTY 登录后):
|
||||
# cd /opt/wecom-it-desk
|
||||
# bash diagnose-500.sh > /tmp/diag.log 2>&1
|
||||
# cat /tmp/diag.log
|
||||
# =============================================================================
|
||||
|
||||
echo "========== 1. 容器状态 =========="
|
||||
docker compose ps
|
||||
|
||||
echo ""
|
||||
echo "========== 2. /opt/wecom-it-desk 目录结构 =========="
|
||||
ls -la /opt/wecom-it-desk/ 2>&1 | head -20
|
||||
echo "--- frontend-h5/dist ---"
|
||||
ls -la /opt/wecom-it-desk/frontend-h5/dist/ 2>&1 | head -10
|
||||
echo "--- frontend-h5/dist/assets ---"
|
||||
ls -la /opt/wecom-it-desk/frontend-h5/dist/assets/ 2>&1 | head -10
|
||||
echo "--- frontend-agent/dist/assets ---"
|
||||
ls -la /opt/wecom-it-desk/frontend-agent/dist/assets/ 2>&1 | head -10
|
||||
echo "--- frontend-portal/dist/assets ---"
|
||||
ls -la /opt/wecom-it-desk/frontend-portal/dist/assets/ 2>&1 | head -10
|
||||
echo "--- frontend-admin/dist/assets ---"
|
||||
ls -la /opt/wecom-it-desk/frontend-admin/dist/assets/ 2>&1 | head -10
|
||||
|
||||
echo ""
|
||||
echo "========== 3. nginx 容器内文件检查 =========="
|
||||
docker compose exec nginx ls -la /usr/share/nginx/html/ 2>&1 | head -20
|
||||
echo "--- /usr/share/nginx/html/itdesk ---"
|
||||
docker compose exec nginx ls -la /usr/share/nginx/html/itdesk/ 2>&1 | head -10
|
||||
echo "--- /usr/share/nginx/html/itdesk/assets ---"
|
||||
docker compose exec nginx ls -la /usr/share/nginx/html/itdesk/assets/ 2>&1 | head -10
|
||||
echo "--- /usr/share/nginx/ssl/ ---"
|
||||
docker compose exec nginx ls -la /etc/nginx/ssl/ 2>&1 | head -10
|
||||
|
||||
echo ""
|
||||
echo "========== 4. nginx 配置实际生效版本(头部 50 行)=========="
|
||||
docker compose exec nginx cat /etc/nginx/nginx.conf 2>&1 | head -50
|
||||
|
||||
echo ""
|
||||
echo "========== 5. nginx 容器端口监听 =========="
|
||||
docker compose exec nginx netstat -tlnp 2>&1 | head -10
|
||||
echo "(没 netstat 用 ss:)"
|
||||
docker compose exec nginx ss -tlnp 2>&1 | head -10
|
||||
|
||||
echo ""
|
||||
echo "========== 6. 直接 curl 测试各路径 =========="
|
||||
echo "--- /itdesk/ (容器内) ---"
|
||||
docker compose exec nginx curl -ksI https://localhost/itdesk/ 2>&1 | head -20
|
||||
echo "--- /itdesk/ (容器外主机 443) ---"
|
||||
curl -ksI https://localhost:443/itdesk/ 2>&1 | head -20
|
||||
echo "--- /itportal/ ---"
|
||||
curl -ksI https://localhost:443/itportal/ 2>&1 | head -20
|
||||
echo "--- /itdesk/assets/ (探 404) ---"
|
||||
curl -ksI https://localhost:443/itdesk/assets/ 2>&1 | head -20
|
||||
|
||||
echo ""
|
||||
echo "========== 7. 主机实际 URL 域名 =========="
|
||||
curl -ksI https://itsupport.servyou.com.cn/itdesk/ 2>&1 | head -20
|
||||
echo "---"
|
||||
curl -ksI https://itsupport.servyou.com.cn/itportal/ 2>&1 | head -20
|
||||
echo "---"
|
||||
curl -ksI https://itsupport.servyou.com.cn/itagent/ 2>&1 | head -20
|
||||
echo "---"
|
||||
curl -ksI https://itsupport.servyou.com.cn/itadmin/ 2>&1 | head -20
|
||||
|
||||
echo ""
|
||||
echo "========== 8. nginx access log 最近 30 行(找 500 请求)=========="
|
||||
docker compose exec nginx tail -30 /var/log/nginx/access.log 2>&1
|
||||
echo ""
|
||||
echo "========== 9. nginx error log 最近 30 行 =========="
|
||||
docker compose exec nginx tail -30 /var/log/nginx/error.log 2>&1
|
||||
|
||||
echo ""
|
||||
echo "========== 10. backend 容器健康 =========="
|
||||
docker compose ps backend
|
||||
echo "--- backend health endpoint ---"
|
||||
docker compose exec backend curl -ks http://localhost:8000/api/health 2>&1 | head -5
|
||||
|
||||
echo ""
|
||||
echo "========== 11. 看一下后端访问 /api/h5/me (H5 启动时会调)=========="
|
||||
echo "--- /api/h5/me 无 token ---"
|
||||
curl -ks -i -X GET https://itsupport.servyou.com.cn/api/h5/me 2>&1 | head -10
|
||||
@@ -0,0 +1 @@
|
||||
IyEvYmluL2Jhc2gKc2V0ICtlICAgIyBjb2xsZWN0IGV2ZXJ5dGhpbmcsIGRvbid0IGJhaWwKCmVjaG8gJyMjIyMjIyMjIyMjIyBTVEVQIDE6IExvY2F0ZSBwcm9qZWN0IGRpcmVjdG9yeSAjIyMjIyMjIyMjIyMnCmNkIC9vcHQvd2Vjb20taXQtZGVzayAyPiYxCmVjaG8gIkN1cnJlbnQgZGlyOiAkKHB3ZCkiCmxzIC1sYSBkb2NrZXItY29tcG9zZS55bWwgMj4mMQplY2hvICcnCgplY2hvICcjIyMjIyMjIyMjIyMgU1RFUCAyOiBEaWFnbm9zZSAoUkVBRC1PTkxZKSAjIyMjIyMjIyMjIyMnCmVjaG8gJy0tLSBBbGwgd2Vjb21faXRfIGNvbnRhaW5lcnMgLS0tJwpkb2NrZXIgcHMgLWEgLS1mb3JtYXQgInRhYmxlIHt7Lk5hbWVzfX1cdHt7LlN0YXR1c319IiB8IGdyZXAgLUUgIndlY29tX2l0X3xOQU1FUyIKZWNobyAnJwplY2hvICctLS0gRGlzayBzcGFjZSAtLS0nCmRmIC1oIC9vcHQgMj4mMQplY2hvICcnCmVjaG8gJy0tLSBiYWNrZW5kIGxhc3QgNjAgbG9nIGxpbmVzIC0tLScKZG9ja2VyIGxvZ3Mgd2Vjb21faXRfYmFja2VuZCAtLXRhaWwgNjAgMj4mMQplY2hvICcnCmVjaG8gJy0tLSBiYWNrZW5kIGludGVybmFsIGhlYWx0aCBjaGVjayAtLS0nCmRvY2tlciBleGVjIHdlY29tX2l0X2JhY2tlbmQgY3VybCAtcyAtbyAtIC13ICJcbkhUVFBfQ09ERTogJXtodHRwX2NvZGV9XG4iIC0tbWF4LXRpbWUgNSBodHRwOi8vbG9jYWxob3N0OjgwMDAvaGVhbHRoIDI+JjEKZWNobyAnJwoKZWNobyAnIyMjIyMjIyMjIyMjIFNURVAgMzogUmVzdGFydCBmcm9tIGNvcnJlY3QgZGlyZWN0b3J5
|
||||
@@ -0,0 +1 @@
|
||||
ICMjIyMjIyMjIyMjIycKY2QgL29wdC93ZWNvbS1pdC1kZXNrCmRvY2tlciBjb21wb3NlIHVwIC1kIDI+JjEKZWNobyAnJwplY2hvICdXYWl0aW5nIDE1cyBmb3Igc2VydmljZXMgdG8gc3RhYmlsaXplLi4uJwpzbGVlcCAxNQplY2hvICcnCmVjaG8gJy0tLSBDb250YWluZXJzIGFmdGVyIHJlc3RhcnQgLS0tJwpkb2NrZXIgcHMgLWEgLS1mb3JtYXQgInRhYmxlIHt7Lk5hbWVzfX1cdHt7LlN0YXR1c319IiB8IGdyZXAgLUUgIndlY29tX2l0X3xOQU1FUyIKZWNobyAnJwoKZWNobyAnIyMjIyMjIyMjIyMjIFNURVAgNDogRW5kLXRvLWVuZCB2ZXJpZmljYXRpb24gIyMjIyMjIyMjIyMjJwplY2hvICctLS0gYmFja2VuZCAvaGVhbHRoIC0tLScKY3VybCAtcyAtbyAtIC13ICJcbkhUVFBfQ09ERTogJXtodHRwX2NvZGV9XG4iIC0tbWF4LXRpbWUgNSBodHRwOi8vbG9jYWxob3N0OjgwMDAvaGVhbHRoCmVjaG8gJycKZWNobyAnLS0tIG5naW54IHJvdXRlcyAoZXhwZWN0IDIwMC8zMDEvMzAyKSAtLS0nCmZvciBwYXRoIGluIC8gL2l0YWdlbnQvIC9pdGg1LyAvaXRhZG1pbi87IGRvCiAgY29kZT0kKGN1cmwgLXMgLW8gL2Rldi9udWxsIC13ICIle2h0dHBfY29kZX0iIC0tbWF4LXRpbWUgNSAiaHR0cDovL2xvY2FsaG9zdCR7cGF0aH0iKQogIGVjaG8gIiAgJHBhdGggLT4gSFRUUCAkY29kZSIKZG9uZQplY2hvICcnCmVjaG8gJyMjIyMjIyMjIyMjIyBET05FICMjIyMjIyMjIyMjIycKZWNobyAnUGFzdGUgQUxMIG91dHB1dCBhYm92ZSBiYWNrIHRvIENsYXVkZSBmb3IgZGlhZ25vc2lzJwo=
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
set +e # collect everything, don't bail
|
||||
|
||||
echo '############ STEP 1: Locate project directory ############'
|
||||
cd /opt/wecom-it-desk 2>&1
|
||||
echo "Current dir: $(pwd)"
|
||||
ls -la docker-compose.yml 2>&1
|
||||
echo ''
|
||||
|
||||
echo '############ STEP 2: Diagnose (READ-ONLY) ############'
|
||||
echo '--- All wecom_it_ containers ---'
|
||||
docker ps -a --format "table {{.Names}}\t{{.Status}}" | grep -E "wecom_it_|NAMES"
|
||||
echo ''
|
||||
echo '--- Disk space ---'
|
||||
df -h /opt 2>&1
|
||||
echo ''
|
||||
echo '--- backend last 60 log lines ---'
|
||||
docker logs wecom_it_backend --tail 60 2>&1
|
||||
echo ''
|
||||
echo '--- backend internal health check ---'
|
||||
docker exec wecom_it_backend curl -s -o - -w "\nHTTP_CODE: %{http_code}\n" --max-time 5 http://localhost:8000/health 2>&1
|
||||
echo ''
|
||||
|
||||
echo '############ STEP 3: Restart from correct directory ############'
|
||||
cd /opt/wecom-it-desk
|
||||
docker compose up -d 2>&1
|
||||
echo ''
|
||||
echo 'Waiting 15s for services to stabilize...'
|
||||
sleep 15
|
||||
echo ''
|
||||
echo '--- Containers after restart ---'
|
||||
docker ps -a --format "table {{.Names}}\t{{.Status}}" | grep -E "wecom_it_|NAMES"
|
||||
echo ''
|
||||
|
||||
echo '############ STEP 4: End-to-end verification ############'
|
||||
echo '--- backend /health ---'
|
||||
curl -s -o - -w "\nHTTP_CODE: %{http_code}\n" --max-time 5 http://localhost:8000/health
|
||||
echo ''
|
||||
echo '--- nginx routes (expect 200/301/302) ---'
|
||||
for path in / /itagent/ /ith5/ /itadmin/; do
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "http://localhost${path}")
|
||||
echo " $path -> HTTP $code"
|
||||
done
|
||||
echo ''
|
||||
echo '############ DONE ############'
|
||||
echo 'Paste ALL output above back to Claude for diagnosis'
|
||||
@@ -0,0 +1,64 @@
|
||||
# NAS full /volume1/ scan with sudo (English-only)
|
||||
# Step 1: User runs `sudo -v` first (password stays local, never enters Claude)
|
||||
# Step 2: This script reuses that 15-min sudo session
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
$outputFile = "$PSScriptRoot\nas_volumes.txt"
|
||||
|
||||
chcp 65001 | Out-Null
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
Write-Host "===================================" -ForegroundColor Cyan
|
||||
Write-Host " NAS Full Scan (with sudo)" -ForegroundColor Cyan
|
||||
Write-Host "===================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "PREREQUISITE: open another terminal and run:" -ForegroundColor Yellow
|
||||
Write-Host " ssh simon@100.85.152.112" -ForegroundColor White
|
||||
Write-Host " sudo -v <- enter simon's password here, password NOT sent to Claude" -ForegroundColor White
|
||||
Write-Host " (keep that SSH session open for 15 min, sudo session cached)" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Read-Host "Press Enter after you have done sudo -v above"
|
||||
|
||||
# Force allocation so sudo can read password from terminal if needed
|
||||
$cmd = @"
|
||||
sudo bash <<'NAS_EOF'
|
||||
echo '===== [1] All top-level entries under /volume1/ ====='
|
||||
ls -la /volume1/ 2>&1
|
||||
echo ''
|
||||
echo '===== [2] Direct children sizes (1-3 minutes) ====='
|
||||
du -sh /volume1/*/ 2>/dev/null | sort -rh
|
||||
echo ''
|
||||
echo '===== [3] Disk space ====='
|
||||
df -h /volume1 2>&1 | head -3
|
||||
echo ''
|
||||
echo '===== [4] /volume1/homes/ ====='
|
||||
ls -la /volume1/homes/ 2>&1 | head -20
|
||||
echo ''
|
||||
echo '===== [5] /volume1/homes/simon/ top dirs by size ====='
|
||||
du -sh /volume1/homes/simon/*/ 2>/dev/null | sort -rh | head -20
|
||||
echo ''
|
||||
echo '===== [6] /volume1/docker/ top dirs by size (likely big) ====='
|
||||
du -sh /volume1/docker/*/ 2>/dev/null | sort -rh | head -20
|
||||
echo ''
|
||||
echo '===== [7] Largest top-level dirs (top 15) ====='
|
||||
du -sh /volume1/* 2>/dev/null | sort -rh | head -15
|
||||
echo ''
|
||||
echo '===== [8] Mounts / storage pools ====='
|
||||
mount | grep -E 'volume|tank' 2>&1 | head -10
|
||||
echo ''
|
||||
echo '===== DONE ====='
|
||||
NAS_EOF
|
||||
"@
|
||||
|
||||
ssh -t simon@100.85.152.112 "$cmd" 2>&1 | Tee-Object -FilePath $outputFile -Encoding UTF8
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "===================================" -ForegroundColor Green
|
||||
Write-Host " Done. Output saved to:" -ForegroundColor Green
|
||||
Write-Host " $outputFile" -ForegroundColor White
|
||||
Write-Host "===================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "Please paste the ENTIRE contents of nas_volumes.txt back" -ForegroundColor Yellow
|
||||
Write-Host "(or just tell me which top-level dir is largest)" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Read-Host "Press Enter to close"
|
||||
@@ -0,0 +1,43 @@
|
||||
# NAS /volume1/ directory listing scan script
|
||||
# Double-click or run in PowerShell, lists all top-level dirs with sizes
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
$outputFile = "$PSScriptRoot\nas_volumes.txt"
|
||||
|
||||
# Force UTF-8 console encoding for SSH output
|
||||
chcp 65001 | Out-Null
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
Write-Host "===================================" -ForegroundColor Cyan
|
||||
Write-Host " NAS /volume1/ Directory Scan" -ForegroundColor Cyan
|
||||
Write-Host "===================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "Scanning... du on large dirs may take 1-3 minutes" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
$cmd = @"
|
||||
echo '===== Top-level dirs in /volume1/ ====='
|
||||
ls -la /volume1/ 2>&1 | grep -v '^total'
|
||||
echo ''
|
||||
echo '===== Size by dir (largest first, may take minutes) ====='
|
||||
du -sh /volume1/*/ 2>/dev/null | sort -rh
|
||||
echo ''
|
||||
echo '===== /volume1/homes/ ====='
|
||||
ls -la /volume1/homes/ 2>/dev/null | head -20
|
||||
echo ''
|
||||
echo '===== /volume1/homes/simon/ content ====='
|
||||
ls -la /volume1/homes/simon/ 2>/dev/null | head -30
|
||||
du -sh /volume1/homes/simon/*/ 2>/dev/null | sort -rh | head -20
|
||||
echo ''
|
||||
echo '===== DONE ====='
|
||||
"@
|
||||
|
||||
ssh simon@100.85.152.112 $cmd 2>&1 | Tee-Object -FilePath $outputFile -Encoding UTF8
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "===================================" -ForegroundColor Green
|
||||
Write-Host " Done. Output saved to:" -ForegroundColor Green
|
||||
Write-Host " $outputFile" -ForegroundColor White
|
||||
Write-Host "===================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Read-Host "Press Enter to close"
|
||||
@@ -0,0 +1,7 @@
|
||||
fp='/opt/wecom-it-desk/nginx/nginx.conf'
|
||||
c=open(fp).read()
|
||||
p='\n # 真实 IP 还原(2026-06-15 v0.5.1)\n set_real_ip_from 10.0.0.0/8;\n set_real_ip_from 172.16.0.0/12;\n set_real_ip_from 192.168.0.0/16;\n set_real_ip_from 10.212.0.0/16;\n real_ip_header X-Forwarded-For;\n real_ip_recursive on;\n'
|
||||
o='error_log /var/log/nginx/error.log warn;'
|
||||
n=c.replace(o,o+p,1)
|
||||
open(fp,'w').write(n)
|
||||
print('patched, +%d bytes'%(len(n)-len(c)))
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
修复 docker-compose.yml 中 REDIS_URL 默认值的 URL-encode 问题。
|
||||
|
||||
背景:
|
||||
- 2026-06-15 故障:REDIS_URL 里的密码 R3d!s@2026#Secure 含 @ # 两个 URL 保留字符,
|
||||
Python redis 库解析时密码被截断成 R3d!s,导致鉴权失败 → Redis 连接超时
|
||||
- 修复:把密码 URL-encode(@→%40, #→%23, !→%21)
|
||||
- ⚠️ 关键: 只 URL-encode REDIS_URL 那行的密码,redis-server --requirepass
|
||||
和 healthcheck 的 redis-cli -a 都必须保持**明文**(否则 Redis 容器启动失败/鉴权失败)
|
||||
|
||||
用法:
|
||||
sudo python3 /tmp/patch-redis-url.py
|
||||
"""
|
||||
fp = '/opt/wecom-it-desk/docker-compose.yml'
|
||||
|
||||
# 读取当前内容
|
||||
with open(fp, encoding='utf-8') as f:
|
||||
c = f.read()
|
||||
|
||||
# 旧值(精确匹配 REDIS_URL 那一行,带 redis://://@ 上下文,避免误改 --requirepass)
|
||||
old = 'REDIS_URL=redis://:${REDIS_PASSWORD:-R3d!s@2026#Secure}@redis:6379/0'
|
||||
|
||||
# 新值:URL-encode 后的密码(!→%21, @→%40, #→%23),仅 REDIS_URL 这一行
|
||||
new = 'REDIS_URL=redis://:${REDIS_PASSWORD:-R3d%21s%402026%23Secure}@redis:6379/0'
|
||||
|
||||
# 检查是否已经修复过(幂等性)
|
||||
if old in c:
|
||||
print('[OK] 检测到未编码版本,准备修复...')
|
||||
c2 = c.replace(old, new, 1) # 只替换第一次出现(更安全)
|
||||
with open(fp, 'w', encoding='utf-8') as f:
|
||||
f.write(c2)
|
||||
delta = len(c2) - len(c)
|
||||
print('[OK] 已修复:REDIS_URL 行的密码已 URL-encode')
|
||||
print(f'[OK] 文件长度变化:{delta:+d} 字节')
|
||||
elif new in c:
|
||||
print('[OK] 已经修复过,跳过(幂等性 OK)')
|
||||
else:
|
||||
print('[ERROR] 既没找到旧值也没找到新值,请人工检查 docker-compose.yml')
|
||||
print('---')
|
||||
print('当前 REDIS_URL 相关配置:')
|
||||
import subprocess
|
||||
result = subprocess.run(['grep', '-n', 'REDIS_URL\\|REDIS_PASSWORD\\|--requirepass\\|redis-cli', fp],
|
||||
capture_output=True, text=True)
|
||||
print(result.stdout)
|
||||
exit(1)
|
||||
|
||||
# 验证:确保 --requirepass 和 redis-cli 仍然是明文(没被误改)
|
||||
import subprocess
|
||||
result = subprocess.run(['grep', '-nE', 'REDIS_URL|--requirepass|redis-cli.*-a', fp],
|
||||
capture_output=True, text=True)
|
||||
print('---')
|
||||
print('当前所有密码相关行(应只有 REDIS_URL 一行是 URL-encoded,其他保持明文):')
|
||||
print(result.stdout)
|
||||
@@ -0,0 +1,20 @@
|
||||
fp = '/opt/wecom-it-desk/nginx/nginx.conf'
|
||||
with open(fp) as f:
|
||||
c = f.read()
|
||||
patch = '''
|
||||
# ------------------------------------------------------------------
|
||||
# 真实 IP 还原(2026-06-15 v0.5.1 修复)
|
||||
# ------------------------------------------------------------------
|
||||
set_real_ip_from 10.0.0.0/8;
|
||||
set_real_ip_from 172.16.0.0/12;
|
||||
set_real_ip_from 192.168.0.0/16;
|
||||
set_real_ip_from 10.212.0.0/16;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
'''
|
||||
old = 'error_log /var/log/nginx/error.log warn;'
|
||||
new = old + patch
|
||||
new_c = c.replace(old, new, 1)
|
||||
with open(fp, 'w') as f:
|
||||
f.write(new_c)
|
||||
print('patched, +{} bytes'.format(len(new_c) - len(c)))
|
||||
@@ -0,0 +1,70 @@
|
||||
# NAS probe script (English-only, prevents PowerShell 5.1 GBK encoding issue)
|
||||
# Output saved to nas_probe_output.txt
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
$outputFile = "$PSScriptRoot\nas_probe_output.txt"
|
||||
|
||||
chcp 65001 | Out-Null
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
Write-Host "===================================" -ForegroundColor Cyan
|
||||
Write-Host " NAS Probe Script" -ForegroundColor Cyan
|
||||
Write-Host "===================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "Connecting via Tailscale: simon@100.85.152.112" -ForegroundColor Yellow
|
||||
Write-Host "Read-only probe, output saved to:" -ForegroundColor Yellow
|
||||
Write-Host " $outputFile" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "SSH will prompt for the simon user password..." -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
$cmd = @"
|
||||
echo '===== [1] DSM Version ====='
|
||||
cat /etc.defaults/VERSION 2>/dev/null | head -10
|
||||
uname -a
|
||||
echo ''
|
||||
echo '===== [2] Docker availability ====='
|
||||
which docker && docker --version
|
||||
ls /var/packages/ContainerManager/target/usr/bin/docker 2>/dev/null
|
||||
/var/packages/ContainerManager/target/usr/bin/docker --version 2>&1
|
||||
echo ''
|
||||
echo '===== [3] All containers (running + stopped) ====='
|
||||
/var/packages/ContainerManager/target/usr/bin/docker ps -a --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}' 2>&1 | head -40
|
||||
echo ''
|
||||
echo '===== [4] /volume1/docker structure ====='
|
||||
ls -la /volume1/docker/ 2>&1 | head -40
|
||||
echo '--- sub-dir sizes ---'
|
||||
du -sh /volume1/docker/*/ 2>/dev/null | head -30
|
||||
echo ''
|
||||
echo '===== [5] Listening ports (22/80/443/3000/3022/18080) ====='
|
||||
ss -tln 2>&1 | head -30
|
||||
echo ''
|
||||
echo '===== [6] Tailscale ====='
|
||||
ls /var/packages/Tailscale/target/bin/ 2>/dev/null
|
||||
/var/packages/Tailscale/target/bin/tailscale status 2>/dev/null | head -10
|
||||
echo ''
|
||||
echo '===== [7] Existing Gitea ====='
|
||||
/var/packages/ContainerManager/target/usr/bin/docker ps -a | grep -i gitea
|
||||
ls -la /volume1/docker/gitea 2>&1 | head -10
|
||||
echo ''
|
||||
echo '===== [8] Disk space ====='
|
||||
df -h /volume1 2>&1 | head -3
|
||||
echo ''
|
||||
echo '===== [9] User and permissions ====='
|
||||
id
|
||||
echo ''
|
||||
echo '===== [10] Installed packages ====='
|
||||
ls /var/packages/ 2>/dev/null | grep -iE 'docker|container|tail|portain'
|
||||
echo ''
|
||||
echo '===== DONE ====='
|
||||
"@
|
||||
|
||||
ssh simon@100.85.152.112 $cmd 2>&1 | Tee-Object -FilePath $outputFile -Encoding UTF8
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "===================================" -ForegroundColor Green
|
||||
Write-Host " Done. Output saved to:" -ForegroundColor Green
|
||||
Write-Host " $outputFile" -ForegroundColor White
|
||||
Write-Host "===================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Read-Host "Press Enter to close"
|
||||
@@ -0,0 +1,78 @@
|
||||
cat > /tmp/gitea-stage1.sh <<'NAS_EOF'
|
||||
#!/bin/bash
|
||||
set +e # don't bail on error, collect everything
|
||||
|
||||
DOCKER=/var/packages/ContainerManager/target/usr/bin/docker
|
||||
|
||||
echo '===== [1] Disk space ====='
|
||||
df -h /volume1
|
||||
|
||||
echo ''
|
||||
echo '===== [2] Docker version ====='
|
||||
$DOCKER --version 2>&1
|
||||
$DOCKER info 2>&1 | head -20
|
||||
|
||||
echo ''
|
||||
echo '===== [3] Existing containers (running + stopped) ====='
|
||||
$DOCKER ps -a --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}' 2>&1
|
||||
|
||||
echo ''
|
||||
echo '===== [4] Existing images (gitea-related highlighted) ====='
|
||||
$DOCKER images --format 'table {{.Repository}}\t{{.Tag}}\t{{.Size}}' 2>&1
|
||||
echo '--- gitea images only ---'
|
||||
$DOCKER images 2>&1 | grep -i gitea
|
||||
|
||||
echo ''
|
||||
echo '===== [5] /volume1/docker structure (top-level) ====='
|
||||
ls -la /volume1/docker/ 2>&1 | head -30
|
||||
echo '--- sub-dir sizes (top 20) ---'
|
||||
sudo du -sh /volume1/docker/*/ 2>/dev/null | sort -rh | head -20
|
||||
|
||||
echo ''
|
||||
echo '===== [6] /volume1/docker/gitea exists? ====='
|
||||
ls -la /volume1/docker/gitea 2>&1
|
||||
|
||||
echo ''
|
||||
echo '===== [7] Listening ports (3000/2222 must be free) ====='
|
||||
ss -tln 2>&1 | grep -E ':3000|:2222|:80|:443' || echo '(none of 3000/2222/80/443 in use)'
|
||||
|
||||
echo ''
|
||||
echo '===== [8] Tailscale ====='
|
||||
/var/packages/Tailscale/target/bin/tailscale status 2>&1 | head -10
|
||||
ip -4 addr show tailscale0 2>&1 | grep inet
|
||||
|
||||
echo ''
|
||||
echo '===== [9] Docker daemon registry config ====='
|
||||
cat /var/packages/ContainerManager/etc/docker/daemon.json 2>&1
|
||||
|
||||
echo ''
|
||||
echo '===== [10] Test Docker Hub reachability ====='
|
||||
curl -s -o /dev/null -w 'docker.io: HTTP %{http_code}, time %{time_total}s\n' \
|
||||
--max-time 8 https://registry-1.docker.io/v2/ 2>&1
|
||||
curl -s -o /dev/null -w 'gcr.io: HTTP %{http_code}, time %{time_total}s\n' \
|
||||
--max-time 8 https://gcr.io/v2/ 2>&1
|
||||
curl -s -o /dev/null -w 'tencentyun mirror: HTTP %{http_code}, time %{time_total}s\n' \
|
||||
--max-time 8 https://mirror.ccs.tencentyun.com/v2/ 2>&1
|
||||
|
||||
echo ''
|
||||
echo '===== [11] User & groups (is simon in docker group?) ====='
|
||||
id
|
||||
groups
|
||||
|
||||
echo ''
|
||||
echo '===== [12] CPU / memory ====='
|
||||
free -h
|
||||
nproc
|
||||
|
||||
echo ''
|
||||
echo '===== STAGE 1 DONE ====='
|
||||
NAS_EOF
|
||||
|
||||
chmod +x /tmp/gitea-stage1.sh
|
||||
echo '=== SCRIPT WRITTEN: /tmp/gitea-stage1.sh ==='
|
||||
echo '=== Press ENTER to execute (sudo will prompt for password) ==='
|
||||
read
|
||||
sudo bash /tmp/gitea-stage1.sh 2>&1 | tee /tmp/gitea-stage1.log
|
||||
echo ''
|
||||
echo '=== LOG SAVED: /tmp/gitea-stage1.log ==='
|
||||
echo '=== Paste the entire output above back to Claude ==='
|
||||
Reference in New Issue
Block a user