如何在 Linux 系统关机时运行命令

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

Opensource.com

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

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

在此我应该澄清一下,我所说的是所谓的“一次性”命令,而不是停止守护进程。尽管如此,很容易将它们视为同一种方式。如果您熟悉 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 仅在英特尔和三星固态硬盘上每周运行一次 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 命令一起。这比依赖 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 脚本吗?

TIA

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