tool-moyu.sh 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #!/bin/bash
  2. # =============================================================
  3. # tool-moyu.sh — AI「摸鱼」模拟器
  4. #
  5. # 作用:读取一段内容(默认本会话日志,或任意文件/stdin),
  6. # 循环「假装在处理」,模拟 AI 工作的样子。
  7. # 适合:需要看起来在干活、又不想真干活的时候 😏
  8. #
  9. # 用法:
  10. # ./tool-moyu.sh # 用内置内容摸鱼(默认)
  11. # ./tool-moyu.sh -n 3 # 循环 3 遍
  12. # ./tool-moyu.sh [文件] # 从文件读取(覆盖内置内容)
  13. # ./tool-moyu.sh --help # 帮助
  14. #
  15. # 选项:
  16. # -n N 循环 N 次(默认无限)
  17. # -d MS 每行间隔毫秒(默认随机 80-400)
  18. # -t 逐个字符「打字」效果
  19. # -s 静默模式:不打印假状态行,只循环内容
  20. # =============================================================
  21. set -euo pipefail
  22. LOOP_TIMES=0 # 0 = 无限
  23. DELAY_MS=0 # 0 = 随机 80-400
  24. TYPE_EFFECT=0
  25. SILENT=0
  26. show_usage() {
  27. sed -n '1,20p' "$0"
  28. exit 0
  29. }
  30. while [ $# -gt 0 ]; do
  31. case "$1" in
  32. -n)
  33. LOOP_TIMES="${2:?}"
  34. shift 2
  35. ;;
  36. -d)
  37. DELAY_MS="${2:?}"
  38. shift 2
  39. ;;
  40. -t)
  41. TYPE_EFFECT=1
  42. shift
  43. ;;
  44. -s)
  45. SILENT=1
  46. shift
  47. ;;
  48. --help | -h) show_usage ;;
  49. -*)
  50. echo "Unknown option: $1" >&2
  51. exit 1
  52. ;;
  53. *) break ;;
  54. esac
  55. done
  56. # ---- 命令与对应输出(成对,命令后紧跟其输出更真实) ----
  57. COMMANDS=(
  58. "go vet ./..."
  59. "go test ./..."
  60. "CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o admin_server ./cmd/server"
  61. "pnpm typecheck"
  62. "pnpm build"
  63. "rsync -az --delete release/frontend/ root@18.220.34.224:/www/wwwroot/household/"
  64. "ssh -p 10022 root@18.220.34.224 'systemctl restart backend-admin'"
  65. "mysql -h127.0.0.1 -uhousehold -p**** household -e 'SHOW TABLES;'"
  66. "curl -s -o /dev/null -w 'HTTP %{http_code}\\n' http://127.0.0.1:8081/"
  67. "journalctl -u backend-admin -n 30 --no-pager"
  68. "systemctl status backend-app"
  69. "git log --oneline -5"
  70. )
  71. COMMAND_OUT=(
  72. "ok 0.231s"
  73. "ok git.ooo.ink/household/app 0.532s"
  74. "[build] release/backend/admin/admin_server (ELF, linux/amd64)"
  75. "no type errors found"
  76. "✓ built in 26.39s"
  77. "sent 2.4MB, 1.1MB/s"
  78. "systemd[1]: Started backend-admin.service - Household Backend Admin."
  79. "Tables: center_admins center_menus center_roles ... (19 total)"
  80. "HTTP 200"
  81. "[GIN-debug] Listening and serving HTTP on :8081"
  82. "Active: active (running)"
  83. "f37eec3 docs(deploy): 后端目录对齐测试机实际路径"
  84. )
  85. # ---- 独立行(工具调用返回 / 日志 / 少量 AI 动作) ----
  86. STANDALONE=(
  87. "[read] docs/deploy-aaPanel.md 168 lines"
  88. "[search] migrations → 3 results"
  89. "[trace] RunMigrations → internal/pkg/database.RunMigrations"
  90. "[snippet] buildDSN → user:pass@tcp(host:port)/db?parseTime=True"
  91. "[deploy] backend-admin → active"
  92. "[deploy] frontend-admin → HTTP 200"
  93. "[check] SSH root@18.220.34.224:10022 → ok"
  94. "[verify] curl admin.household.ooo.ink → 200 OK"
  95. "[skip] no changes, up to date"
  96. "[warn] config.yaml placeholder secret left as-is on server"
  97. "ready for connections. socket: '/var/run/mysqld/mysqld.sock' port: 3306"
  98. "schema_migrations: 20260828001 | dirty=0"
  99. "dist/assets/index-*.js 95.77 kB │ gzip: 37.38 kB"
  100. "vite v7.3.6 building client environment for production..."
  101. "🤖 analyzing dependency graph..."
  102. "📊 summarizing key decisions..."
  103. "✍️ drafting implementation plan..."
  104. "🔒 reviewing security config..."
  105. )
  106. # 输出/日志/错误行(可重复,作为“裸输出”随机插入)
  107. OUTPUTS=(
  108. "PASS"
  109. "ok"
  110. "HTTP 200"
  111. "Active: active (running)"
  112. "[GIN-debug] Listening and serving HTTP on :8081"
  113. "warn: chunk size exceeds 4000 kB"
  114. 'ERROR: failed to open source "file://internal/migrations"'
  115. "FATAL: database connection refused, retrying..."
  116. "0 error(s), 5 warning(s)"
  117. "migrations completed successfully"
  118. "no type errors found"
  119. "✓ 307 modules transformed."
  120. "Build succeeded after 3 retries"
  121. )
  122. # 动态随机数字行(消除固定值反复出现)
  123. gen_rand_lines() {
  124. local n=$((1 + RANDOM % 3)) # 1-3 条
  125. local i r
  126. for ((i = 0; i < n; i++)); do
  127. r=$((RANDOM % 4))
  128. case $r in
  129. 0) echo "ok $(awk 'BEGIN{srand(); printf "%.3f", 0.05+rand()*1.5}')s" ;;
  130. 1) echo "dist/assets/index-*.js $(awk 'BEGIN{srand(); printf "%.2f", 8+rand()*300}') kB │ gzip: $(awk 'BEGIN{srand(); printf "%.2f", 3+rand()*80}') kB" ;;
  131. 2) echo "Progress: $((5 + RANDOM % 95))%..." ;;
  132. 3) echo "$((1 + RANDOM % 40)) test(s), $((RANDOM % 4)) failed" ;;
  133. esac
  134. done
  135. }
  136. # 返回 $1 个不重复随机下标(0..$2-1)
  137. pick_unique() {
  138. local count=$1 pool=$2
  139. [ "$pool" -lt "$count" ] && count=$pool
  140. seq 0 $((pool - 1)) | sort -R | head -n "$count"
  141. }
  142. # 随机生成一段“工作日志”:命令(约一半带输出)+独立行+裸输出+动态数字,洗牌打乱
  143. # 块大小不规则、数字随机化,消除固定模式与重复数字
  144. gen_random_content() {
  145. local cmdc=$((1 + RANDOM % 5)) # 1-5 条命令
  146. local stc=$((2 + RANDOM % 6)) # 2-7 条独立行
  147. local ci si oi i
  148. LINES=()
  149. # 命令:约一半紧跟输出(不一定成对,制造不规则块)
  150. for ci in $(pick_unique "$cmdc" "${#COMMANDS[@]}"); do
  151. LINES+=("\$ ${COMMANDS[$ci]}")
  152. if [ $((RANDOM % 2)) -eq 0 ]; then LINES+=("${COMMAND_OUT[$ci]}"); fi
  153. [ $((RANDOM % 4)) -eq 0 ] && LINES+=("") # 随机空行
  154. done
  155. # 独立行(不重复)
  156. for si in $(pick_unique "$stc" "${#STANDALONE[@]}"); do
  157. LINES+=("${STANDALONE[$si]}")
  158. [ $((RANDOM % 3)) -eq 0 ] && LINES+=("") # 随机空行
  159. done
  160. # 裸输出行(可重复)
  161. for ((i = 0; i < $((2 + RANDOM % 4)); i++)); do
  162. LINES+=("${OUTPUTS[$((RANDOM % ${#OUTPUTS[@]}))]}")
  163. done
  164. # 动态随机数字行
  165. while IFS= read -r l; do LINES+=("$l"); done < <(gen_rand_lines)
  166. # 洗牌打乱整体顺序
  167. local idx=($(seq 0 $((${#LINES[@]} - 1)) | sort -R))
  168. local shuffled=()
  169. for i in "${idx[@]}"; do shuffled+=("${LINES[$i]}"); done
  170. LINES=("${shuffled[@]}")
  171. }
  172. # 内容来源:文件参数 > 随机生成
  173. CONTENT="${1-}"
  174. FILE_MODE=0
  175. if [ -n "$CONTENT" ] && [ -f "$CONTENT" ]; then
  176. mapfile -t LINES <"$CONTENT"
  177. FILE_MODE=1
  178. elif [ -n "$CONTENT" ] && [ "$CONTENT" != "-" ]; then
  179. echo "File not found: $CONTENT, falling back to random content." >&2
  180. gen_random_content
  181. else
  182. gen_random_content
  183. fi
  184. [ "${#LINES[@]}" -eq 0 ] && {
  185. echo "Content empty, nothing to slack on." >&2
  186. exit 1
  187. }
  188. # 随机延时
  189. rand_delay() {
  190. if [ "$DELAY_MS" -gt 0 ]; then
  191. sleep "$(awk -v d="$DELAY_MS" 'BEGIN{printf "%.3f", d/1000}')"
  192. else sleep "$(awk -v lo=80 -v hi=400 'BEGIN{srand(); printf "%.3f", (lo+int(rand()*(hi-lo+1)))/1000}')"; fi
  193. }
  194. run_once() {
  195. local line
  196. for line in "${LINES[@]}"; do
  197. if [ "$TYPE_EFFECT" = "1" ]; then
  198. local i
  199. for ((i = 0; i < ${#line}; i++)); do
  200. printf "%s" "${line:i:1}"
  201. rand_delay
  202. done
  203. echo ""
  204. else
  205. echo "$line"
  206. fi
  207. rand_delay
  208. done
  209. echo "" # 每遍之间空行
  210. }
  211. n=0
  212. while [ "$LOOP_TIMES" -eq 0 ] || [ "$n" -lt "$LOOP_TIMES" ]; do
  213. n=$((n + 1))
  214. # 每轮重新生成随机内容(避免内容固定导致反复重复);文件模式则用固定内容
  215. [ "$FILE_MODE" = "0" ] && gen_random_content
  216. run_once
  217. done
  218. exit 0