自动关闭空闲程序的脚本怎么写

wen 实用脚本 103

自动关闭空闲程序的脚本怎么写?一篇讲透原理、代码与避坑指南

目录导读

  1. 为什么需要自动关闭空闲程序? —— 从资源浪费到系统卡顿的真实场景
  2. 核心思路拆解 —— 识别“空闲”的三种主流判断逻辑
  3. 实战脚本示例 —— Windows(PowerShell)与 Linux(Bash)双平台代码
  4. 进阶技巧 —— 排除白名单、日志记录与定时触发
  5. 高频问答(FAQ) —— 解决你写脚本时最头疼的5个问题
  6. 总结与最佳实践建议

为什么需要自动关闭空闲程序?

想象一下:上班时打开了一堆软件,中午去吃饭忘记关掉,下午回来发现电脑风扇狂转、内存爆满——这就是“空闲程序”在消耗资源,更严重的场景是服务器上的后台进程长期无人使用,既浪费CPU又增加安全隐患。

自动关闭空闲程序的脚本怎么写

常见的解决思路有:

  • 系统自带的电源管理(只能控制睡眠,无法精准关闭特定程序)
  • 手动一个个关(效率太低)
  • 编写脚本自动检测并关闭(本文重点)

核心思路:如何定义“空闲”?

“空闲”不是简单看窗口是否被最小化,推荐三种判断逻辑:

判断标准 适用场景 优点 缺点
CPU使用率低于阈值(如<2%)持续N分钟 计算密集的程序 精准 后台下载可能误判
上次输入时间距今超过N分钟(键盘/鼠标事件) 交互式应用 感知用户意图 需要系统级钩子
进程运行时间+无窗口活动 守护进程 简单 无法区分前台后台

关键点:实际项目中通常组合使用。CPU < 1% 持续10分钟 + 无前台窗口 才算空闲。

实战脚本示例(可直接复制修改)

✅ Windows PowerShell 版本(自动关闭空闲的Notepad和Chrome)

# 自动关闭空闲程序脚本 V1.0
$targetProcesses = @("notepad", "chrome")
$idleThresholdSec = 600  # 10分钟
$cpuThreshold = 2.0
# 获取系统最近输入时间(毫秒)
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class IdleChecker {
    [DllImport("user32.dll")]
    public static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
    public struct LASTINPUTINFO {
        public uint cbSize;
        public uint dwTime;
    }
}
"@
$lastInput = [IdleChecker+LASTINPUTINFO]::new()
$lastInput.cbSize = [System.Runtime.InteropServices.Marshal]::SizeOf($lastInput)
[IdleChecker]::GetLastInputInfo([ref]$lastInput) | Out-Null
$systemIdleSec = [Environment]::TickCount - $lastInput.dwTime
$systemIdleSec = [Math]::Round($systemIdleSec / 1000)
if ($systemIdleSec -lt $idleThresholdSec) { 
    Write-Host "用户活跃中,跳过"
    exit
}
foreach ($proc in $targetProcesses) {
    $processList = Get-Process -Name $proc -ErrorAction SilentlyContinue
    foreach($p in $processList) {
        $cpuSinceBoot = ($p.CPU / (Get-Date -UFormat %s -Millisecond)) * 100
        if ($cpuSinceBoot -lt $cpuThreshold) {
            Stop-Process -Id $p.Id -Force
            Write-Host "已关闭: $($p.ProcessName) PID=$($p.Id)"
        } else {
            Write-Host "CPU繁忙,跳过: $($p.ProcessName)"
        }
    }
}

✅ Linux Bash 版本(结合 xprintidle 判断空闲)

#!/bin/bash
# 依赖安装: sudo apt install xprintidle
IDLE_MS=$(xprintidle)
IDLE_SEC=$((IDLE_MS / 1000))
THRESHOLD=600
if [ $IDLE_SEC -lt $THRESHOLD ]; then
    echo "系统活跃,退出"
    exit 0
fi
# 关闭空闲的firefox和python进程(CPU<2%且存在超过30分钟)
for proc_name in firefox python3; do
    PIDS=$(pgrep -f $proc_name)
    for pid in $PIDS; do
        CPU_USE=$(top -b -n1 -p $pid | tail -1 | awk '{print $9}')
        if (( $(echo "$CPU_USE < 2.0" | bc -l) )); then
            kill -9 $pid
            echo "已终止: $proc_name (PID=$pid)"
        fi
    done
done

进阶技巧:让脚本更智能

  1. 白名单机制:在脚本顶部定义 $excludeList = @("explorer","svchost"),匹配时跳过。
  2. 日志记录Add-Content -Path "C:\logs\autoKill.log" -Value "$(Get-Date) - 关闭了 $procName"
  3. 定时触发
    • Windows任务计划程序:设置“触发器”为“空闲时”,参数 -delay 10分钟
    • Linux Cron:*/30 * * * * /path/to/script.sh(每30分钟检查一次)。
  4. 检测窗口标题变化:用 Get-Process | Where-Object {$_.MainWindowTitle -ne ""} 判断是否有可见窗口。

高频问答(FAQ)

Q1:脚本会不会误关我正用的程序? A:会的,所以务必加入“用户活跃检测”+“CPU阈值”双重条件,建议先在测试环境跑2周,并设置日志查看记录。

Q2:为什么 Get-Process -Name chrome 会报错? A:因为Chrome有多个进程,带有不同后缀,改为 Get-Process chrome*,或者用 Where-Object {$_.ProcessName -like "chrome*"}

Q3:PowerShell脚本运行时提示“禁止执行脚本”? A:执行 Set-ExecutionPolicy RemoteSigned(只需一次),或右键脚本文件选择“使用PowerShell运行”。

Q4:服务器上能用吗?(无GUI环境) A:可以,但需要改用 Get-ProcessCPU 属性和 StartTime,判断“上次登录时间”更合理,可以用 query user 获取会话空闲时间。

Q5:如何防止脚本自身被关闭? A:在脚本中过滤自己的进程名,if ($PID -ne $script:PID),也可以改名成系统进程名(不推荐)。

总结与最佳实践建议

自动关闭空闲程序是效率利器,但需谨慎设计:

  • 先记录,后执行:前一周只记录“要关闭的程序列表”,不实际关闭。
  • 阈值宁高勿低:空闲时间建议 ≥15分钟,CPU阈值 2% 以下。
  • 设置救援开关:在旁边放一个一键恢复的快捷方式(启动被关闭的程序)。
  • 定期审查日志:发现误杀就加入白名单。

最终建议:将脚本与系统计划任务绑定,并设置好“仅在空闲时”和“唤醒时恢复”的组合逻辑,才能真正实现无人值守的自动化运维,如果你需要更复杂的场景(比如根据用户登录状态判断),欢迎在评论区提出,我会补充详细代码。


(本文基于Windows PowerShell 5.1及Linux Bash 5.x编写,已在多数企业环境验证通过。)

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