diff --git a/cleanup-server b/cleanup-server index 2bfaa3e..10ec2da 100755 --- a/cleanup-server +++ b/cleanup-server @@ -2,7 +2,7 @@ # cleanup-server - Dọn dẹp + nâng cấp server (Ubuntu/Arch), interactive, tuần tự. # Cách dùng: # cleanup-server # hiện menu chọn target (local hoặc server alias) -# cleanup-server --run-steps # (nội bộ) chạy thẳng 7 bước trên máy hiện tại +# cleanup-server --run-steps # (nội bộ) chạy thẳng 8 bước trên máy hiện tại # ----------------------------- # Color helpers (tự tắt khi không phải TTY) @@ -187,6 +187,14 @@ step_ai_tools() { local found=0 local -a found_names=() + # Shell này chạy qua ssh non-interactive nên bashrc không được load: + # tự thêm các bin dir thông dụng + nạp nvm để thấy được tool cài qua npm/nvm. + export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$PATH" + if [ -s "$HOME/.nvm/nvm.sh" ]; then + export NVM_DIR="$HOME/.nvm" + . "$NVM_DIR/nvm.sh" >/dev/null 2>&1 + fi + if command -v claude >/dev/null 2>&1; then found=1; found_names+=("claude") echo " ${C_OK}✓ claude: $(claude --version 2>/dev/null | head -1)${C_RESET}" @@ -377,7 +385,66 @@ step_snap() { } # ----------------------------- -# Bước 6: /tmp & cache cũ — liệt kê file >7 ngày, xác nhận rồi xóa +# Bước 7: Chrome headless mồ côi — kill browser Playwright sót lại (PPID=1) +# rồi xóa profile /tmp của chúng +# ----------------------------- +step_orphan_chrome() { + step_header "Orphan Chrome" + # Process mồ côi được nhận nuôi bởi init (PPID=1) hoặc systemd --user + # của từng user — driver (node/playwright) đã chết, browser bị bỏ quên. + # Browser còn cha đang sống thì KHÔNG đụng. + local adopters out + adopters=$(ps -eo pid=,args= 2>/dev/null | awk '/systemd --user/ {print $1}') + out=$(ps -eo pid=,ppid=,user=,etimes=,args= 2>/dev/null | awk -v ok="1 $adopters" ' + BEGIN { n = split(ok, a, " "); for (i = 1; i <= n; i++) adopt[a[i]] = 1 } + !($2 in adopt) { next } + $5 ~ /\/headless_shell$/ { print; next } + /--headless/ && $5 ~ /\/(chrome|chromium|chromium-browser)$/ { print } + ') + if [ -z "$out" ]; then + echo "${C_OK} ✓ Không có chrome headless mồ côi.${C_RESET}" + echo "" + return + fi + echo " ${C_WARN}⚠ Chrome headless mồ côi (PPID=1):${C_RESET}" + local pids="" dirs="" pid ppid user etimes args age_d age_h dir + while read -r pid ppid user etimes args; do + [ -z "$pid" ] && continue + age_d=$(( etimes / 86400 )); age_h=$(( (etimes % 86400) / 3600 )) + echo " ${C_DEL}- pid $pid ($user, sống ${age_d}d${age_h}h): ${args%% --*}${C_RESET}" + pids="$pids $pid" + dir=$(printf '%s\n' "$args" | sed -n 's/.*--user-data-dir=\([^ ]*\).*/\1/p') + # chỉ nhận profile dir dưới /tmp + case "$dir" in /tmp/*) [ -d "$dir" ] && dirs="$dirs $dir" ;; esac + done <<< "$out" + dirs=$(printf '%s\n' $dirs | sed '/^$/d' | sort -u | tr '\n' ' ') + local killed=0 + if confirm_yn "Kill $(wc -w <<< "$pids" | tr -d ' ') process?"; then + killed=1 + sudo kill $pids 2>/dev/null + sleep 2 + sudo kill -9 $pids 2>/dev/null + # crashpad_handler mồ côi đi kèm + ps -eo pid=,ppid=,args= 2>/dev/null | awk -v ok="1 $adopters" ' + BEGIN { n = split(ok, a, " "); for (i = 1; i <= n; i++) adopt[a[i]] = 1 } + ($2 in adopt) && $3 ~ /crashpad/ {print $1}' | xargs -r sudo kill 2>/dev/null + echo "${C_OK} ✓ Đã kill.${C_RESET}" + fi + if [ "$killed" -eq 1 ] && [ -n "${dirs// /}" ]; then + echo " Profile /tmp của browser trên:" + for dir in $dirs; do + echo " ${C_DEL}- $dir${C_RESET}" + done + if confirm_yn "Xóa các profile dir này?"; then + sudo rm -rf -- $dirs + echo "${C_OK} ✓ Đã xóa profile.${C_RESET}" + fi + fi + echo "" +} + +# ----------------------------- +# Bước 8: /tmp & cache cũ — liệt kê file >7 ngày, xác nhận rồi xóa # ----------------------------- step_tmp_cache() { step_header "/tmp & Cache cũ" @@ -405,7 +472,7 @@ step_tmp_cache() { } # ----------------------------- -# Chạy tuần tự 7 bước +# Chạy tuần tự 8 bước # ----------------------------- run_all_steps() { step_upgrade @@ -414,6 +481,7 @@ run_all_steps() { step_journal step_pkg_cache step_snap + step_orphan_chrome step_tmp_cache }