如何在 Linux 关机时运行命令

653 位读者喜欢这篇文章。
Penguins gathered together in the Artic

Opensource.com

长久以来,Linux 和 Unix 系统都非常容易在启动时运行命令。只需将您的命令添加到 /etc/rc.local 即可。但事实证明,在关机时运行命令要稍微复杂一些。

为什么要在计算机关机时运行命令?也许您想从数据库中注销机器或服务。也许您想将数据从易失性存储系统复制到永久位置。想让您的电脑在关机前在 Twitter 帐户上发布“#RIP 我!”吗?

此时我应该澄清一下,我谈论的是所谓的“一次性”命令,而不是停止守护进程。尽管如此,很容易将它们视为相同的方式。如果您熟悉 SysVinit,您可能会想,“哦,我只需创建一个 kill 脚本。” 例如,当您的系统退出运行级别 3 时,应该调用 /etc/rc.d/rc3.d/K99runmycommandatshutdown。毕竟,这就是 /etc/init.d/ 中的脚本停止的方式。

这是一个很好的猜测,但事实证明这是错误的。SysVinit 不会盲目地运行 kill 脚本。相反,它会查找(在 Red Hat 6 上)/var/lock/subsys/service_name(这里的 service_name 将是 runmycommandatshutdown)。因此,您必须稍微耍一些花招,并将您的脚本视为常规服务。下面的脚本给出了一个例子

#!/bin/sh
# chkconfig: 2345 20 80
# description: An example init script to run a command at shutdown

# runmycommandatshutdown runs a command at shutdown. Very creative.

LOCKFILE=/var/lock/subsys/
start(){
    # Touch our lock file so that stopping will work correctly
    touch ${LOCKFILE}
}

stop(){
# Remove our lock file
rm ${LOCKFILE}
# Run that command that we wanted to run
mycommand
}

case "$1" in
    start) start;;
    stop) stop;;
    *)
        echo $"Usage: $0 {start|stop}"
        exit 1
esac
exit 0

将该脚本放入 /etc/init.d/runmycommandatshutdown 并使用 chkconfig on runmycommandatshutdown 启用它后,您的命令将在关机时运行。

systemd

所有这些都很棒,但是如果您运行的 Linux 发行版使用 systemd 而不是 SysVinit 呢?事实证明,使用 systemd 要简单得多。您只需将脚本放入 /usr/lib/systemd/system-shutdown/ 中,这由 systemd-halt.service 处理。当然,如果您需要在特定顺序中管理依赖项(例如,如果网络堆栈已关闭,则无法发布推文),那么您可以编写 systemd 服务单元文件。例如

[Unit]
Description=Run mycommand at shutdown
Requires=network.target
DefaultDependencies=no
Before=shutdown.target reboot.target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=mycommand

[Install]
WantedBy=multi-user.target
标签
User profile image.
Ben Cotton 是一名训练有素的气象学家,但天气是一个很棒的爱好。Ben 在红帽公司担任 Fedora 项目经理。他是《开源项目项目管理》的作者。在 Twitter (@FunnelFiasco) 或 FunnelFiasco.com 上找到他。

10 条评论

“事实证明,使用 systemd 要简单得多。”

我对此表示异议 - 多年来,我一直在系统关机时运行一个脚本,将所有已更改的文件复制到外部磁盘。让 systemd 等待作业完成再关机是一个主要的难题。据推测,systemd 尊重 rc.d 脚本,但我无法使其工作。

感谢您扩展了我对 Linux 的了解。我想让 'fstrim' 在我每周关机时运行一次。我已经试验过 'cron' 和 'anacron',但我不确定它是否正在发生。我想我应该检查日志以确保。

ubuntu 16.04 它每周自动运行 fstrim 一次,ubuntu 14.04 lts 仅在英特尔和三星 ssd 上每周运行 fstrim 一次,除非您在某处添加一个 no vender check 选项,如果您去 youtube 广告搜索 how collins,然后点击他的名字,您可以观看一个视频,他在视频中谈论了一点关于 Darrin 以及如何在 ubuntu 14.04 lts 中添加 no venerchech 选项,但不确定其他 Linux 发行版。

回复 作者 Don Watkins

在 Slackware(BSD 兼容模式下的 sysvinit)中,它甚至更简单 :)

$ cat /etc/rc.d/rc.local_shutdown
#!/bin/sh
#
# /etc/rc.d/rc.local_shutdown: 本地系统关机脚本。
#
# 将任何本地关机命令放在此处。

my_command_at_shutdown
exit 0

$ sudo chmod +x /etc/rc.d/rc.local_shutdown

我想念过去关机曾经是一个可以编辑的脚本的日子。我们运行 Informix。我们会给用户一段较长的宽限期,比如 15 分钟。这让他们有时间完成他们正在做的事情,但总会有一个人会一直工作到最后一刻,并妨碍最终关机。Informix 有一种模式,它可以继续处理现有连接,但会阻止创建新连接,所以我只是将进入该模式的命令与 wall 命令一起放入关机脚本中,wall 命令发出了第一个警告消息。这比依赖 sysv 运行级别更灵活。

这听起来确实很方便。当我在学术界担任系统管理员时,我总是尝试将关机安排在人们睡觉的时间。但当然,无论您选择什么时间,总会至少有一个研究生在那个时间工作。 :-)

回复 作者 igoddard (未验证)

在我的终端上,需要进行一些修改。首先,我必须添加脚本

sudo chkconfig --add runmycommandatshutdown

其次,参数“on”需要放在脚本的末尾
sudo chkconfig runmycommandatshutdown on

干杯!

我在我的 Fedora 24 盒子(使用 systemd)上尝试了一个脚本,但它未能运行。有两个可能的原因

1. 文章没有提及使脚本可执行 -- 这是必要的吗?

2. 我的脚本执行 'dnf upgrade -y && dnf clean all'(系统升级,清理缓存),这仅允许由 su 执行,我不使用 sudo -- systemd 例程在关机时是否会自动以 root 用户身份运行脚本?

先谢谢了

知识共享许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.