Skip to content

Instantly share code, notes, and snippets.

@ihainan
Created January 28, 2026 01:30
Show Gist options
  • Select an option

  • Save ihainan/e985e6a6ba687c7da53461e64ba27726 to your computer and use it in GitHub Desktop.

Select an option

Save ihainan/e985e6a6ba687c7da53461e64ba27726 to your computer and use it in GitHub Desktop.
#!/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