在启动(或重新启动/关闭)时运行脚本但前提是今天尚未执行的最简单方法?

在启动(或重新启动/关闭)时运行脚本但前提是今天尚未执行的最简单方法?

你知道的最简单的方法是什么?使用任何工具

答案1

在脚本的开头,只需触摸某处的标志,以便该脚本的后续调用可以检查该标志的存在和寿命。

你的问题有些含糊不清。首先,我们假设您要问“如何使脚本仅在自上次执行脚本以来经过一定时间后才执行”。

#!/bin/bash
flag="/var/tmp/$(basename -- $0).flag"
min_age=$(( 60 * 60 * 24 )) # 24 hours

if [ -e "$flag" ] ;then
  (( $(date +%s) - $(date +%s -r "$flag") > min_age )) || exit 1
fi
touch "$flag"

# Proceed with your script
# ...

但是,如果您问“如何使脚本仅在自午夜以来尚未执行过的情况下才执行”......

#!/bin/bash
flag="/var/tmp/$(basename -- $0).flag"

if [ -e "$flag" ] ;then
  [ $(date +%F) = $(date +%F -r "$flag") ] && exit 1
fi
touch "$flag"

# Proceed with your script
# ...

--

如果您只是问“如何在关机时运行脚本”——那么不同发行版的情况差异很大。您很可能需要调查一下/etc/rc6.d。例如,在我的系统上,我有/etc/rc.d/rc.local_shutdown,我可以在其中添加内容。您需要提及您正在使用的发行版。

或者看看这个线程... 关机前执行命令

答案2

最简单很大程度上是一个问题观点,但我觉得最简单的方法就是使用cron.您将需要一些其他“成分”来实现您的目标,但cron可以充当定时启动脚本的调度程序boot。这假设cron您系统上的版本提供了该@reboot功能;请参阅man 5 crontab验证是否允许使用“特殊”字符串(@reboot@yearly等)。

也就是说,使用cron就像编辑用户的crontab.从您的bash命令行:

$ crontab -e

这将crontab在您的默认编辑器中打开您的。添加以下行:

@reboot sleep 15; /path/to/your/script >> /path/to/your/iofile.txt 2>&1

这会在每次系统启动时运行您的脚本。

  • 由于cron不知道脚本中所需的任何服务的状态,因此该sleep 15命令用于给操作系统 15 秒的时间来整理所有所需的系统资源。您可能需要比这更多或更少,具体取决于所需的资源和其他变量。

  • crontab在您的as中使用完整路径规范环境(特别是PATH)与交互式 shell 中的不同。

  • 脚本输出将会stderrstdout应该是重定向到本地文件(io文件.txt这里)。这io文件.txt文件将提供一种简单的方法来访问脚本引发的任何错误 - 对于调试非常有帮助!

您已要求应用一个条件来运行您的脚本@reboot“但前提是今天尚未执行”。这意味着有一个该脚本可能已由用户手动执行的可能性,或者系统可能已在同一天之前重新启动过。

当然,满足该条件取决于您的定义“今天”;即过去 24 小时内的“今天”,或同一日期的“今天”。

对于这种情况today=24 hours or less,您的条件可能满足如下:

#!/bin/bash
LAST_BOOT=$(cat /path/to/your/timestamp.txt)
CURRENT_BOOT=$(date +%s)
ELAPSED_TIME=$((CURRENT_BOOT - LAST_BOOT))
echo $CURRENT_BOOT > /path/to/your/timestamp.txt
# test ELAPSED_TIME < threshold
if [ $((ELAPSED_TIME <= 86400)) ]; then exit; fi

# the balance of your script follows...

注意使用+%s格式date给出纪元时间;这使我们能够减去检查两次开机时间是否为24小时(86,400秒)。

对于这种情况today=same date,您的条件可能满足如下:

#!/bin/bash
LAST_BOOT=$(cat /path/to/your/timestamp.txt)
CURRENT_BOOT=$(date +%d)
# test for same date
if [ $((CURRENT_BOOT = LAST_BOOT)) ]; then exit; fi 

# the balance of your script follows...

请注意,date +%d格式仅提供日期。我们测试语句中上次启动时间与当前时间之间的相等性,if这意味着脚本已在该日期运行。

或者:

在考虑了您刚才的所有评论之后,您不妨考虑一下anacron。它的使用不像 那样广泛cron,但它确实有一个优点,即它的@daily时间表“将任务移动到不同的时刻,以便它们在系统启动时运行”。您可能还想比较一下它的优点,及其缺点相比cron。如果你想深入挖掘,这可能有帮助

答案3

你可以考虑使用纳克朗

Anacron 允许在并非一直打开的计算机上安排定期作业。为了实现这一点,它维护所谓的时间戳文件,记录上次运行作业的时间。当计算机打开时,anacron 会通过各种机制(启动脚本、常规 cron 作业、systemd 计时器)定期触发,并根据时间戳文件启动到期作业。

使用 anacron,为了每天运行一次命令,您需要将这样的行放入/etc/anacrontab

@daily  0   daily-job   command
  • 第一个字段是频率,可以是@daily@weekly@monthly以及任意天数(例如,2每 2 天)。

  • 第二个字段是 anacron 被触发后开始运行作业的延迟。

  • 第三个字段是职位名称。

  • 最后,第四个字段是要执行的命令。

在 Debian 衍生产品上,您可以将脚本放入/etc/cron.daily其中,因为 anacron(如果已安装)默认接管运行每日、每周和每月 cron 作业的任务。

另一种选择是氟龙,它允许做同样的事情(甚至可能更多),但我没有个人经验。

相关内容