From f156371f684afd7ab6fee7be2de235220762a4e9 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 12 十月 2026 19:44:36 +0800
Subject: [PATCH] feat: 新增 JHHG.sh —— 九鸿化工前端部署脚本的 macOS 版
---
JHHG.sh | 467 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 467 insertions(+), 0 deletions(-)
diff --git a/JHHG.sh b/JHHG.sh
new file mode 100755
index 0000000..d212f9c
--- /dev/null
+++ b/JHHG.sh
@@ -0,0 +1,467 @@
+#!/usr/bin/env bash
+# ============================================================================
+# Vue 鍓嶇閮ㄧ讲鑴氭湰锛坢acOS / Linux 鐗堬級鈥斺�� 閾跺窛涔濋缚鍖栧伐锛圝HHG锛�
+#
+# 鐢卞悓鐩綍鐨� JHHG.bat 杞啓鑰屾潵锛氭楠ゃ�佹彁绀鸿銆佹湇鍔″櫒銆佽处鍙枫�佽繙绔洰褰曘��
+# 瓒呮椂鍙傛暟涓� .bat 瀹屽叏涓�鑷达紝Windows 涓婃�庝箞鐢紝杩欓噷灏辨�庝箞鐢ㄣ��
+#
+# 涓� .bat 鐨勫叏閮ㄥ樊鍒細
+# 1. 涓嶄緷璧� sshpass.exe銆傜郴缁熼噷鏈� sshpass 灏辩敤 sshpass锛屾病鏈夊氨閫�鍥� macOS
+# 鑷甫鐨� /usr/bin/expect 鏉ュ杺瀵嗙爜 鈥斺�� 鎵�浠ヨ繖鍙� Mac 涓嶇敤瑁呬换浣曚笢瑗夸篃鑳借窇銆�
+# 2. 鑴氭湰寮�澶翠細 cd 鍒拌嚜宸辨墍鍦ㄧ洰褰曪紝浠庝换浣曚綅缃皟鐢ㄩ兘鑳芥纭瀯寤哄拰涓婁紶銆�
+# 3. 缁撳熬鐨� pause 鍙湪浜や簰寮忕粓绔噷鐢熸晥锛岃鍏跺畠鑴氭湰/绠¢亾璋冪敤鏃朵笉浼氬崱浣忋��
+# 4. 銆屾瘮杈冩枃浠跺ぇ灏忋�嶈繖涓�姝ユ寜鏍囬鐨勫師鎰忕湡姝e仛浜嗘瘮瀵癸紙.bat 鍙墦鍗颁笉姣斿锛夛紝
+# 澶у皬涓嶄竴鑷寸洿鎺ユ姤閿欙紝閬垮厤鎶婁竴涓笂浼犳畫缂虹殑鍖呰В鍘嬪埌绾夸笂鐩綍銆�
+#
+# 鐢ㄦ硶锛�
+# ./JHHG.sh # 棣栨鍙兘闇�瑕� chmod +x JHHG.sh
+# bash JHHG.sh
+#
+# 鍙�夌幆澧冨彉閲忥紙涓�鑸敤涓嶅埌锛夛細
+# JHHG_TRANSPORT=sshpass|expect 寮哄埗鎸囧畾鍠傚瘑鐮佺殑鏂瑰紡
+# ============================================================================
+
+set -uo pipefail
+
+# =========================
+# 閰嶇疆锛堜笌 JHHG.bat 涓�瀛椾笉宸級
+# =========================
+
+readonly COMPANY='JHHG'
+readonly REMOTE_USER='root'
+readonly REMOTE_HOST='42.63.70.90'
+readonly REMOTE_PORT='22'
+# 瀵嗙爜鍚� ! 鍜� #锛氬繀椤荤敤鍗曞紩鍙凤紱涓嶈 source 鍒颁氦浜掑紡 shell 閲岃窇锛堥偅閲屼細鍋� ! 鍘嗗彶灞曞紑锛夛紝
+# 鐢� ./JHHG.sh 鎴� bash JHHG.sh 鎵ц銆�
+# 2026-10-12 瀹炴祴杩囷細鏈嶅姟鍣ㄦ帴鍙楃殑灏辨槸杩欎釜瀹屾暣瀛楃涓诧紙鍘绘帀 !@##@! 鐨� Nxjhhg 浼氳鎷掞級銆�
+readonly PASSWORD='Nxjhhg!@##@!'
+readonly ZIP_FILE='dist.zip'
+readonly REMOTE_DIR='/home/vue/dist'
+readonly SSH_OPTS=(-o StrictHostKeyChecking=no -o ConnectTimeout=10 -o ServerAliveInterval=15 -o ServerAliveCountMax=3)
+
+readonly REMOTE_TARGET="${REMOTE_USER}@${REMOTE_HOST}"
+readonly REMOTE_TMP="${REMOTE_DIR}/.dist.zip.uploading"
+
+# 鑴氭湰鑷韩鎵�鍦ㄧ洰褰� = 椤圭洰鏍圭洰褰�
+cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+# =========================
+# 杈撳嚭helper锛堜笌 .bat 鐨勬彁绀烘牸寮忎竴鑷达級
+# =========================
+
+log() { printf '%s\n' "$*"; }
+ok() { printf '[OK] %s\n' "$*"; }
+info() { printf '[INFO] %s\n' "$*"; }
+warn() { printf '[WARN] %s\n' "$*"; }
+err() { printf '[ERROR] %s\n' "$*"; }
+
+# 涓� .bat 鐨� :END 涓�鏍凤紝浜や簰寮忕粓绔噷鍋滀竴涓嬪啀閫�鍑�
+pause_if_interactive() {
+ if [[ -t 0 ]]; then
+ printf '\n鎸夊洖杞﹂敭閫�鍑�...'
+ read -r _ || true
+ printf '\n'
+ fi
+}
+
+fail() {
+ log ''
+ log '============================================================'
+ log ' DEPLOY FAILED'
+ log '============================================================'
+ log ''
+ log 'Please check the error message above.'
+ log ''
+ pause_if_interactive
+ exit 1
+}
+
+# 娌¤鏄惧紡澶勭悊灏卞け璐ョ殑鍛戒护锛屼篃璧板埌 DEPLOY FAILED锛屼笉鐣欏崐鎴緭鍑�
+on_unexpected_error() {
+ err "鍛戒护澶辫触锛堥��鍑虹爜 $1锛岃剼鏈 $2 琛岋級銆�"
+ fail
+}
+
+trap 'on_unexpected_error $? $LINENO' ERR
+
+# =========================
+# 浼犺緭灞傦細鎶婂瘑鐮佸杺缁� ssh/scp
+# =========================
+
+# 浼樺厛 sshpass锛堝拰 .bat 涓�鏍凤級锛屾病鏈夊氨鐢� macOS 鑷甫鐨� expect
+TRANSPORT="${JHHG_TRANSPORT:-}"
+if [[ -z "$TRANSPORT" ]]; then
+ if command -v sshpass >/dev/null 2>&1; then
+ TRANSPORT='sshpass'
+ elif command -v expect >/dev/null 2>&1; then
+ TRANSPORT='expect'
+ fi
+fi
+
+# 鐢ㄥ綋鍓� TRANSPORT 鎵ц涓�鏉� ssh/scp 鍛戒护锛屽弬鏁板師鏍烽�忎紶
+# 瀵嗙爜閫氳繃鐜鍙橀噺浼犻�掞紝涓嶅嚭鐜板湪鍛戒护琛屽弬鏁伴噷锛堜笉浼氳繘 ps 杈撳嚭锛�
+run_remote() {
+ if [[ "$TRANSPORT" == 'sshpass' ]]; then
+ SSHPASS="$PASSWORD" sshpass -e "$@"
+ return $?
+ fi
+ # expect 鍒嗘敮锛氱▼搴忓繀椤诲啓鎴愭枃浠跺啀鐢� -f 璋冪敤锛屽洜涓� `expect -c 鑴氭湰 鍙傛暟...`
+ # 涓嶄細鎶婂弬鏁版斁杩� $argv锛堜細鎶婂畠褰撹剼鏈枃浠跺悕锛夈��
+ local exp_file rc
+ exp_file="$(mktemp "${TMPDIR:-/tmp}/jhhg-deploy.XXXXXX")" || {
+ err 'temp file creation failed.'
+ return 1
+ }
+ cat >"$exp_file" <<'EXPECT_PROGRAM'
+set timeout 300
+log_user 1
+if {[catch {spawn {*}$argv} spawn_err]} {
+ puts stderr "spawn failed: $spawn_err"
+ exit 127
+}
+expect {
+ -re "(?i)are you sure you want to continue connecting" { send "yes\r"; exp_continue }
+ -re "(?i)password:" { send "$env(JHHG_PW)\r"; exp_continue }
+ eof
+}
+# 鎶婂瓙杩涚▼鐨勯��鍑虹爜鍘熸牱甯﹀嚭鍘伙紙瀵嗙爜閿欐椂 ssh 杩斿洖 255锛屽繀椤昏涓婂眰鎰熺煡鍒帮級
+set wait_result {}
+catch wait wait_result
+set rc [lindex $wait_result 3]
+if {![string is integer -strict $rc]} { set rc 1 }
+exit $rc
+EXPECT_PROGRAM
+ JHHG_PW="$PASSWORD" expect -f "$exp_file" "$@"
+ rc=$?
+ rm -f "$exp_file"
+ return $rc
+}
+
+ssh_remote() { # ssh_remote "杩滅鍛戒护"
+ run_remote ssh -p "$REMOTE_PORT" "${SSH_OPTS[@]}" "$REMOTE_TARGET" "$1"
+}
+
+scp_up() { # scp_up 鏈湴鏂囦欢 杩滅璺緞
+ run_remote scp -P "$REMOTE_PORT" "${SSH_OPTS[@]}" "$1" "${REMOTE_TARGET}:$2"
+}
+
+# =========================
+# 寮�濮�
+# =========================
+
+log ''
+log '============================================================'
+log ' Vue Dist Auto Deploy'
+log '============================================================'
+log ''
+log "Company : $COMPANY"
+log "Server : $REMOTE_USER@$REMOTE_HOST"
+log "Port : $REMOTE_PORT"
+log "Remote Dir : $REMOTE_DIR"
+log "Package : $ZIP_FILE"
+log ''
+
+# =========================
+# [1/7] 瀵嗙爜宸ュ叿
+# =========================
+
+log '[1/7] Checking password tool...'
+
+if [[ -z "$TRANSPORT" ]]; then
+ err 'sshpass 鍜� expect 閮芥病鏈夛紝鏃犳硶鑷姩杈撳叆瀵嗙爜銆�'
+ info 'macOS 涓�鑸嚜甯� /usr/bin/expect锛屾甯镐笉浼氳蛋鍒拌繖閲岋紱'
+ info '濡傛灉纭疄娌℃湁锛岃 sshpass 鍗冲彲锛堝彲鑳介渶鍏堝姞绗笁鏂� tap锛夛細brew install sshpass'
+ info 'Linux: apt install sshpass / yum install sshpass'
+ fail
+fi
+
+if [[ "$TRANSPORT" == 'sshpass' ]]; then
+ ok "sshpass found: $(command -v sshpass)"
+else
+ ok "expect found: $(command -v expect)锛坢acOS 鑷甫锛屾棤闇�瀹夎 sshpass锛�"
+fi
+
+# =========================
+# [2/7] pnpm
+# =========================
+
+log ''
+log '[2/7] Checking pnpm...'
+
+if ! command -v pnpm >/dev/null 2>&1; then
+ err 'pnpm not found.'
+ info 'HINT: npm install -g pnpm'
+ fail
+fi
+
+if ! pnpm --version; then
+ err 'pnpm execution failed.'
+ fail
+fi
+
+# =========================
+# [3/7] node
+# =========================
+
+log ''
+log '[3/7] Checking Node.js...'
+
+if ! command -v node >/dev/null 2>&1; then
+ err 'Node.js not found.'
+ fail
+fi
+
+if ! node --version; then
+ err 'Node.js execution failed.'
+ fail
+fi
+
+# =========================
+# node_modules
+# =========================
+
+if [[ ! -d node_modules ]]; then
+ log ''
+ info 'node_modules not found.'
+ info 'Running pnpm install...'
+ if ! pnpm install; then
+ err 'pnpm install failed.'
+ fail
+ fi
+ ok 'pnpm install completed.'
+else
+ ok 'node_modules exists.'
+fi
+
+# =========================
+# [4/7] 鏋勫缓
+# =========================
+
+log ''
+log '[4/7] Building project...'
+
+SKIP_BUILD=''
+if [[ -f "$ZIP_FILE" ]]; then
+ log ''
+ warn "$ZIP_FILE already exists."
+ printf 'Rebuild? Y/N (default Y): '
+ read -r REBUILD_ANSWER || true
+ case "$(printf '%s' "${REBUILD_ANSWER:-}" | tr '[:lower:]' '[:upper:]')" in
+ N) info 'Skip build.'; SKIP_BUILD='1' ;;
+ esac
+fi
+
+if [[ -z "$SKIP_BUILD" ]]; then
+ info "Company: $COMPANY"
+ info 'Command: pnpm run build'
+ log ''
+ export VITE_COMPANY="$COMPANY"
+ if ! pnpm run build; then
+ log ''
+ err 'Build failed.'
+ fail
+ fi
+ log ''
+ ok 'Build completed.'
+fi
+
+# =========================
+# [5/7] 妫�鏌ュ寘
+# =========================
+
+log ''
+log '[5/7] Checking package...'
+
+if [[ ! -f "$ZIP_FILE" ]]; then
+ err "$ZIP_FILE not found."
+ info 'HINT: Please check whether your build generates dist.zip.'
+ fail
+fi
+
+LOCAL_ZIP_BYTES="$(wc -c < "$ZIP_FILE" | tr -d ' ')"
+LOCAL_ZIP_MB="$(awk -v b="$LOCAL_ZIP_BYTES" 'BEGIN { printf "%.2f", b / 1048576 }')"
+
+ok 'Package found.'
+info "File size: $LOCAL_ZIP_BYTES bytes"
+info "File size: $LOCAL_ZIP_MB MB"
+
+# =========================
+# [6/7] 娴嬭瘯 SSH
+# =========================
+
+log ''
+log '[6/7] Testing SSH connection...'
+
+if ! ssh_remote 'echo SSH_OK'; then
+ err 'SSH connection failed.'
+ fail
+fi
+
+ok 'SSH connection successful.'
+
+# =========================
+# 寤鸿繙绔洰褰�
+# =========================
+
+log ''
+info 'Creating remote directory...'
+
+if ! ssh_remote "mkdir -p '$REMOTE_DIR'"; then
+ err 'Failed to create remote directory.'
+ fail
+fi
+
+ok 'Remote directory ready.'
+
+# =========================
+# 涓婁紶涓存椂鏂囦欢
+# =========================
+
+log ''
+info 'Uploading package...'
+
+ssh_remote "rm -f '$REMOTE_TMP'" || true
+
+# 杩滅璺緞涓嶈兘鍔犲紩鍙凤細ssh 閭f潯鐨勫崟寮曞彿鏄粰杩滅 shell 鍓ョ殑锛岃�� scp 鐨勫弬鏁颁笉缁� shell锛�
+# 鍗曞紩鍙蜂細鍙樻垚鏂囦欢鍚嶇殑鐪熷疄瀛楃锛堣繙绔細鍘诲紑 "'/home/vue/dist/..." 杩欎釜鐩稿璺緞锛�
+if ! scp_up "$ZIP_FILE" "$REMOTE_TMP"; then
+ err 'Upload failed.'
+ fail
+fi
+
+ok 'Upload completed.'
+
+# =========================
+# 鏍¢獙杩滅鏂囦欢
+# =========================
+
+log ''
+info 'Checking remote package...'
+
+if ! ssh_remote "test -f '$REMOTE_TMP'"; then
+ err 'Remote package does not exist.'
+ fail
+fi
+
+ok 'Remote package exists.'
+
+# =========================
+# 姣旇緝鏂囦欢澶у皬
+# =========================
+
+log ''
+info 'Checking package size...'
+log ''
+
+# 澶у皬姣斿鏀惧湪杩滅鍋氥�佸彧鍙栭��鍑虹爜銆�
+# 涓嶈鐢� $(run_remote ...) 鍘绘埅鍙栬繙绔緭鍑猴細expect 浼氭妸鏁存浜や簰鍥炴樉锛坰pawn 鍛戒护琛屻��
+# 瀵嗙爜鎻愮ず锛変竴璧峰啓杩� stdout锛屾埅鍑烘潵鐨勪笉鏄懡浠ょ粨鏋滐紝姣斿蹇呯劧澶辫触銆�
+if ! ssh_remote "test \"\$(stat -c %s '$REMOTE_TMP')\" -eq $LOCAL_ZIP_BYTES"; then
+ # 鍙橀噺涓�寰嬪姞 ${}锛歜ash 3.2 浼氭妸绱ц窡鍏跺悗鐨勫叏瑙掑瓧绗︼紙濡傘�岋紙銆嶏級褰撴垚鍙橀噺鍚嶇殑涓�閮ㄥ垎锛�
+ # 浜庢槸 $ZIP_FILE锛� 浼氳瑙f瀽鎴愬悕涓� "ZIP_FILE锛�" 鐨勫彉閲忥紝閰� set -u 鐩存帴鎶� unbound variable
+ err "鍖呭ぇ灏忎笉涓�鑷达細杩滅 ${REMOTE_TMP} 涓庢湰鍦� ${ZIP_FILE}锛�${LOCAL_ZIP_BYTES} 瀛楄妭锛変笉绗︼紝涓婁紶鍙兘琚埅鏂��"
+ info "杩滅涓存椂鏂囦欢宸蹭繚鐣欍�傚彲鍦ㄦ湇鍔″櫒涓婃墽琛� stat -c %s '${REMOTE_TMP}' 鏍稿锛岀‘璁ゅ悗鍒犻櫎銆�"
+ fail
+fi
+
+ok "鍖呭ぇ灏忎竴鑷达細${LOCAL_ZIP_BYTES} 瀛楄妭銆�"
+
+# =========================
+# 鏀瑰悕鐢熸晥
+# =========================
+
+log ''
+info 'Activating package...'
+
+if ! ssh_remote "mv -f '$REMOTE_TMP' '$REMOTE_DIR/$ZIP_FILE'"; then
+ err 'Failed to activate package.'
+ fail
+fi
+
+ok 'Package activated.'
+
+# =========================
+# 妫�鏌� unzip
+# =========================
+
+log ''
+info 'Checking unzip...'
+
+if ! ssh_remote 'command -v unzip'; then
+ err 'unzip is not installed on server.'
+ log ''
+ log 'CentOS/RHEL:'
+ log 'yum install -y unzip'
+ log ''
+ log 'Ubuntu/Debian:'
+ log 'apt install -y unzip'
+ fail
+fi
+
+ok 'unzip found.'
+
+# =========================
+# 娴嬭瘯 ZIP
+# =========================
+
+log ''
+info 'Testing remote ZIP...'
+
+if ! ssh_remote "cd '$REMOTE_DIR' && unzip -t '$ZIP_FILE'"; then
+ log ''
+ err 'ZIP test failed.'
+ info 'Remote ZIP has been kept.'
+ fail
+fi
+
+ok 'ZIP test passed.'
+
+# =========================
+# 瑙e帇
+# =========================
+
+log ''
+info 'Extracting package...'
+
+if ! ssh_remote "cd '$REMOTE_DIR' && unzip -o '$ZIP_FILE'"; then
+ log ''
+ err 'Remote unzip failed.'
+ info 'Remote ZIP has been kept.'
+ fail
+fi
+
+log ''
+ok 'Extract completed.'
+
+# =========================
+# 鍒犻櫎杩滅 ZIP
+# =========================
+
+log ''
+info 'Removing remote ZIP...'
+
+if ssh_remote "rm -f '$REMOTE_DIR/$ZIP_FILE'"; then
+ ok 'Remote ZIP removed.'
+else
+ warn 'Failed to remove remote ZIP.'
+fi
+
+# =========================
+# [7/7] 瀹屾垚
+# =========================
+
+log ''
+log '============================================================'
+log ' DEPLOY SUCCESS'
+log '============================================================'
+log ''
+log "Company : $COMPANY"
+log "Server : $REMOTE_HOST:$REMOTE_PORT"
+log "Remote Dir : $REMOTE_DIR"
+log "Package : $ZIP_FILE"
+log "Size : $LOCAL_ZIP_MB MB"
+log ''
+log 'Deployment completed successfully.'
+log ''
+
+pause_if_interactive
--
Gitblit v1.9.3