I need to run a script every 64 hours. I couldn't find the answer with
cron. Is it possible with it, or should I use a loop in a shell script?
I suggest perhaps using a crontab "front end" like crontab.guru for figuring out crontab if you're a beginner.
However, as in your case, the hour setting only allows for values of 0 to 23, so you can't use crontab here.
Instead, I'd suggest using
at. In your case, I'd probably use something like:
at now + 64 hours
and then enter your command or
echo "<your command>" | at now + 64 hours
at the beginning of your script, etc.
Basically, you'll be scheduling running the command right when the command has been invoked the last time. Also, if you don't want a time delta, rather the exact time, I suggest doing a bit of time arithmetic, and then use an exact time with
at to have the command run.
I highly suggest reading the man page of
at, as it is fairly comprehensive.
cron is made to run things on date or clock events, i.e. every 1st of a month or week or every third hour of a day, respectively.
For running things in time intervals that cannot be simply expressed by arithmetics on clock time or dates, I'd suggest using a
systemd timer - which of course works only if you have
systemd running on your respective device.
You will need two files, the service file to run the script and the timer file for managing the events.
$cat /etc/systemd/system/myscript.service [Unit] Description=this service runs my script [Service] ExecStart=/full/path/to/myscript.sh #[Install] #WantedBy=multi-user.target
This service simply executes the script without checking if it succeeded or anything. Optionally enable the service via
systemctl enable myscript.service which means it will be executed once during boot time - I commented this out, because the timer will take care of boot events. You may manually run your script by
systemctl start myscript.service.
$cat /etc/systemd/system/myscript.timer [Unit] Description=this timer runs myscript.service every 64h [Timer] OnBootSec=120 OnUnitActiveSec=64h [Install] WantedBy=timers.target
This is the timer to run the
myscript.service every 64h since the last activation of the service as well as two minutes after boot time (to ensure that the system is in the right state for the service to run).
Note that the timer will not remember the 64h if you reboot/power off. Enable and start the timer accordingly:
systemctl enable myscript.timer systemctl start myscript.timer
Since the timer only starts after a boot or since the last unit activation, you will have to run the service once to ensure the timer runs:
systemctl start myscript.service
Check the status of the timers by
64 hours is 2 and 2/3 days, so 3 * 64 hours = 192 hours = 8 days. So you could almost do
0 0 1-25/8 * * foo 0 16 3-27/8 * * foo 0 8 6-30/8 * * foo
except that you get a short pattern at the end of the month (if the month has 30 days, then there will be only 16 hours between the run at 08:00 on the 30th and the one at 00:00 on the 1st; if the month has 31 days, it will be 40 hours; if the month has 28 days, it will be 32 hours between the run at 16:00 on the 27th and the one at 00:00 on the 1st; if the month has 29 days, it will be 56), and also things will be off by 1 hour whenever your locality goes on or comes off of summer time (assuming it does).
Doesn't quite meet your specs (and I endorse any of the other answers that do), but it is an interesting exercise in making do.