Bash 如何在空闲超时后重启 Firefox,避免每秒打开新标签页?
需要修正空闲时间的比较方式,并确保脚本启动的 Firefox 实例可以跟踪生命周期。原来的 if($(xprintidle)>120000); 没有进行数值比较;每秒出现一个新标签页,通常与 Firefox 将启动请求转交给已有实例有关。
空闲时间判断为什么不正确
原来的写法是:
if($(xprintidle)>120000);
单层圆括号表示子 shell,$(xprintidle) 的输出会被当成命令名,而 >120000 是输出重定向,可能在当前目录创建名为 120000 的文件。
应先读取空闲时间,再使用 Bash 的算术比较:
idle=$(xprintidle)
if (( idle > 120000 )); then
# 执行超时操作
:
fi
xprintidle 返回的单位是毫秒,120000 对应 120 秒。实际使用时还应检查命令是否执行成功,以及输出是否为数字。
为什么会每秒打开一个标签页
第一个循环依赖一个前提:执行 firefox ... 后,该命令会一直等待浏览器退出。
如果启动请求被转交给已经运行的 Firefox 实例,新执行的命令可能很快返回。循环等待一秒后再次执行启动命令,就会不断向已有实例发送打开网址的请求。
仅凭提供的代码,无法确定为什么加入第二个循环后才出现这一现象。不过,第二个循环中的错误比较不能正确控制 Firefox 退出,需要单独修复。
对于 kiosk,可以使用专用 profile,并通过 --no-remote 避免将启动请求转交给已有实例。原命令中的其他参数需要根据实际 Firefox 版本确认是否适用,下面只保留相关启动参数。
用一个循环管理启动和超时
下面的示例会在 Firefox 退出后重新启动它,并在空闲达到 120 秒时关闭当前实例。在空闲时间降到阈值以下之前,脚本只触发一次关闭,避免无人操作时反复重启。
#!/usr/bin/env bash
url='https://thesite.com'
profile_dir="$HOME/.mozilla/firefox/kiosk-profile"
timeout_ms=120000
browser_pid=''
idle_handled=0
mkdir -p "$profile_dir" || exit 1
cleanup() {
if [[ -n "$browser_pid" ]]; then
kill "$browser_pid" 2>/dev/null || :
wait "$browser_pid" 2>/dev/null || :
fi
}
trap cleanup EXIT
trap 'exit 0' INT TERM
while true; do
if [[ -z "$browser_pid" ]] || ! kill -0 "$browser_pid" 2>/dev/null; then
if [[ -n "$browser_pid" ]]; then
wait "$browser_pid" 2>/dev/null || :
fi
firefox --no-remote --profile "$profile_dir" --kiosk "$url" &
browser_pid=$!
fi
if ! idle=$(xprintidle); then
printf '%s\n' '无法读取空闲时间' >&2
exit 1
fi
if [[ ! "$idle" =~ ^[0-9]+$ ]]; then
printf '无效的空闲时间:%s\n' "$idle" >&2
exit 1
fi
if (( 10#$idle < timeout_ms )); then
idle_handled=0
elif (( idle_handled == 0 )); then
kill "$browser_pid" 2>/dev/null || :
wait "$browser_pid" 2>/dev/null || :
browser_pid=''
idle_handled=1
fi
sleep 1
done
把 url 替换为实际网站地址,再用 Bash 运行脚本。$! 保存本次后台启动命令的 PID;关闭时只处理这个 PID。wait 等待该进程退出,下一轮循环再启动 Firefox。
这里使用 kill 默认发送的 SIGTERM 请求退出。如果 Firefox 卡住、没有响应,wait 可能持续等待。需要自动处理这种情况时,应另外设计退出超时和后续处理策略。
运行前需要注意什么
- 专用 profile 不能同时被另一个 Firefox 实例占用。如果启动命令立即退出,先查看终端中的错误信息,确认参数、profile 和显示环境是否正常。
- 原来的
pkill -f firefox按完整命令行匹配,可能影响其他 Firefox 实例或相关进程。跟踪本次启动的 PID 更适合这个场景。 - 原来的
sleep 120只会暂停空闲检查循环,不会阻止另一个循环启动 Firefox。示例通过idle_handled控制连续空闲期间的重复触发。 - 该方案以
xprintidle能在当前 X11 会话中正常读取空闲时间为前提。原生 Wayland 环境需要使用适合桌面环境的空闲检测方式。
备注:内容仅供参考。
