我有一个使用 go-rod 用 go 编写的程序,它启动无头铬并连接到调试端口以执行一些与 Web 相关的操作。使用模式相当于Python中的selenium或puppeteer。
当我在 ssh 会话中从命令行运行该程序时,它可以工作。
我现在需要每晚执行这个程序。不幸的是,将其作为 cron 作业运行是行不通的。错误信息是Failed to get the debug url: /system.slice/cron.service is not a snap cgroup
。
snap 提供的安全性是一件好事,我想保留它。
如何使用 snap chromium 每晚运行我的程序?
编辑:按照noisefloor的建议,我设置了一个systemd计时器来将我的程序作为用户服务运行。即使我注销并重新启动后,它仍然有效。这是食谱。
mkdir -p ~/.config/systemd/user
loginctl enable-linger <user>
:告诉 systemd <user> 有一些 systemd 服务和计时器存储在~/.config/systemd/user
. <user> 将替换为您的帐户名。~/.config/systemd/user/myservice.service
创建包含以下内容的服务文件
[Unit]
Description=My service
[Service]
ExecStart=<cmd args>
[Install]
WantedBy=multi-user.target
~/.config/systemd/user/myservice.timer
创建名为包含的计时器文件
[Unit]
Description=Timer for my service
[Timer]
# start myservice every night at 05:00:00 in the morning
OnCalendar=*-*-* 5:00:00
Persistent=true
[Install]
WantedBy=timers.target
systemctl --user start myservice.timer
检查计时器是否正在运行:
systemctl --user list-timers
重启后启用计时器
systemctl --user enable myservice.timer
这比添加 crontab 行稍微繁琐一些,但我们受益于 cgroup 沙箱保护。
注意:systemctl 命令不必使用 sudo 或以 root 身份执行。
由 systemd 启动的所有内容(包括用户会话和 cron 作业)都在一个切片 Unit中运行。slice 单元在后台使用名为cgroups的 Linux 内核功能来对分配给进程/进程组的资源进行分组和分离,以便每次使用。cgroup A 中的进程无法访问 cgroup B 中的资源。
cron 在 system.slice 内运行,而 Chromium snap 通常在 user1xxx.slice 内运行(而 1xxx 是系统分配的用户编号),后者在 user.slice 内运行。因此,由 cron 启动的 Go 程序无法访问 Chromium 的资源,因为它们运行在不同的 slice / cgroup 中。
通过运行命令可以在终端中输出切片的层次顺序和分组
systemd-cgls
。该问题的一个可能的解决方案可能是不通过 cron启动 Go 程序,而是通过systemd 计时器单元启动它,该单元与运行 Chromium snap 的用户相同。这会将 Go 程序的执行移动到 user1xxx.slice 中,因此它与 Chromium 位于同一片内。