How do I set up cron
to run a file just once at a specific time? One of the alternatives is at
but it is not accessible to all users on standard hosting plans. Therefore I was wondering whether there is way to do it using cron
?
-
I have tried running `$at = shell_exec('at');` on standart LAMP server and it returned NULL. Therefore I asume it doesn't work (have permissions) by default. – Gajus Mar 29 '11 at 14:05
-
Is there an easy way to move this to ServerFault? It seems more appropriate there. – TomOnTime Aug 23 '22 at 17:36
7 Answers
You really want to use at
. It is exactly made for this purpose.
echo /usr/bin/the_command options | at now + 1 day
However if you don't have at
, or your hosting company doesn't provide access to it, you can have a cron job include code that makes sure it only runs once.
Set up a cron entry with a very specific time:
0 0 2 12 * /home/adm/bin/the_command options
Next /home/adm/bin/the_command needs to either make sure it only runs once.
#! /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

- 4,175
- 4
- 36
- 39
-
The + is for "You really want to use at. It is exactly made for this purpose.", because that's so true... I did only just find out about it though; so, why not use it's own CLI? Unless the current interaction perhaps added after 2015, in which case my question isn't really applicable.. – Jun 19 '17 at 18:38
-
2You don't have to `echo` the command into "at". Its just something I do because eventually I automate everything. – TomOnTime Jun 19 '17 at 19:04
-
Hi @Tomontime, I wonder if one can trigger reboot like this (without cron), since that needs sudo/root - like `echo "reboot" | at now + 9 hour` – Valter Ekholm Dec 22 '20 at 15:51
-
1@ValterEkholm You can do that. However you might get better results by using `shutdown` and specifying the right flags to reboot, and to delay by 9 hours. The benefit of using the shutdown command is that it has built-in facilities to abort a reboot; people might be more familiar with those flags than `atq`. The downside is that `shutdown` has different flags on Linux, *BSD, Solaris, etc. – TomOnTime Dec 23 '20 at 16:22
-
Aha, thanks, now I get the idea - not use "at" / just "shutdown with flags" – Valter Ekholm Dec 27 '20 at 18:43
Try this out to execute a command on 30th March 2011 at midnight:
0 0 30 3 ? 2011 /command
WARNING: As noted in comments, the year column is not supported in standard/default implementations of cron. Please refer to TomOnTime answer below, for a proper way to run a script at a specific time in the future in standard implementations of cron.
-
so this will make it run only once? well, seemingly. However, is there any way to convert timestamp to crong time format? – Gajus Mar 29 '11 at 14:13
-
You should probably omit the 'Day of week' field by using a question mark (?). – gparis Mar 29 '11 at 14:43
-
2From Wikipedia: http://en.wikipedia.org/wiki/Cron#Special_Characters ... The '?' character is used to omit the specification of a value for the day-of-month and day-of-week fields. Since it's not valid to specify values for both fields, '?' becomes necessary to omit one of either ('*' is considered a specific value). – gparis Mar 29 '11 at 15:04
-
If I'm correct, does this add a line every time you execute this? Or will it remove itself from the crontab list after it's done? – Martijn Oct 21 '14 at 13:52
-
You may edit the crontab file and remove the scheduled job after it has been executed. – gparis Oct 21 '14 at 14:32
-
4
-
2There is no year in "standard" crontab. But checkout this question: http://stackoverflow.com/questions/7724316/how-can-i-specify-time-in-cron-considering-year - some implementations do allow it. – Matthew Wilcoxson Dec 07 '15 at 11:17
-
This will run on March 30 every year for normal "cron"s without a year specification. https://crontab.guru/#0_0_30_3_* – Katie Aug 08 '18 at 17:00
-
Downvoted. This answer does not run once, as the original question requests. – Sopalajo de Arrierez Jul 25 '19 at 19:33
You really want to use at
. It is exactly made for this purpose.
echo /usr/bin/the_command options | at now + 1 day
However if you don't have at
, or your hosting company doesn't provide access to it, you could make a self-deleting cron entry.
Sadly, this will remove all your cron entries. However, if you only have one, this is fine.
0 0 2 12 * crontab -r ; /home/adm/bin/the_command options
The command crontab -r
removes your crontab entry. Luckily the rest of the command line will still execute.
WARNING: This is dangerous! It removes ALL cron entries. If you have many, this will remove them all, not just the one that has the "crontab -r" line!
-
5Moderator note: this is not a repost of [Tom's other answer here](https://stackoverflow.com/a/30378470/100297), this is an alternative answer using a different technique. – Martijn Pieters Nov 28 '16 at 16:57
You could put a crontab file in /etc/cron.d
which would run a script that would run your command and then delete the crontab file in /etc/cron.d
. Of course, that means your script would need to run as root.

- 11,045
- 14
- 66
- 89

- 4,321
- 2
- 26
- 29
Your comment suggests you're trying to call this from a programming language. If that's the case, can your program fork a child process that calls sleep then does the work?
What about having your program calculate the number of seconds until the desired runtime, and have it call shell_exec("sleep ${secondsToWait) ; myCommandToRun");

- 11,045
- 14
- 66
- 89

- 11,957
- 4
- 29
- 37
-
You are right: I am trying to run it from PHP. What if the secondsToWait is [..] 60*60*24*30, that is, 30 days? wouldn't it eventually kill the server? (and I need to start more than one job; hundreds [but they must run at different times]) – Gajus Mar 29 '11 at 14:16
-
You didn't say anything in your question about the time being a month away. Of course that changes things. – dj_segfault Mar 31 '11 at 04:56
For those who is not able to access/install at
in environment, can use custom script:
#!/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
Let's name the script as run1time.sh Example could be something like:
nohup bash run1time.sh /path/to/your/script.sh 202008150300 &

- 29
- 1
- 2
-
-
@NVS Abhilash this is real working workaround, alternative to at command. Year column in cron is not supported in standard/default implementations. – Zaur Hajili Aug 15 '20 at 21:51
at
is the correct way.
If you don't have the at
command in the machine and you also don't have install privilegies on it, you can put something like this on cron
(maybe with the crontab
command):
* * * 5 * /path/to/comand_to_execute; /usr/bin/crontab -l | /usr/bin/grep -iv command_to_execute | /usr/bin/crontab -
it will execute your command one time and remove it from cron
after that.

- 1,056
- 3
- 13
- 31