Created
January 28, 2026 01:30
-
-
Save ihainan/e985e6a6ba687c7da53461e64ba27726 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Sunshine 退出会话时:智能冻结进程 | |
| # 此脚本在容器内部运行 | |
| # 逻辑: | |
| # - 如果有游戏运行:冻结 Steam + reaper + 游戏 | |
| # - 如果没有游戏:只冻结 reaper,保持 Steam 客户端运行 | |
| LOG_FILE="$(dirname "$0")/steam-pause.log" | |
| log_message() { | |
| echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" | |
| } | |
| # 一次性获取所有子进程(从深到浅,用于暂停) | |
| get_all_children_batch() { | |
| local parent_pid="$1" | |
| ps -eo pid,ppid | awk -v root=$parent_pid ' | |
| BEGIN { | |
| todo[root] = 1 | |
| depth[root] = 0 | |
| } | |
| { | |
| parent[$1] = $2 | |
| children[$2] = children[$2] " " $1 | |
| } | |
| END { | |
| # BFS 遍历,记录每个节点的深度 | |
| while (length(todo) > 0) { | |
| for (p in todo) { | |
| current = p | |
| current_depth = depth[current] | |
| delete todo[p] | |
| break | |
| } | |
| n = split(children[current], kids) | |
| for (i = 1; i <= n; i++) { | |
| if (kids[i] != "") { | |
| depth[kids[i]] = current_depth + 1 | |
| max_depth = (current_depth + 1 > max_depth) ? current_depth + 1 : max_depth | |
| todo[kids[i]] = 1 | |
| all_pids[kids[i]] = 1 | |
| } | |
| } | |
| } | |
| # 从深到浅(用于暂停:先暂停子进程) | |
| for (d = max_depth; d >= 0; d--) { | |
| for (pid in all_pids) { | |
| if (depth[pid] == d) print pid | |
| } | |
| } | |
| } | |
| ' 2>/dev/null || true | |
| } | |
| # 暂停进程树 | |
| suspend_process_tree() { | |
| local pid="$1" | |
| # 获取所有子进程(从深到浅) | |
| local children=$(get_all_children_batch "$pid") | |
| # 批量暂停所有子进程 | |
| if [ -n "$children" ]; then | |
| local children_list=$(echo "$children" | tr '\n' ' ') | |
| kill -STOP $children_list 2>/dev/null | |
| fi | |
| # 最后暂停父进程 | |
| kill -STOP "$pid" 2>/dev/null | |
| } | |
| # 检查是否有游戏正在运行(快速检测) | |
| check_game_running() { | |
| # 通过 SteamLaunch 或 applaunch 标识判断是否有游戏运行 | |
| if ps aux | grep -E "(SteamLaunch|applaunch)" | grep -v grep > /dev/null 2>&1; then | |
| return 0 # 有游戏运行 | |
| else | |
| return 1 # 没有游戏运行 | |
| fi | |
| } | |
| # 查找所有目标进程 | |
| find_target_processes() { | |
| local include_steam="$1" # 是否包含 Steam 主进程 | |
| # 查找 Steam 主进程(如果需要) | |
| if [ "$include_steam" = "yes" ]; then | |
| steam_pid=$(pgrep -x steam 2>/dev/null | head -1) | |
| [ -n "$steam_pid" ] && echo "steam:$steam_pid" | |
| fi | |
| # 查找 reaper 进程 | |
| pgrep -x reaper 2>/dev/null | sed "s/^/reaper:/" | |
| # 查找游戏进程(通过 SteamLaunch 或 applaunch 标识) | |
| ps aux | grep -E "(SteamLaunch|applaunch)" | grep -v grep | awk '{ | |
| pid = $2 | |
| cmd = "ps -o comm= -p " pid " 2>/dev/null || echo game" | |
| cmd | getline comm | |
| close(cmd) | |
| print comm ":" pid | |
| }' | |
| } | |
| log_message "=========================================" | |
| log_message "开始智能暂停进程" | |
| log_message "=========================================" | |
| # 快速检查是否有游戏运行 | |
| if check_game_running; then | |
| log_message "检测到游戏正在运行,将暂停 Steam 客户端和游戏" | |
| target_processes=$(find_target_processes "yes") | |
| else | |
| log_message "未检测到游戏运行,只暂停 reaper,保持 Steam 客户端运行" | |
| target_processes=$(find_target_processes "no") | |
| fi | |
| if [ -z "$target_processes" ]; then | |
| log_message "未找到需要暂停的进程" | |
| exit 0 | |
| fi | |
| total_count=$(echo "$target_processes" | wc -w) | |
| log_message "找到 $total_count 个目标进程,开始暂停..." | |
| success_count=0 | |
| for process_entry in $target_processes; do | |
| process_name=$(echo "$process_entry" | cut -d: -f1) | |
| pid=$(echo "$process_entry" | cut -d: -f2) | |
| if suspend_process_tree "$pid"; then | |
| success_count=$((success_count + 1)) | |
| fi | |
| done | |
| log_message "暂停完成: $success_count/$total_count 个进程树" | |
| log_message "=========================================" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment