Table of Contents
If you want to send us your comments, please do so. Thanks
More on comments
cron
cron mail filter: cron-deja-vu. It filters unwanted recurring cron e-mails,
incron: cron-like daemon which handles filesystem events. incron is an “inotify cron” system driven by filesystem events instead of time events.
Edit with incrontab -e
Main rule
Always put the code in a script
Start the script with
#! /bin/bash
Then call the script from cron. If you do not you can get something like
/bin/sh: 1: [[: not found
in the case you used an [[ statement for example
Use DISPLAY:0
DISPLAY=:0 needs to be added on a seperate line in the variables section, before the cron commands. This is needed for old Linux reasons whereby the audio is linked to the display. See Cron sechduling to play music using mpg123 issue:
For various reasons, audio playing is typically attached to where the display (X server) is running on Linux. The cron process doesn't know about any display settings for the system, so can't play audio unless you tell it how. (This is one of the old and confusing bits about ‘the Unix way’ that I wish would go away forever. How much sense does it make to have to do something about a display when you want audio? None!)
manpages
man 8 cron man 1 crontab man 5 crontab man 8 run-parts
Environment variables
Variable | Remark |
---|---|
HOME=/home/user | This is an example |
LOGNAME | May NOT be changed |
MAILTO=user | user to send the output e-mail to. user can also be a full e-mail address like something@somewhere.tld |
PATH=/home/user | This is an example |
SHELL=/bin/bash | The default shell is “/bin/sh” |
DISPLAY=:0 | Define the display for GUI output and audio output. Or DISPLAY=:0.0 |
XAUTHORITY=/home/user/.Xauthority | Needed for DISPLAY |
XDG_RUNTIME_DIR=“/run/user/1000” | Needed for DISPLAY |
LOCALES | All variables from the locales |
Job definition
/etc/crontab
# .---------------- minute (0 - 59) # | .------------- hour (0 - 23) # | | .---------- day of month (1 - 31) # | | | .------- month (1 - 12) OR jan,feb,mar,apr ... # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat # | | | | | # * * * * * user-name command to be executed
crontab -e
This is about the users own crontab. user-name is not needed
# .---------------- minute (0 - 59) # | .------------- hour (0 - 23) # | | .---------- day of month (1 - 31) # | | | .------- month (1 - 12) OR jan,feb,mar,apr ... # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat # | | | | | # * * * * * command to be executed
More of the same
When a command has to be executed several times on a day, day of month, month, day of week use, example:
List | 3,6,7 | Execute at 3 and 6 and 7 | |
Range | 5-9 | Execute at 5 and 6 and 7 and 8 and 9 | |
Step | 3/5 | Execute at 3 and 8 and 13 and 18 and 23 | Does not work in Debian |
Step | */20 | Execute at 20 and 40 | Does work in Debian |
dow (day of the week)
0 or 7 Sun(day)
Use the day of the week number, the full day name or the three letter shortended version like in the sunday options example above or have a look in this table
0 Sun SUN Sunday 1 Mon MON Monday 2 Tue TUE Tuesday 3 Wed WED Wednesday 4 Thu THU Thursday 5 Fri FRI Friday 6 Sat SAT Saturday 7 Sun SUN Sunday
A reference: Crontab day of the week syntax
Other time indicators
@reboot @hourly @daily @weekly @monthly
Skipping @reboot jobs
When @reboot is used and cron is restarted via systemctl restart cron.service you can get
aug 08 09:37:24 Hostname cron[10663]: (CRON) INFO (Skipping @reboot jobs -- not system startup)
because it is not a (re)boot, cron is not started at (re)boot
Output to audio
This (when DISPLAY=:0 is added before all jobs) worked on Buster. Not on Bookworm anymore:
43 * * * * mpg123 /home/user/someaudio.mp3 >> /dev/null 2>&1
Bookworm
On bookworm pipewire is used. Make sure cron has access to the pipewire user session
Turn this on via the pulseaudio support of pipewire via TCP
Copy the pulse.properties block from /usr/share/pipewire/pipewire-pulse.conf to ~/.config/pipewire/pipewire-pulse.conf.d/properties.conf and uncomment de tcp:4713 entry
Configure mpg123 to use the pulseaudio server on localhost
mpg123 http://localhost:4713 /home/user/audio.mp3
Output to GUI
Add to the cron envrironment variables (crontab -e)
DISPLAY=:0 #DISPLAY=:0.0 XAUTHORITY=/home/user/.Xauthority
Works for
/usr/bin/xmessage Helloxmessage /usr/bin/notify-send Hello
Or do something like
/bin/bash -c 'DISPLAY=:0 /usr/bin/xmessage Hello'
This does not work
/bin/bash -c 'DISPLAY=:0 /usr/bin/notify-send Hello'
MAILTO
When a script is ran from cron all echo output is send to the user via an e-mail
The e-mail address can be set with MAILTO=user, MAILTO=user@hostname or MAILTO=name@somedomain.tld
MAILTO=user@$HOSTNAME does not work
Put the MAILTO statement above the # m h dom mon dow command line
Output redirection to e-mail
Send output of a cron job to a specific user
7 * * * * somescript.sh | mail -s "Subject" name@e-mailprovider.com
Output redirection to a file
Send output to a file
7 * * * * somescript 2>&1 >> $HOME/cron.log 7 * * * * somescript >> $HOME/cron.log 2>&1
Do not send the output anywhere
7 * * * * somescript >/dev/null 2>&1
File locations
User cron
The crontab file is saved in /var/spool/cron/crontabs/username
To edit the crontab file run
crontab -e
System wide cron
Each entry also needs a username after the 5 time and date positions
/etc/crontab
General cron
/etc/cron.d
Fixed time files
/etc/cron.daily /etc/cron.weekly /etc/cron.monthly
cron options file
/etc/default/cron
systemd cron unit file
/etc/systemd/system/multi-user.target.wants/cron.service
init cron deamon file
/etc/init.d/cron
Separate cron log file
Recommended
As root do
- touch /var/log/cron.log
- chown root:syslog /var/log/cron.log
- chmod 664 /var/log/cron.log
- vi /etc/rsyslog.d/50-default.conf
- Remove the # at the line starting with #cron.*
- Save and close the file
- systemctl restart rsyslog
- systemctl status rsyslog
- Read the log: less -S /var/log/cron.log
Limitations
- Jobs can be missed on systems which are not on 24 hours a day. In that case use anacron. To run anacron jobs in user mode
- This is not true. In fact anacron is useless if you need to run a job again, after a reboot, within 24 hours. In that case use a script and add its execution to crontab. See an example below
- Under investigation: When the computer is started and presenting the login screen, no user is logged in, cron runs the cron jobs of all users including the root user on the computer
- Beep sounds are not played when the user is not logged in.
- Beep sounds are played when the user is logged in
- When audio is playing the audio played via cron might not be heard. This depends on the sound card. Some examples:
- Beep plays always from cron when the user is logged in
- When a mp3 file is playing with mpg123 a mp3 file played with mpg123 from cron plays also
- When a video is playing in a webbrowser a mp3 file played with mpg123 from cron does not play.
- The mp3 file played with mpg123 from cron plays when the video in the webbrowser is paused, this is not always the case. Reason unknown, under investigation
Example script
#! /bin/bash
CONSTAT=0 export CONSTAT if [[ $CONSTAT -eq 0 ]]; then #if ! [[ -f /tmp/34con.txt ]]; then if [[ $(nmcli connection show --active | tail -n 1 | tr -s ' ' | cut -d ' ' -f 1) == enp3s0 ]]; then nmcli -p con up "78 netwerk enp3s0 78.34" # con is hetzelfde als connection echo "Networkmanager connection changed to 78.34" else echo "Networkmanager connection is already at 78.34" fi CONSTAT=1 export CONSTAT # echo 34connection.sh has run on $(date) > /tmp/34con.txt fi
32 / 64 bit computers
It seems that cron has different behaviour on an 32 bit Debian system and an 64 bit Debian system
/etc/cron.daily and alike
Also valid for /etc/cron.hourly/ and /etc/cron.weekly/ and /etc/cron.monthly/ and probably also for /etc/cron.d/
Scripts in these directories are not allowed to have an extension, a dot in the filename. If they do they will not get executed.
cli differences to cron
chown
This command has to be run as root
When run from a normal cron job it results in an error
If run as
sudo chown user:user folder/
it works if
user ALL=(root:ALL) NOPASSWD:/bin/chown *\:* *
is added to the sudoers file. Do this as root with
visudo
echo
When using the -e option it only works fine in a script. Make sure to add #! /bin/bash at the first line of the script
When echo -e is used it is needed to do “\” expansion on the commandline and in scripts, not in cron
In cron -e is not needed, if used it will be displayed as literal -e. This works fine:
36,38 * * * * echo "Some test\t\t$(date)" >> $HOME/crontest.txt
The echo output in a script in the e-mail cron sends is the same for
echo -e "Some text" echo -e "\033[01;46;37mSome text\033[00m"
date
date +'%s' date "+%s" echo -e "\nDone at $(date +'%s') which is at $(date +'%d-%b-%Y %H:%M UTC')"
$USER
cron does not know about the user. So the $USER variable is empty. Demonstration: Add to cron:
* * * * * echo -e "$(date)\tuser: $USER" >> $HOME/crontest.txt
Check crontest.txt after a few minutes
Do not forget to turn this cronjob off after testing
Getting the username of the user on whose behave cron has executed the job can be achieved by using
USERcron=$(whoami) # The user who ran the script or on whose behave cron has ran
or with
USERcron=$(echo $HOME | cut -d / -f 3)
This works for both root and a normal user
Make sure to define user in every file called by an other file
Also
USERcron=$(id -u)
holds the user in cron. Only it is the numeric representation root being 0 and the first added user mostly 1000
Check if a script is run from cron or started by a user
Use $USER
Proof of concept
#! /bin/bash USERcron=$(whoami) # The user who ran the script or on whose behave cron has ran. # This works for both root and a normal user, interactive or ran from cron. echo "user_whoami: $user_whoami" echo USER: $USER # When ran interactive $USER has a value. When ran from cron $USER is empty if [[ -z $USER ]]; then # USER is an empty string so ran from cron interactive=1 #No, the script is initiated by cron echo -e "User is: $USER\tinteractive is: $interactive" echo -e "Ran from Cron" else # Double check if [[ -n $USER ]]; then # USER is a normal user. The sting is not empty interactive=0 #Yes, the script is initiated by the user echo -e "User is: $USER\tinteractive is: $interactive" echo -e "Initiated by the user, not ran from Cron" else echo Strange error when determining who ran this script fi fi
Use a variable
This does not work if you want to read calledfromcron in somescript.sh the variable unkown, its value is empty. nice -n 19 is just there for the demo
cron entry: * 20 23 6 2 export CALLEDFROMCRON=1; nice -n 19 echo Hallo from cron. calledfromcron is: $calledfromcron; $HOME/somescript.sh; export CALLEDFROMCRON=0
This works. The sleep 20 command is added so /tmp/calledfromcron.txt is removed when $HOME/somescript.sh has probably finished execution. Not a perfect solution but it might work in certain cases
cron entry: * 21 23 6 2 echo "calledfromcron" > /tmp/calledfromcron.txt; $HOME/somescript.sh; sleep 20; rm -f /tmp/calledfromcron.txt cron entry: * 21 23 6 2 touch /tmp/calledfromcron.txt; $HOME/somescript.sh; sleep 20; rm -f /tmp/calledfromcron.txt
Use ps
Thanks to Sebastiaan
The Z is added to avoid comparison of empty strings which will give an error
The “ are added to avoid misinterpretation of spaces
#!/bin/bash if [ "Z$(ps o comm="" -p $(ps o ppid="" -p $$))" == "Zcron" -o \ "Z$(ps o comm="" -p $(ps o ppid="" -p $(ps o ppid="" -p $$)))" == "Zcron" ] then echo "Called from cron on $(date)" >> ~/test.txt else echo "Not called from cron on $(date)" >> ~/test.txt fi
This does not work
Just for reference:
Check if $- includes the i flag. The i is set for interactive shells
If cron is running the i is not present. But also when this is implemented in a script, that is ran from the command line, it is in non interactive mode so the i flag is not set also
You can from the commandline and as a command in cron
echo Flags: $- if [[ $- == *i* ]]; then echo i flag is present; fi
You can run this script form the commandline and with cron
#! /bin/bash case "$-" in *i*) INTERCACTIVE=1 ;; *) INTERCACTIVE=0 ;; esac if [[ $INTERCACTIVE -eq 0 ]]; then touch $HOME/not_interactive.txt fi if [[ $INTERCACTIVE -eq 1 ]]; then echo "Interactive" fi
Errors
bad minute
After saving and closing the file opened with crontab -e
$ crontab -e crontab: installing new crontab "/tmp/crontab.abcde/crontab":20: bad minute errors in crontab file, can't install. Do you want to retry the same edit? (y/n) y crontab: installing new crontab $
20 is the linenumber the error is found on
This happenes when you want to split long lines with a \
Extra spaces to line out the code of the command are allowed
redirection unexpected
/bin/sh: 1: Syntax error: redirection unexpected
Solution: write a script and execute it with cron
MP3 file does not play
Under investigation:
See also limitations
Example of the cronjob
0 * * * * mpg123 /home/user/audiofile.mp3
The mp3 file does not always play. Sometimes it plays sometimes it does not. After a while it did not play at all anymore.
It has heard being played while an other mp3 file is pause and while an other mp3 file is played
Everything works fine after pausing a Rumble video in Firefox. Youtube videos might cause the mp3 file not to play.
Ran the script containing
!# /bin/bash /usr/bin/mpg123 /home/user/someaudio.mp3 >> /home/user/someaudio.log 2>&1
from cron
This resulted in (cat /home/user/someaudio.log):
High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3 version 1.25.10; written and copyright by Michael Hipp and others free software (LGPL) without any warranty but with best wishes Cannot connect to server socket err = No such file or directory Cannot connect to server request channel jack server is not running or cannot be started JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock Segmentation fault
When the script is ran in a terminal it runs fine, the mp3 file is played
Solution: The commandline should be one of these two:
DISPLAY=:0.0 mpg123 /home/user/someaudio.mp3 DISPLAY=:0.0 /usr/bin/mpg123 /home/user/someaudio.mp3
Useful links
Crontabs reboot only works for root
Cron settings aid
Ubuntu cron howto
Cronitor: a cron monitor
Main subjects on this wiki: Linux, Debian, HTML, Microcontrollers, Privacy
RSS
Disclaimer
Privacy statement
Bugs statement
Cookies
Copyright © : 2014 - 2024 Webevaluation.nl and the authors
Changes reserved.