diff --git a/cmd/waiter/raw_windows.go b/cmd/waiter/raw_windows.go index f8ddd45..8d2f769 100644 --- a/cmd/waiter/raw_windows.go +++ b/cmd/waiter/raw_windows.go @@ -9,14 +9,14 @@ import ( ) var ( - kernel32 = syscall.NewLazyDLL("kernel32.dll") - procGetConsoleMode = kernel32.NewProc("GetConsoleMode") - procSetConsoleMode = kernel32.NewProc("SetConsoleMode") - procGetStdHandle = kernel32.NewProc("GetStdHandle") + kernel32 = syscall.NewLazyDLL("kernel32.dll") + procGetConsoleMode = kernel32.NewProc("GetConsoleMode") + procSetConsoleMode = kernel32.NewProc("SetConsoleMode") + procGetStdHandle = kernel32.NewProc("GetStdHandle") ) const ( - stdInputHandle = ^uint32(9) + 1 // -10 + stdInputHandle = ^uint32(9) + 1 // -10 enableVirtualTerminalProcessing = 0x0004 enableProcessedOutput = 0x0001 enableWrapAtEOLOutput = 0x0002 diff --git a/deploy-waiter.sh b/deploy-waiter.sh new file mode 100644 index 0000000..2f0aacf --- /dev/null +++ b/deploy-waiter.sh @@ -0,0 +1,136 @@ +#!/bin/bash +# waiter 远程更新(106 / 30) +# +# 现状(更新前): +# 两台都是 8月27日构建的 /opt/waiter/waiter(11,388,177 字节), +# 以 root 跑 waiter-remote.service,配置指向 ws://192.168.2.60:9890/... +# 进程已连续运行 1 天 7.5 小时、无掉线记录 ⇒ 本次是**预防性**更新: +# · 拿到 94c74b2 的设备桥修复(未 bind 时收到 ping 会关连接) +# · 版本对齐到内核 1.4.0(docs/git-branching.md 要求客户端与内核同步) +# +# 安全设计: +# · 先备份旧二进制,失败即回滚(trap 捕获) +# · 只换二进制,**不动** waiter.yaml +# · 逐台更新并验证,**不并行**(两台都连同一网关,同时重启会同时断链) +# · 验证项:进程活着 + 设备在网关侧注册成功 +# +# 用法: +# bash deploy-waiter.sh check 只读检查 +# bash deploy-waiter.sh deploy 更新指定一台 +# bash deploy-waiter.sh rollback 回滚指定一台 + +set -uo pipefail + +NEW=${NEW_WAITER:-/tmp/waiter-new} +SVC=waiter-remote.service +BIN=/opt/waiter/waiter +CFG=/opt/waiter/waiter.yaml + +# 106 用 admin(需 sudo),30 用 root +ssh_of() { + case "$1" in + 192.168.2.106) echo "admin@$1" ;; + 192.168.2.30) echo "root@$1" ;; + *) echo "" ;; + esac +} +sudo_of() { [ "$1" = "192.168.2.106" ] && echo "sudo" || echo ""; } + +say() { printf '\n\033[1m%s\033[0m\n' "$*"; } +info() { printf ' %s\n' "$*"; } + +do_check() { + local ip=$1 t s + t=$(ssh_of "$ip"); [ -z "$t" ] && { info "未知主机: $ip"; return 1; } + s=$(sudo_of "$ip") + info "──── $ip ────" + ssh -o BatchMode=yes -o ConnectTimeout=8 "$t" " + echo -n ' 主机: '; hostname + echo -n ' 当前二进制: '; ls -la $BIN 2>/dev/null | awk '{print \$5\" 字节 \"\$6\" \"\$7\" \"\$8}' + echo -n ' 服务: '; systemctl is-active $SVC 2>/dev/null + echo -n ' 进程时长: '; ps -o etime= -p \$(pgrep -f 'waiter --daemon' | head -1) 2>/dev/null + echo -n ' 配置网关: '; grep -oE 'ws://[^\"]+' $CFG 2>/dev/null | head -1 + echo -n ' 配置校验和: '; md5sum $CFG 2>/dev/null | cut -c1-32 + " 2>&1 + info " 新二进制: $NEW ($(stat -c %s "$NEW" 2>/dev/null) 字节)" + info " 新版本: $(/tmp/waiter-new --version 2>&1 | head -1)" + return 0 +} + +do_deploy() { + local ip=$1 t s + t=$(ssh_of "$ip"); [ -z "$t" ] && { info "未知主机: $ip"; return 1; } + s=$(sudo_of "$ip") + [ -f "$NEW" ] || { info "新二进制不存在: $NEW"; return 1; } + + say "更新 $ip" + do_check "$ip" + + echo + read -r -p "确认更新 $ip 的 waiter ? 输入 yes 继续: " ans + [ "$ans" = "yes" ] || { info "已取消"; return 1; } + + # 备份 + 停服 + 替换 + 启服;失败即回滚 + scp -q "$NEW" "$t:/tmp/waiter.new" || { info "上传失败"; return 1; } + info "已上传" + + ssh -o BatchMode=yes -o ConnectTimeout=8 "$t" " + set -e + $s cp -a $BIN $BIN.bak-\$(date +%Y%m%d-%H%M%S) + echo BACKUP=\$(ls -t $BIN.bak-* | head -1) + $s systemctl stop $SVC + $s install -m 0755 /tmp/waiter.new $BIN + rm -f /tmp/waiter.new + $s systemctl start $SVC + " 2>&1 | tail -3 + info "已替换并启动" + + sleep 8 + say "更新后验证 $ip" + local alive=false + for i in 1 2 3 4 5; do + if ssh -o BatchMode=yes -o ConnectTimeout=8 "$t" "systemctl is-active --quiet $SVC" 2>/dev/null; then + alive=true; break + fi + sleep 3 + done + if [ "$alive" = true ]; then + info "✓ 服务 active" + ssh -o BatchMode=yes -o ConnectTimeout=8 "$t" " + echo -n ' 新二进制: '; ls -la $BIN | awk '{print \$5\" 字节\"}' + echo -n ' 进程时长: '; ps -o etime= -p \$(pgrep -f 'waiter --daemon' | head -1) 2>/dev/null + echo -n ' 配置未变: '; md5sum $CFG | cut -c1-32 + " 2>&1 + info "★ 请在网关侧确认设备已重新注册(/kernel 的 channels 应出现 device/)" + else + info "✗ 服务未起来 —— 回滚" + do_rollback "$ip" + return 1 + fi +} + +do_rollback() { + local ip=$1 t s + t=$(ssh_of "$ip"); s=$(sudo_of "$ip") + say "回滚 $ip" + ssh -o BatchMode=yes -o ConnectTimeout=8 "$t" " + set -e + BAK=\$(ls -t $BIN.bak-* 2>/dev/null | head -1) + [ -n \"\$BAK\" ] || { echo '找不到备份'; exit 1; } + $s systemctl stop $SVC + $s install -m 0755 \"\$BAK\" $BIN + $s systemctl start $SVC + echo \"已回滚到 \$BAK\" + " 2>&1 | tail -2 + sleep 5 + info "服务: $(ssh -o BatchMode=yes "$t" "systemctl is-active $SVC" 2>/dev/null)" +} + +case "${1:-check}" in + check) + for ip in 192.168.2.106 192.168.2.30; do say "检查 $ip"; do_check "$ip"; done + ;; + deploy) do_deploy "${2:?用法: deploy }" ;; + rollback) do_rollback "${2:?用法: rollback }" ;; + *) echo "用法: $0 {check|deploy |rollback }"; exit 2 ;; +esac diff --git a/scripts/kernel-stress/cmp.py b/scripts/kernel-stress/cmp.py index 0e60679..ae9948f 100644 --- a/scripts/kernel-stress/cmp.py +++ b/scripts/kernel-stress/cmp.py @@ -90,13 +90,14 @@ def has_error(frames): def tools_done(frames): - """数出工具真正执行的个数(按 done-N 标记去重)。""" + """ 数出工具真正执行的个数(按 done-N 标记去重)。""" blob = " ".join(frames) return len({int(m.group(1)) for m in re.finditer(r"done-(\d+)", blob)}) # ---------------------------------------------------------------- 单轮测量 + def measure(sock, key, marker, rounds): """连一次、跑 rounds 轮(每轮唯一输入)。 @@ -128,6 +129,7 @@ def measure(sock, key, marker, rounds): # ---------------------------------------------------------------- 并发轰炸 + def blast(sock, key, conns, inputs, tag): """conns 条连接并发,每条连接连发 inputs 条输入。返回通过率。 @@ -175,6 +177,7 @@ def blast(sock, key, conns, inputs, tag): # ---------------------------------------------------------------- 主流程 + def arg_int(pos, default, name): """解析位置参数为正整数;非法时给出可执行报错而不是裸 ValueError。""" if pos >= len(sys.argv):