定时退出不活跃程序的脚本

wen 实用脚本 1

本文目录导读:

定时退出不活跃程序的脚本

  1. 安装和使用说明
  2. 替代方案:Python版本(更可靠)
  3. 注意事项
  4. 自动启动(开机自启)
#!/bin/bash
# 不活跃阈值(秒)
INACTIVE_LIMIT=300  # 5分钟
CHECK_INTERVAL=60   # 检查间隔(秒)
# 需要监控的程序列表(进程名或完整路径)
TARGET_PROGRAMS=(
    "firefox"
    "google-chrome"
    "code"  # VS Code
)
# 获取当前活跃窗口的进程信息
get_active_process() {
    # 方法1:使用xdotool(需要安装)
    if command -v xdotool &> /dev/null; then
        active_pid=$(xdotool getactivewindow getwindowpid)
        if [ -n "$active_pid" ]; then
            ps -p "$active_pid" -o comm= 2>/dev/null
            return
        fi
    fi
    # 方法2:使用wmctrl(备用方案)
    if command -v wmctrl &> /dev/null; then
        active_window=$(wmctrl -lp | grep "$(xdotool getactivewindow getwindowname)" | awk '{print $3}')
        if [ -n "$active_window" ]; then
            ps -p "$active_window" -o comm= 2>/dev/null
            return
        fi
    fi
    echo ""
}
# 获取进程的最后活动时间
get_last_active_time() {
    local process_name=$1
    # 使用/proc文件系统获取进程启动时间
    local pids=$(pgrep -x "$process_name" 2>/dev/null)
    if [ -n "$pids" ]; then
        for pid in $pids; do
            # 获取进程启动时间(Unix时间戳)
            local start_time=$(stat -c %Y /proc/"$pid" 2>/dev/null)
            # 获取进程的tty活动时间(如果有)
            local last_access=$(stat -c %X /proc/"$pid" 2>/dev/null)
            echo "$last_access"
            return
        done
    fi
    echo ""
}
# 主检查循环
echo "启动不活跃程序监控..."
echo "不活跃阈值:${INACTIVE_LIMIT}秒"
echo "检查间隔:${CHECK_INTERVAL}秒"
echo "监控程序:${TARGET_PROGRAMS[*]}"
echo "----------------------------------------"
while true; do
    current_time=$(date +%s)
    active_process=$(get_active_process)
    for program in "${TARGET_PROGRAMS[@]}"; do
        # 检查程序是否在运行
        if pgrep -x "$program" &> /dev/null; then
            # 获取程序最后活动时间
            last_active=$(get_last_active_time "$program")
            if [ -n "$last_active" ] && [ "$last_active" -gt 0 ]; then
                inactive_time=$((current_time - last_active))
                # 检查程序是否当前活跃(是活跃窗口)
                if [ "$active_process" != "$program" ]; then
                    if [ "$inactive_time" -gt "$INACTIVE_LIMIT" ]; then
                        echo "$(date '+%Y-%m-%d %H:%M:%S') - 程序 $program 不活跃超过 ${INACTIVE_LIMIT}秒 (实际:${inactive_time}秒),正在终止..."
                        # 终止程序(使用SIGTERM先,如果不行再用SIGKILL)
                        pkill -x "$program" 2>/dev/null
                        sleep 2
                        # 如果进程仍然存在,强制终止
                        if pgrep -x "$program" &> /dev/null; then
                            pkill -9 -x "$program" 2>/dev/null
                            echo "$(date '+%Y-%m-%d %H:%M:%S') - 强制终止 $program"
                        else
                            echo "$(date '+%Y-%m-%d %H:%M:%S') - $program 已正常终止"
                        fi
                    fi
                fi
            fi
        fi
    done
    sleep "$CHECK_INTERVAL"
done

安装和使用说明

安装依赖工具

# Debian/Ubuntu
sudo apt-get install xdotool wmctrl
# CentOS/RHEL
sudo yum install xdotool wmctrl
# macOS (使用brew)
brew install xdotool

保存脚本

# 保存为文件
nano kill_inactive.sh
# 添加执行权限
chmod +x kill_inactive.sh
# 运行脚本
./kill_inactive.sh

