关闭前执行命令


52

我想在计算机关闭之前执行一个简单的命令(定时不是必不可少的)。

对于启动,我可以使用/etc/rc.local; 是否有类似的关机方法?

请注意,我仍然想使用菜单中的集成关机按钮。即我不想每次通过终端关闭时都使用自定义脚本-它需要是自动的。

Answers:


42

Linux Mint基于Ubuntu,因此我猜测运行级别系统可能是相同的。在Ubuntu上,根据不同运行级别的脚本在/etc/rc[0-6].d目录中的存在来执行。运行级别 0对应于关闭,运行级别 6对应于重新启动。

通常,脚本本身存储在中/etc/init.d,然后将符号链接放置在与您所需的运行级别相对应的目录中。

因此,在您的情况下,编写您的脚本,将其存储在中/etc/init.d/,然后在指向/etc/rc0.d/etc/rc6.d(如果需要两者)的每个中创建一个符号链接。

每个运行级别目录中的脚本将按照升序顺序执行,因此,如果运行级别内的顺序对您很重要,请相应地选择符号链接的名称。


我只是看了init.d(精确的Kubuntu)中的骨架文件,并感到有些害怕。我只想添加一些命令,将关闭日期回显到/ var / log下的文件中。我可以这样做还是必须处理框架文件中的其他一些内容?
2012年

2
@Joe-不需要大多数东西,除非您希望脚本作为标准服务可控。您只需简单地回显自己的日志文件就不会破坏任何内容,因此请尝试一下。
ire_and_curses 2012年

1
是一个简单的示例init.d脚本。另外,使用sudo update-rc.d /etc/init.d/myservice defaults
RolfBly 2014年

我已经编写了/etc/init.d/spark_shutdown.sh并在/etc/rc0.d和/etc/rc6.d中创建了链接,现在我如何确认此脚本在ubuntu aws ec2实例中运行
Ashish Karpe

10

现在,Ubuntu变体和Mint已迁移到systemd,我发现基于上述内容的旧解决方案不太令人满意。我在网上搜索了有关如何使用systemd进行搜索的信息,最后结合了其他人的智慧并将其记录为blogspot.com.au上的博客文章,其中包含以下教程。

使用systemd,您可以创建一个或两个文件,以使用以下模板调用脚本,并执行几个命令。简单。


GUI版本

首先创建要在启动和/或关闭时运行的脚本。我创建了.scopening_atstart和.scfullcopy_atend。

然后,通过右键单击文件,选择属性并确保在权限下选中了“允许将文件作为程序执行”,以确保它们都可执行。

我创建的两个文件填充并保存了虚拟磁盘的内容。他们还在我的主目录中创建一个文件,以证明该服务正在运行。它们的形式为:

