|
Home | Switchboard | Unix Administration | Red Hat | TCP/IP Networks | Neoliberalism | Toxic Managers |
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and bastardization of classic Unix |
On a Linux system, some tasks have to be automated on a regular basis. It would be one option to configure each process with a process-specific solution to handle recurring tasks, but that would not be efficient to deal with. That is why on Linux the cron service is used as a generic service to run processes automatically at specific times.
The cron service consists of two major components. First, there is the cron daemon crond. and then crontab command which manages the list of task is specified in cron configuration file. They can be listed with crontab -l command The latter is re-read automatically each time you change it with crontab -e command.
This daemon is invoked every minute and reads and analyzes its configuration file to determine is any job needs to be run
Cron configuration file has a unique structure with five fields preceding each command. Those five fields constitutes time specification and define minute, hour, day_of_the_month, month, day_of_the_week that the job will be executed. In this particular order.
In Linux cron configuration, like configuration on many other services became quite Byzantium and completely un-transparent and the task can be specified in three different places, two of which are never listed by crontab -l command which supposedly should list all jobs for the particular user. It is important to understand that crontab -l lists only tasks specified via crontab -e command.
So each RHEL sysadmin needs to write a script that lists all relevant sources to understand how cron service on his particular server behaves. In the simplest form it should be
crontab -1 ls /etc/cron.d /etc/cron.hourly cron.daily cron.weekly cron.monthly
Yes another complication is that cron is now is managed by systemd, but in comparison with other daemons manual intervention is seldom required and this is a minor problem.
Although I once did encountered a server with RHEL6 in which it periodically died and that created strange and difficult to troubleshoot effects on monitoring
There is also another daemon called atd which provides "one time" execution of tasks. It allows you to specify execution of scripts of binaries at any desired time. This daemon configuration is controlled by three command at, atq and atrm.
Another face of the same daemon is represented by the batch command which allow to specify multiple jobs in sequential queues. Around 20 queues are available.
The cron service is started by default on every RHEL system. The service is needed because some system tasks are running through cron as well. An example of these is logrotate, a service that cleans up log files and runs on a regular basis, but other important maintenance processes are started automatically through cron also.
Usually the cron service does not need any management. Where other services need to be reloaded or restarted to activate changes to their configuration, this is not needed by cron. The cron daemon wakes up every minute and checks its configuration to see whether anything needs to be started.
To monitor the current status of the cron service, you can use the systemctl status crond -l command.
[0]d620@ROOT:/etc/cron.d # systemctl status crond -l ? crond.service - Command Scheduler Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2019-03-22 14:26:50 EDT; 3 weeks 6 days ago Main PID: 3416 (crond) CGroup: /system.slice/crond.service mq3416 /usr/sbin/crond -n Mar 22 14:26:50 d620 systemd[1]: Started Command Scheduler. Mar 22 14:26:50 d620 crond[3416]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 54% if used.) Mar 22 14:26:51 d620 crond[3416]: (CRON) INFO (running with inotify support)
The most significant part of the output of the systemctl status crond command is in the beginning: It mentions that the crond service is loaded and that it is enabled as well.
The fact that the service is enabled means that it will automatically be started whenever this service is restarting.
The last part of the command shows current status information. Through the journald service, the systemctl command you can find out what is actually happening to the crond service.
When scheduling services through cron, you need to specify when exactly the services need to be started. In the crontab configuration (which is explained more in depth in the next section), you use a time string to indicate when tasks should be started.
The sequence of fields in crontab table is listed in the file /etc/crontab
[0]d620@ROOT:~ # cat /etc/crontab SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root # For details see man 4 crontabs # Example of job definition: # .---------------- 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 * 11 * * * logger -p INFO `date` # Each minute between 11:00 and 11:59 (probably not what you want) 0 23 * * 1-5 logger -p INFO `date` # Every day at 11 a.m. on weekdays only 0 7-18 * * 1-5 logger -p INFO `date` # Every hour between 7 a.m. and 6 p.m. on weekdays on the hour 0 */2 2 12 5 logger -p INFO `date` # Every 2 hours on the hour on December second and every Friday in December
The command logger -p INFO `date` is very convenient for debugging as it allow to verify that you specified sequence of invocation is correct.
In any of these fields, you can use an * to refer to any value. Ranges of numbers are allowed, as are lists and patterns. Some examples are listed next:
There are thee major ways to add a script to cron for root:
[0]d620@ROOT:/etc/cron.d # cat rear 30 1 * * * root /usr/sbin/rear checklayout || /usr/sbin/rear mkrescue
NOTE
The last way to schedule cron jobs is through the following directories:
In these directories, you typically find scripts that are put in there from RPM package files. When opening these scripts, notice that no information is included about the time when the command should be executed. That is because the exact time of execution does not really matter. The only thing that does matter is that the job is launched once an hour, day, week, or month.
To ensure regular execution of the job, cron uses the Anacron extension. This extension takes care of starting the hourly, daily, weekly, and monthly cron jobs, no matter at which exact time. To determine how this should be done, Anacron uses the /etc/anacrontab file.
[1] d620@ROOT:~ # cat /etc/anacrontab # /etc/anacrontab: configuration file for anacron # See anacron(8) and anacrontab(5) for details. SHELL=/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root # the maximal random delay added to the base delay of the jobs RANDOM_DELAY=45 # the jobs will be started during the following hours only START_HOURS_RANGE=3-22 #period in days delay in minutes job-identifier command 1 5 cron.daily nice run-parts /etc/cron.daily 7 25 cron.weekly nice run-parts /etc/cron.weekly @monthly 45 cron.monthly nice run-parts /etc/cron.monthly
In /etc/anacrontab, the jobs to be executed are specified in lines that contain three fields. The first field specifies the frequency of job execution, expressed in days. The second column specifies how long anacron waits before executing the job, and in the last part is the command that should be executed.
Cron jobs can be started not only for root but for any users. To create a user-specific cron job, type crontab -e after logging in as that user, or as root type crontab -e -u username
NOTE:
In this exercise, you apply some of the cron basics. You schedule cron jobs using different mechanisms.
23 11 * * 1-5 logger -INFO I am alive
logger -p INFO "This message is coming from the script chronoline cron.hourlys"
*/5 11 * * * root logger -p INFO Five minutes timebeat
Whereas cron is used to schedule jobs that need to be executed on a regular basis, the atd service is available for services that need to be executed only once. On RHEL 7, the atd service is available by default, so all that needs to be done is scheduling jobs.
To run a job through the atd service, you would use the at command, followed by the time the job needs to be executed. This can be a specific time, as in at 14:00, but it can also be a time indication like at now or at noon.
You can also specify offset from now, like
at now + 30 minutes
to submit command to at commend you can use 3 methods.
echo tail -12 /var/log/messages | at now + 3 minutes
at -f /etc/overnight_file_transmission.sh 19:00
After scheduling jobs with at, you can use the atq command (q for queue) to get an overview of all jobs currently scheduled. Without any parameteers it lists all the jobs. With a numeric parameter (representing job ID) option -V instructs atq command to list time the job will be executed before reading the job on the console.
[1] d620@ROOT:/etc/cron.d # atq -V 1 at version 3.1.13 1 Thu Apr 18 16:43:00 2019 a root
To list the content of the job you should use at -c <job number> command, for example
at -c 1
you will see that job includes setting the environment that exist at themoment of submission of the job. The likes you entered are at the very bootom of this listing.
[1] d620@ROOT:/etc/cron.d # at -c 2 #!/bin/sh # atrun uid=0 gid=0 # mail root 0 umask 22 XDG_SESSION_ID=677; export XDG_SESSION_ID HOSTNAME=d620; export HOSTNAME PREVPWD=/etc/cron.d; export PREVPWD SELINUX_ROLE_REQUESTED=; export SELINUX_ROLE_REQUESTED SHELL=/bin/bash; export SHELL HISTSIZE=1000; export HISTSIZE SSH_CLIENT=192.168.5.14\ 56167\ 22; export SSH_CLIENT SELINUX_USE_CURRENT_RANGE=; export SELINUX_USE_CURRENT_RANGE OLDPWD=/root; export OLDPWD PROMPT_DIRTRIM=3; export PROMPT_DIRTRIM SSH_TTY=/dev/pts/0; export SSH_TTY USER=root; export USER LS_COLORS=rs=0:di=01\;34:ln=01\;36:mh=00:pi=40\;33:so=01\;35:do=01\;35:bd=40\;33\;01:cd=40\;33\;01:or=40\;31\;01:mi=01\;05\;37\;41:su=37\;41:sg=30\;43:ca=30\;41:tw=30\;42:ow=34\;42:st=37\;44:ex=01\;32:\*.tar=01\;31:\*.tgz=01\;31:\*.arc=01\;31:\*.arj=01\;31:\*.taz=01\;31:\*.lha=01\;31:\*.lz4=01\;31:\*.lzh=01\;31:\*.lzma=01\;31:\*.tlz=01\;31:\*.txz=01\;31:\*.tzo=01\;31:\*.t7z=01\;31:\*.zip=01\;31:\*.z=01\;31:\*.Z=01\;31:\*.dz=01\;31:\*.gz=01\;31:\*.lrz=01\;31:\*.lz=01\;31:\*.lzo=01\;31:\*.xz=01\;31:\*.bz2=01\;31:\*.bz=01\;31:\*.tbz=01\;31:\*.tbz2=01\;31:\*.tz=01\;31:\*.deb=01\;31:\*.rpm=01\;31:\*.jar=01\;31:\*.war=01\;31:\*.ear=01\;31:\*.sar=01\;31:\*.rar=01\;31:\*.alz=01\;31:\*.ace=01\;31:\*.zoo=01\;31:\*.cpio=01\;31:\*.7z=01\;31:\*.rz=01\;31:\*.cab=01\;31:\*.jpg=01\;35:\*.jpeg=01\;35:\*.gif=01\;35:\*.bmp=01\;35:\*.pbm=01\;35:\*.pgm=01\;35:\*.ppm=01\;35:\*.tga=01\;35:\*.xbm=01\;35:\*.xpm=01\;35:\*.tif=01\;35:\*.tiff=01\;35:\*.png=01\;35:\*.svg=01\;35:\*.svgz=01\;35:\*.mng=01\;35:\*.pcx=01\;35:\*.mov=01\;35:\*.mpg=01\;35:\*.mpeg=01\;35:\*.m2v=01\;35:\*.mkv=01\;35:\*.webm=01\;35:\*.ogm=01\;35:\*.mp4=01\;35:\*.m4v=01\;35:\*.mp4v=01\;35:\*.vob=01\;35:\*.qt=01\;35:\*.nuv=01\;35:\*.wmv=01\;35:\*.asf=01\;35:\*.rm=01\;35:\*.rmvb=01\;35:\*.flc=01\;35:\*.avi=01\;35:\*.fli=01\;35:\*.flv=01\;35:\*.gl=01\;35:\*.dl=01\;35:\*.xcf=01\;35:\*.xwd=01\;35:\*.yuv=01\;35:\*.cgm=01\;35:\*.emf=01\;35:\*.axv=01\;35:\*.anx=01\;35:\*.ogv=01\;35:\*.ogx=01\;35:\*.aac=01\;36:\*.au=01\;36:\*.flac=01\;36:\*.mid=01\;36:\*.midi=01\;36:\*.mka=01\;36:\*.mp3=01\;36:\*.mpc=01\;36:\*.ogg=01\;36:\*.ra=01\;36:\*.wav=01\;36:\*.axa=01\;36:\*.oga=01\;36:\*.spx=01\;36:\*.xspf=01\;36:; export LS_COLORS MAIL=/var/spool/mail/root; export MAIL PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin; export PATH PWD=/etc/cron.d; export PWD LANG=en_US.UTF-8; export LANG SELINUX_LEVEL_REQUESTED=; export SELINUX_LEVEL_REQUESTED HISTCONTROL=ignoredups; export HISTCONTROL SHLVL=1; export SHLVL HOME=/root; export HOME LOGNAME=root; export LOGNAME SSH_CONNECTION=192.168.5.14\ 56167\ 192.168.5.23\ 22; export SSH_CONNECTION LESSOPEN=\|\|/usr/bin/lesspipe.sh\ %s; export LESSOPEN PROMPT_COMMAND=root_prompt; export PROMPT_COMMAND XDG_RUNTIME_DIR=/run/user/0; export XDG_RUNTIME_DIR cd /etc/cron\.d || { echo 'Execution directory inaccessible' >&2 exit 1 } ${SHELL:-/bin/sh} << 'marcinDELIMITER379b732b' echo timebeat marcinDELIMITER379b732b
It is also possible to remove any scheduled at job using the atrm command followed by the number of the at job that you want to remove, for example
atrm 2
.
The batch command works like at, but is more sophisticated. When using batch, you can specify multiple jobs that will will be executed sequentially one after another. Of also can serve multiple queues. The default queue for batch is b queue. Each queue is denoted with a single letter and can be specified using option -q:
-q queue
uses the specified queue. A queue designation consists of a single letter; valid queue designations range from a to z. and A to Z. The a queue is the default for at and the b queue for batch. Queues with higher letters run with increased niceness. The special queue "=" is reserved for jobs which are currently running.
You also can specify the level of system load at which batch jobs are allowed to run. The default is when system load is lower than 0.8, which in most cases is a reasonable default value.
If in your environment this value is too high or too low you can be specified manually when starting atd, using the -l command-line option. If atd was already started you need to restart it via systemctl.
By default, all users can enter cron jobs. It is possible to limit which user is allowed to schedule cron jobs by using the /etc/cron.allow and /etc/cron.deny configuration files. If the cron.allow file exists, a user must be listed in it to be allowed to use cron. If the /etc/cron.deny file exists, a user must not be listed in it to be allowed to set up cron jobs.