![在启动(或重新启动/关闭)时运行脚本但前提是今天尚未执行的最简单方法?](https://linux22.com/image/13853/%E5%9C%A8%E5%90%AF%E5%8A%A8%EF%BC%88%E6%88%96%E9%87%8D%E6%96%B0%E5%90%AF%E5%8A%A8%2F%E5%85%B3%E9%97%AD%EF%BC%89%E6%97%B6%E8%BF%90%E8%A1%8C%E8%84%9A%E6%9C%AC%E4%BD%86%E5%89%8D%E6%8F%90%E6%98%AF%E4%BB%8A%E5%A4%A9%E5%B0%9A%E6%9C%AA%E6%89%A7%E8%A1%8C%E7%9A%84%E6%9C%80%E7%AE%80%E5%8D%95%E6%96%B9%E6%B3%95%EF%BC%9F.png)
你知道的最简单的方法是什么?使用任何工具
答案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 中的不同。脚本输出将会
stderr
或stdout
应该是重定向到本地文件(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 作业的任务。
另一种选择是氟龙,它允许做同样的事情(甚至可能更多),但我没有个人经验。