重新启动计算机后如何继续执行脚本?


18

我正在用bash写一个shell脚本。在脚本中的某个时刻,它检测到机器需要重新启动才能继续。它发出:

sudo reboot

当计算机重新启动时,此脚本需要做更多的工作。如何配置某些内容以继续执行此脚本中的工作?

我假设有一些地方可以写一个shell脚本,以便它将在下次重新启动时执行。这样的地方在哪里?我看到cron有一个@reboot指令。我也知道Apache之类的服务是由upstart在启动时启动的。这两个都是合适的机制吗?如果是这样,它将如何被触发?

该脚本仅需要运行一次,而无需每次重新启动。因此,它必须移至仅在下次重新启动时运行的某个位置,或者一旦运行即可将其自身删除。

该问题询问有关重新启动后如何保存应用程序状态的信息。我的脚本没有太多状态,因此我可以进行管理。我只需要知道如何让此脚本在下次重新启动后触发某些程序即可运行。

我的特定版本是Ubuntu Linux 14.04。原始脚本由系统管理员在命令行中启动(与从cron运行相反)。


仅在无法避免的情况下,才应使用脚本中的重新启动。例如,新的内核安装。我确定您无需重新启动就可以完成工作。您能指定为什么需要重启吗?
混乱

1
该脚本会安装一个新内核(或者调用apt upgrade可能会这样做)。它还会在重新启动之前检查是否确实需要重新启动。
Stephen Ostermiller 2014年

“只能在无法避免的情况下使用脚本中的重新启动。” -@chaos为什么?
约翰·雷德

Answers:


16

在系统上,唯一真正持久的是文件。那几乎是您应该使用的。这是使用init.d脚本的解决方案。

让我们考虑以下(简单)脚本/etc/init.d/myupdate

#! /bin/sh

### BEGIN INIT INFO
# Provides:          myupdate
### END INIT INFO

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

case "$1" in
    start)
        /path/to/update/script
        ;;
    stop|restart|reload)
        ;;
esac

如果使用激活它update-rc.d myupdate defaults,则该start操作将在启动时执行。现在,当您的更新脚本要求重新启动时:

touch /var/run/rebooting-for-updates
sudo reboot

使用此解决方案,您可以将更新脚本分为两部分:

before_reboot(){
    # Do stuff
}

after_reboot(){
    # Do stuff
}

if [ -f /var/run/rebooting-for-updates ]; then
    after_reboot
    rm /var/run/rebooting-for-updates
    update-rc.d myupdate remove
else
    before_reboot
    touch /var/run/rebooting-for-updates
    update-rc.d myupdate defaults
    sudo reboot
fi

它将执行before_reboot代码部分,在中创建文件/var/run,然后重新启动。引导时,将再次调用该脚本,但是由于该文件存在,after_reboot因此将调用而不是before_reboot

请注意,这update-rc.d需要root特权。

不使用文件(来自Stephen Ostermiller的评论):

如果您熟悉该getopts实用程序,则可能要使用选项而不是文件。在初始化脚本中,使用以下命令调用脚本:

/path/to/update/script -r

然后在脚本中,检查选项而不是文件。不带选项调用一次脚本,init.d将在引导时再次调用它,这次使用-r

# Set AFTER_REBOOT according to options (-r).

if [ "x$AFTER_REBOOT" = "xyes" ]; then
    # After reboot
else
    # Before reboot
fi

您可以在此处找到有关选项处理的更多信息(仅适用于简短选项)。我还通过调用来编辑脚本,update-rc.d以保持这项一次性工作(来自另一条评论)。


2
这可能是简单的调用/path/to/update/script --after-reboot/etc/init.d/myupdate,而不是依靠的存在/var/run/rebooting-for-updates。然后,在直接运行与在引导时调用时,它将具有不同的参数。
Stephen Ostermiller 2014年

好人之一,没有考虑选项。请允许我编辑;)
约翰·史密斯

1
另外,由于这是一项一次性的工作,因此我可能希望将update-rc.d myupdate defaults和添加update-rc.d myupdate remove到脚本本身中,以及编写和删除该脚本,/etc/init.d/myupdate以免文件停滞不前。
斯蒂芬·奥斯特米勒

我已经实现了,效果很好。我要添加的唯一的另一件事是我的基于Debian的系统在该INIT INFO部分中需要其他项目:wiki.debian.org/LSBInitScripts
Stephen Ostermiller 2014年

我真的想保持简单;)编写适当的init.d会花费一些时间,但是很高兴您能获得更多信息:这些脚本非常方便。
约翰·史密斯
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.