使用 systemd 在系统关闭之前执行脚本?

使用 systemd 在系统关闭之前执行脚本?

我写了一个脚本来暂停我所有的 VirtualBox 机器,并在 中添加一行/etc/rc.local.shutdown,但它似乎不起作用,

su - XX -c /XX

当我下次启动时,VirtualBox 告诉我机器是 Aborted,所以脚本没有执行。 (手动启动该脚本对我有用)

PS我已经启用了shutdown.target

编辑

这个问题似乎比我想象的更复杂,在我的系统中.bashrc,如果它运行在 上tty3,它就会执行startx,所以当 systemd 决定关闭/重新启动时,它会VBoxSVC在 X Session 终止时杀死进程和其他东西。

我还尝试破解 的源代码xfsm-shutdown-helper,制作一个假的systemctl,首先执行我的脚本,以上都不起作用。

答案1

如果我理解正确的话,您希望在 tty3 上的 bash 会话终止之前或 Xserver 终止之前挂起您的 VB 机器。

我相信 systemd 不知道您正在运行的 Xsession,因为您从 .bashrc 启动它,因此很难告诉 systemd 在终止您的 shell 或 Xsession 之前挂起您的 VB。您必须在关闭序列中找到一个“足够早”的位置,这可能很难找到并且在语义上有问题,因为它将“用户内容”与“系统内容”混合在一起

解决方案可能在某种程度上取决于 systemd 终止进程的方式,但以下内容至少应该指出一个好的方向:

在 shell 终止之前

suspendVB() {
        echo "suspending VBs"
        # put real code here
        exit
}

trap suspendVB EXIT

如果您将其作为 bash 的 rc 文件(或将其添加到 .bashrc 中),则其中的代码suspendVB()将在 shell 终止之前执行。您可以通过运行来测试这一点

bash --rcfile xxx

其中文件xxx包含上面的代码。这会在当前 shell 中启动另一个 shell,仅用于测试。当您运行简单的退出时,您将看到:

martin@beaureve:~$ exit
exit
suspending VBs
/home/martin >

然后您就回到了原来的(登录)shell。

您可能需要了解 systemd 实际上如何终止您的登录 shell,并且您可能需要EXIT用其他一些信号进行替换。查找trap命令以了解更多信息。

请注意,当 systemd 使用“-9”(SIGKILL)终止您的进程时,您将无法捕获终止,即您不走运。

在 Xsession 终止之前

或者,您可以在 Xsession 中尝试类似的操作。这在 systemd 终止您的 Xsession 的情况下至关重要它会终止你的 shell。您可能想要在 X 启动文件之一(例如 .xinitrc)中插入陷阱 - 查找手册页startxxinit了解更多信息。

如果你的startx文件看起来像我的,那么 xserver 在前台启动,你也可以简单地将挂起命令放在 X 实际启动的行之后(并且根本不使用陷阱):

xinit "$client" $clientargs -- "$server" $display $serverargs
retval=$?
echo " --- suspending VBs ---"

我输入了“挂起 VB”这一行,当我运行时,startx -- vt8我在 vt8 上获得了一个 fullblows (kde) 会话,只有当我注销时,“挂起 VB”这行才会出现在屏幕上。

相关内容