如何设置 cron 在特定时间只运行一次文件? [关闭]

Posted

技术标签:

【中文标题】如何设置 cron 在特定时间只运行一次文件? [关闭]【英文标题】:How do I set up cron to run a file just once at a specific time? [closed] 【发布时间】:2011-07-25 07:58:06 【问题描述】:

如何设置cron 在特定时间只运行一次文件?替代方案之一是at,但并非所有使用标准托管计划的用户都可以访问它。因此我想知道是否有办法使用cron 来做到这一点?

【问题讨论】:

我尝试在标准 LAMP 服务器上运行 $at = shell_exec('at');,它返回 NULL。因此我认为默认情况下它不起作用(具有权限)。 【参考方案1】:

你真的想使用at。它正是为此目的而制作的。

echo /usr/bin/the_command options | at now + 1 day

但是,如果您没有 at,或者您的托管公司不提供对其的访问权限,您可以让 cron 作业包含确保它只运行一次的代码。

设置一个具有非常具体时间的 cron 条目:

0 0 2 12 * /home/adm/bin/the_command options

下一个 /home/adm/bin/the_command 需要确保它只运行一次。

#! /bin/bash

COMMAND=/home/adm/bin/the_command
DONEYET="$COMMAND.alreadyrun"

export PATH=/usr/bin:$PATH

if [[ -f $DONEYET ]]; then
  exit 1
fi
touch "$DONEYET"

# Put the command you want to run exactly once here:
echo 'You will only get this once!' | mail -s 'Greetings!' me@example.com

【讨论】:

+ 表示“你真的想使用 at。它正是为此目的而制作的。”,因为这是真的……不过我只是发现了它;那么,为什么不使用它自己的 CLI?除非当前的交互可能在 2015 年之后添加,在这种情况下我的问题并不适用.. 您不必将echo 命令转换为“at”。这只是我做的事情,因为最终我会自动化一切。 嗨@Tomontime,我想知道是否可以像这样触发重启(没有cron),因为这需要sudo/root - 比如echo "reboot" | at now + 9 hour @ValterEkholm 你可以这样做。但是,通过使用shutdown 并指定正确的标志来重新启动并延迟 9 小时,您可能会获得更好的结果。使用shutdown 命令的好处是它具有中止重启的内置功能;人们可能比atq 更熟悉这些标志。缺点是shutdown 在 Linux、*BSD、Solaris 等上有不同的标志。 啊哈,谢谢,现在我明白了 - 不要使用“at”/只是“使用标志关闭”【参考方案2】:

尝试在 2011 年 3 月 30 日午夜执行命令:

0 0 30 3 ? 2011  /command

警告:如 cmets 中所述,year 列在 cron 的标准/默认实现中不受支持。请参考TomOnTime answer below,了解在cron的标准实现中在未来特定时间运行脚本的正确方法。

【讨论】:

所以这会让它只运行一次?好吧,貌似。但是,有什么办法可以将时间戳转换为cron时间格式吗? 您应该使用问号 (?) 省略“星期几”字段。 来自***:en.wikipedia.org/wiki/Cron#Special_Characters ... '?'字符用于省略指定日期和星期几字段的值。由于为两个字段指定值是无效的,“?”有必要省略其中之一('*' 被视为特定值)。 嗯?什么时候“年”被添加为一列。你能解释一下吗? “标准”crontab 中没有年份。但是检查这个问题:***.com/questions/7724316/… - 一些实现确实允许它。【参考方案3】:

你真的想使用at。它正是为此目的而制作的。

echo /usr/bin/the_command options | at now + 1 day

但是,如果您没有 at,或者您的托管公司不提供对它的访问权限,您可以创建一个自删除 cron 条目。

遗憾的是,这将删除您的所有 cron 条目。不过,如果你只有一个,这很好。

0 0 2 12 * crontab -r ; /home/adm/bin/the_command options

命令crontab -r 删除您的crontab 条目。幸运的是,命令行的其余部分仍然会执行。

警告:这很危险!它删除所有 cron 条目。如果你有很多,这会将它们全部删除,而不仅仅是具有“crontab -r”行的那个!

【讨论】:

版主注意:这不是Tom's other answer here的转贴,这是使用不同技术的替代答案。【参考方案4】:

您可以在/etc/cron.d 中放置一个crontab 文件,该文件将运行一个脚本来运行您的命令,然后删除/etc/cron.d 中的crontab 文件。当然,这意味着您的脚本需要以 root 身份运行。

【讨论】:

【参考方案5】:

您的评论表明您正在尝试从编程语言中调用它。如果是这种情况,你的程序可以派生一个调用睡眠的子进程然后工作吗?

让您的程序计算距离所需运行时间的秒数,并让它调用shell_exec("sleep $secondsToWait) ; myCommandToRun");

【讨论】:

你是对的:我正在尝试从 php 运行它。如果 secondsToWait 是 [..] 60*60*24*30,也就是 30 天怎么办?它最终不会杀死服务器吗? (而且我需要开始一份以上的工作;数百份[但它们必须在不同的时间运行]) 您在问题中没有提到一个月后的时间。当然,这会改变一些事情。【参考方案6】:

at 是正确的方法。

如果您的机器中没有at 命令并且您也没有安装权限,您可以在cron 上放置类似的内容(可能使用crontab 命令):

* * * 5 * /path/to/comand_to_execute; /usr/bin/crontab -l | /usr/bin/grep -iv command_to_execute | /usr/bin/crontab - 

它会执行一次您的命令,然后将其从cron 中删除。

【讨论】:

【参考方案7】:

对于无法在环境中访问/安装at的用户,可以使用自定义脚本:

#!/bin/bash
if [ $# -lt 2 ]; then
echo ""
echo "Syntax Error!"
echo "Usage: $0 <shell script> <datetime>"
echo "<datetime> format: %Y%m%d%H%M"
echo "Example: $0 /home/user/scripts/server_backup.sh 202008142350"
echo ""
exit 1
fi

while true; do
  t=$(date +%Y%m%d%H%M);      
  if [ $t -eq $2 ]; then
    /bin/bash $1
    echo DONE $(date);
    break;
  fi;
  sleep 1;
done

我们将脚本命名为 run1time.sh 示例可能类似于:

nohup bash run1time.sh /path/to/your/script.sh 202008150300 &

【讨论】:

这似乎无法回答问题。 @NVS Abhilash 这是真正可行的解决方法,可以替代 at 命令。标准/默认实现不支持 cron 中的年份列。

以上是关于如何设置 cron 在特定时间只运行一次文件? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

每分钟运行一次 cron 作业,但从特定时间开始

如何在AWS Windows实例中运行Cron作业(事件计划)

仅在特定时间每分钟运行一次 cron 作业?

将 cron 选项卡设置为工作日的特定时间

Cron 作业每 x 周和特定日期运行一次 [关闭]

cron 表达式 每分钟从特定时间开始