Systemd:如何在不实际关闭的情况下关闭

Systemd:如何在不实际关闭的情况下关闭

我正在设置一个运行 Debian Jessie 的嵌入式设备,以便在 UPS 发生电源故障时关闭。不幸的是,设备的引导加载程序每当退出时都会重新启动操作系统,因此 shutdown/halt 命令相当于重新启动。

我主要关心的是保护所连接硬盘上的数据。我认为我最好的选择是杀死尽可能多的任务,然后等待断电。systemctl isolate emergency.target看起来很接近我想要的,除了它让磁盘挂载。有没有一种方法可以final.target在没有实际关闭/停止命令的情况下基本上让 Systemd 进入?

答案1

systemctl halt可能会成功。从手册:

halt
    Shut down and halt the system. This is mostly equivalent to
    systemctl start halt.target --job-mode=replace-irreversibly
    --no-block, but also prints a wall message to all users. This
    command is asynchronous; it will return after the halt operation is
    enqueued, without waiting for it to complete. Note that this
    operation will simply halt the OS kernel after shutting down,
    leaving the hardware powered on. Use systemctl poweroff for
    powering off the system (see below).

答案2

假设这不仅仅是某种看门狗设备的问题,您可以尝试劫持kexecsystemd 的目标。这通常用于加载 kdump 内核来转储内存,但您实际上可以设置该目标来执行任何操作。

我创建了一个名为 systemd 的单元kexec-sleep并将其放入/etc/systemd/system/kexec-sleep.service(我不确定这些Requires//After行是否Before完全正确,但它们在虚拟机中为我工作):

[Unit]
Description=Sleep forever at kexec
DefaultDependencies=no
Requires=umount.target
After=umount.target
Before=final.target

[Service]
Type=oneshot
ExecStart=/sbin/kexec-sleep
KillMode=none

[Install]
WantedBy=kexec.target

这将调用/sbin/kexec-sleep,它只是一个 shell 脚本(如下所示)。它尝试以只读方式重新挂载根文件系统,因此它应该保持干净状态,直到设备断电。我sleep那里有一些可能比您需要的长,最后还有一个提示,可以让您重新启动而无需拔掉电源线。

#!/bin/sh

stty sane < /dev/console       # enable automatic CRLF output on console
exec < /dev/console > /dev/console 2>&1  # redirect stdio to/from console
echo "Sleeping several seconds for processes to terminate..."
sleep 10
# kill some expected processes
killall dhclient
# sleep again...
sleep 5
echo "Processes still running:"
/bin/ps --ppid 2 -p 2 --deselect    # list non-kernel processes
echo "Attempting to remount root filesystem read-only..."
sync; sync; sync
mount -o remount,ro /
grep /dev/sda /proc/mounts
while true; do
    echo "System paused. Type 'reboot' to reboot"
    read -p '> ' entry
    if [ "$entry" = "reboot" ]; then
        /sbin/reboot -f
    fi
done

创建这些文件后,运行chmod +x /sbin/kexec-sleepsystemctl enable kexec-sleep.

要触发此操作而不是正常关闭,请运行systemctl kexec

相关内容