#!/bin/sh
cp -pru /home/john/zRamdisk/subdirectory1/* /home/john/.wine/drive_c/subdirectory1/
rm /home/john/stop_time
date +%D' '%T > /home/john/stop_time

然后,我以root用户身份打开文件管理器,打开/etc/systemd/system并创建了文件startup.service和文件save-ramdisk.service。显然,您可以选择自己的名称,通用名称可能包含一个名为johns_start.service的启动文件和一个名为johns_shutdown.service的关机文件。只是不要选择现有的服务名称。

[Unit]
Description=Startup Applications

[Service]
Type=oneshot
RemainAfterExit=false
ExecStart=/home/john/.scopening_atstart

[Install]
WantedBy=multi-user.target

[Unit]
Description=Save Ramdisk to Wine drive C

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=/home/john/.scfullcopy_atend

[Install]
WantedBy=multi-user.target

您可以使用相同的服务文件,用可执行脚本的完整路径替换我的。

最后,对于每个命令,执行命令systemctl enable your_files_name(但不带后缀服务)。所以我的第一个是systemctl enable startup

重新启动计算机一次以启动服务。每当systemd进入多用户目标时,将执行启动服务,而当退出多用户目标时,将执行停止服务。下面将介绍具有不同激活条件的替代服务文件。


CLI(命令行)版本

该描述假定您是从主目录而不是/ home / john进行操作,并根据需要使用sudo,并选择在我编写vim或svim的编辑器。

在第一行创建启动和关闭Shell脚本,#!/bin/sh并使用使其可执行chmod +x my_new_filename

如上创建两个文件,或者在此示例中,创建一个文件来处理启动和关闭任务。我将在我的主目录中执行脚本,但是@don_crissti在Stack Exchange上显示了一些替代方法。

vim /etc/systemd/system/start_and_stop.service

并复制文件内容:

[Unit]
Description=Run Scripts at Start and Stop

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/home/john/.startup_commands  #your paths and filenames
ExecStop=/home/john/.shutdown_commands

[Install]
WantedBy=multi-user.target

然后使用以下命令启用服务

systemctl enable start_and_stop

并重新启动系统,之后这些服务将被激活。这些命令systemctl is-enabled start_and_stopsystemctl is-active start_and_stop可用于监视新服务。


更改关机的触发条件

首先,这些文件使用多用户环境的打开或关闭来启动运行脚本。下面的文件使用四个可能的关闭过程的开始来启动其脚本。在Before行+ WantedBy行上添加或删除目标,可以使您更好地区分:

此文件是在本文的第二个答案提出的,但是直到添加安装部分,我才能使其运行。

同样,在中编辑脚本/etc/systemd/service/并使用启用它systemctl enable your_file_name。更改目标时,我使用了该systemclt disable file_name命令,然后重新启用了该命令,将其符号链接到目标目录。重新启动,该服务将运行。

[Unit]
Description=Do something required
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target
# This works because it is installed in the target and will be
#   executed before the target state is entered
# Also consider kexec.target

[Service]
Type=oneshot
ExecStart=/home/john/.my_script  #your path and filename

[Install]
WantedBy=halt.target reboot.target shutdown.target

7

您需要rc.shutdown为Linux内核使用关闭脚本。引用OpenBSD手册页

当使用reboot(8)或halt(8)命令关闭系统时,或者发出init(8)信号时,或者发出键盘请求的停止命令(如果体系结构支持)时,rc( 8)用参数``shutdown''调用。

因此,您只需打开rc.shutdown并向其中添加任何要执行的shell命令。

更新:由于Linux Mint基于Ubuntu,而Ubuntu具有不同的启动/关闭过程,因此以下是与您相关的过程:

编写要执行的Shell脚本,然后将其复制到您的.NET中的相关目录中/etc/rc*.d/。该*对应于运行级别为您想要的脚本来执行。
Ubuntu遵循Debian运行级别编号,因此您具有运行级别0(用于暂停)和运行级别6(用于重新引导)。


1

对于Debian Wheezy,Devuan及其派生产品以及其他产品中使用的基于SysV依赖关系的初始化系统,您可以模拟rc.shutdown类似物的行为,rc.local如下所示:

将命令添加到以下框架/etc/rc.shutdown

#!/bin/sh -e
#
# rc.shutdown
#

# <add your commands here, before exit 0>

exit 0

保存脚本并使用将该文件可执行chmod a+x /etc/rc.shutdown

然后,将/etc/init.d/rc.shutdown具有以下内容的新脚本添加到系统中:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          rc.shutdown
# Required-Start:
# Required-Stop:
# X-Stop-After:      umountroot
# Default-Start:
# Default-Stop:      0 6
# Short-Description: Run /etc/rc.shutdown if it exist
### END INIT INFO


PATH=/sbin:/usr/sbin:/bin:/usr/bin

. /lib/init/vars.sh
. /lib/lsb/init-functions

do_stop() {
    if [ -x /etc/rc.shutdown ]; then
            [ "$VERBOSE" != no ] && log_begin_msg "Running local shutdown scripts (/etc/rc.shutdown)"
        /etc/rc.shutdown
        ES=$?
        [ "$VERBOSE" != no ] && log_end_msg $ES
        return $ES
    fi
}

case "$1" in
    start)
        # No-op
        ;;
    restart|reload|force-reload)
        echo "Error: argument '$1' not supported" >&2
        exit 3
        ;;
    stop|status)
    do_stop
        exit 0
        ;;
    *)
        echo "Usage: $0 start|stop" >&2
        exit 3
        ;;
esac

同时使该脚本可执行。

在/etc/rc[06].d中创建符号链接:

cd /etc/rc0.d ; ln -s ../init.d/rc.shutdown K01rc.shutdown

cd /etc/rc6.d ; ln -s ../init.d/rc.shutdown K01rc.shutdown

使用insserv纠正符号链接,并创造必要的.depend.boot,.depend.start和.depend.stop文件:

insserv -v

您需要是root用户或对上述所有命令使用sudo。


我今天在这上面浪费了一点时间,无法使其与Ubuntu 16一起使用,也许是我自己,但是上面的解决方案立即起作用了。
Mike Q
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.