自定义配置

  • INACTIVE_LIMIT: 不活跃超时时间(秒)
  • CHECK_INTERVAL: 检查间隔(秒)
  • TARGET_PROGRAMS: 要监控的程序列表

替代方案:Python版本(更可靠)

#!/usr/bin/env python3
import os
import time
import subprocess
import json
from datetime import datetime
# 配置
INACTIVE_LIMIT = 300  # 5分钟
CHECK_INTERVAL = 60   # 1分钟
TARGET_PROGRAMS = ["firefox", "google-chrome", "code"]
def get_active_window_process():
    """获取当前活跃窗口的进程名"""
    try:
        # 使用xdotool获取活跃窗口PID
        result = subprocess.run(
            ["xdotool", "getactivewindow", "getwindowpid"],
            capture_output=True, text=True, timeout=2
        )
        if result.returncode == 0:
            pid = result.stdout.strip()
            # 获取进程名
            proc_result = subprocess.run(
                ["ps", "-p", pid, "-o", "comm="],
                capture_output=True, text=True, timeout=2
            )
            if proc_result.returncode == 0:
                return proc_result.stdout.strip()
    except:
        pass
    return None
def get_process_last_active(pid):
    """获取进程最后活动时间(文件访问时间)"""
    try:
        proc_dir = f"/proc/{pid}"
        if os.path.exists(proc_dir):
            # 使用进程的文件访问时间作为活动指示
            stat_info = os.stat(proc_dir)
            return stat_info.st_atime
    except:
        pass
    return None
def kill_process(process_name):
    """终止进程"""
    try:
        # 先尝试正常终止
        subprocess.run(["pkill", "-x", process_name], timeout=5)
        time.sleep(2)
        # 检查是否还在运行,强制终止
        check = subprocess.run(
            ["pgrep", "-x", process_name],
            capture_output=True, text=True
        )
        if check.stdout.strip():
            subprocess.run(["pkill", "-9", "-x", process_name], timeout=5)
            return "force_killed"
        return "killed"
    except Exception as e:
        return f"error: {e}"
def main():
    print(f"启动不活跃程序监控...")
    print(f"不活跃阈值:{INACTIVE_LIMIT}秒")
    print(f"检查间隔:{CHECK_INTERVAL}秒")
    print(f"监控程序:{TARGET_PROGRAMS}")
    print("-" * 40)
    while True:
        try:
            current_time = time.time()
            active_process = get_active_window_process()
            # 获取所有目标程序的PID
            for program in TARGET_PROGRAMS:
                result = subprocess.run(
                    ["pgrep", "-x", program],
                    capture_output=True, text=True
                )
                pids = result.stdout.strip().split('\n') if result.stdout.strip() else []
                for pid in pids:
                    if not pid:
                        continue
                    last_active = get_process_last_active(pid)
                    if last_active:
                        inactive_time = current_time - last_active
                        # 检查是否当前活跃
                        if active_process != program:
                            if inactive_time > INACTIVE_LIMIT:
                                print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - "
                                      f"程序 {program} (PID: {pid}) 不活跃超过 "
                                      f"{INACTIVE_LIMIT}秒 (实际:{int(inactive_time)}秒),终止中...")
                                status = kill_process(program)
                                print(f"状态:{status}")
                                break  # 只终止一个实例
            time.sleep(CHECK_INTERVAL)
        except KeyboardInterrupt:
            print("\n监控已停止")
            break
        except Exception as e:
            print(f"错误:{e}")
            time.sleep(CHECK_INTERVAL)
if __name__ == "__main__":
    main()

注意事项

  1. x permission: 需要 xdotool 访问X server,可能在Wayland下不工作
  2. 权限问题: 可能需要root权限来终止某些系统进程
  3. 准确性: 不活跃检测基于文件访问时间,可能不完全准确
  4. 资源占用: 监控会占用少量系统资源

自动启动(开机自启)

# 创建systemd服务(Linux)
sudo nano /etc/systemd/system/kill_inactive.service
[Unit]
Description=Kill Inactive Programs Monitor
[Service]
ExecStart=/path/to/kill_inactive.sh
Restart=always
User=your_username
[Install]
WantedBy=default.target
# 启用服务
sudo systemctl enable kill_inactive.service
sudo systemctl start kill_inactive.service

选择适合你系统的版本,并根据需要调整配置参数。

抱歉,评论功能暂时关闭!