Until now, we learned about various useful shell utilities and how to write them into a shell script in order to avoid writing the same instructions again and again. Automating tasks by writing into scripts reduces the tasks up to a certain extent, but still we will have to run those scripts whenever required. Sometimes, it happens that we want to run a command or script at a particular time, for example, sysadmin has to run a clean-up and maintenance of a system available in the data center at 12:30 AM. To perform the required operation, sysadmin will login into a machine around 12:30 AM and do the necessary work. But what if his or her home network is down and the data center is far? It will be inconvenient and tough to perform a task at that moment. There are also a few tasks that need to be performed on daily or hourly basis, for example, monitoring the network usage of each user, taking a system backup, and so on. It will be very boring to execute repetitive tasks again and again.
In this chapter, we will see how to solve such issues by scheduling tasks at a specific time or interval of time by using utilities at
and crontab
. We will also see how systemd (the first process started after a system is booted up with PID 1) manages processes needed after system start-up. We will also see how systemd manages different services and system logs. At the end, we will learn how we can embed other scripting languages in a shell script to get extra capabilities in the shell script.
This chapter will cover the following topics in detail:
In general, when we run a command or script, it starts executing instantly. However, what if we want it to run later at a specific time? For example, I want to download large data from the Internet, but don't want to slow down my Internet bandwidth while I am working. So, I would like to run my download script at 1:00 AM since I won't be using the Internet for any kind of work after 1:00 AM. It is possible to schedule download scripts or commands later at a specified time using the at
command. We can also list scheduled tasks using the atq
command or remove any scheduled tasks using the atrm
command.
We will use the at
command to run tasks at a given time. The syntax of using the at
command is as follows:
at [Option] specified_time
In the preceding syntax, specified_time
refers to the time at which a command or script should run. The time can be in the following format:
Time format |
Description |
---|---|
HH:MM |
The specific time of the day in hours (HH) and minutes (MM). If the time is already past, then the next day is assumed. Time is specified in 24 hours format. |
noon |
At 12:00 during day time. |
teatime |
At 16:00 or 4 pm in afternoon. |
midnight |
At 12:00 at night. |
today |
Refers to the current time on same day. |
tomorrow |
Refers to the current time on the next day. |
AM or PM |
Suffixed with the time to specify time in 12-hour format, for example, 4:00PM. |
now + count time-units |
Run a script at the same time after a certain time-unit. Count can be an integer number. Time units can be in minutes, hours, days, weeks, months, or years. |
Date |
A date can be given in the form of month-name, day, and optional year. Date can be in one of the following formats: MMDD[CC]YY, MM/DD/[CC]YY, DD.MM.[CC]YY, or [CC]YY-MM-DD. |
The options to the at
command are explained in the following table:
The following command is scheduled to run at 14:00, which stores the filesystem's usage in a file called file_system_usage.log
in a user's home directory:
$ at 14:00 warning: commands will be executed using /bin/sh at> df > ~/file_system_usage.log at> <EOT> job 33 at Mon Sep 21 14:00:00 2015
When we run the at
command as shown, a warning message warning: commands will be executed using /bin/sh is printed, which specifies which shell will be used to execute commands. In the next line, we will see at prompt
where we can specify the list of commands to be executed at 14:00. In our case, we entered the df > ~/file_system_usage.log
command, which means run the df
command and save its result in the file_system_usage.log
file.
Once the list of commands to be entered is finished, press the Enter key and then, in the next line, use the Ctrl + d keys to exit from at
prompt. Before getting a normal shell prompt, we will see the message saying created job number and time stamp at which the job will be executed. In our case, the job number is 33
and the time stamp is Mon Sep 21 14:00:00 2015
.
We can check the content of the file_system_usage.log
file once the time stamp we specified is over.
We can print on stdout
what is going to be executed when a particular scheduled job runs:
$ at -c 33 # Lists content of job 33
We can see that the df > ~/file_system_usage.log
command will be executed. The rest of the lines specify in what environment a task will be executed.
Now, consider a job scheduled by the root user:
# at -v 4am Mon Sep 21 04:00:00 2015 warning: commands will be executed using /bin/sh at> reboot at> <EOT> job 34 at Mon Sep 21 04:00:00 2015
The job with the number 34
is scheduled by the user root. This job system will reboot at 4am
.
We can schedule a script file for execution at a specific time using the -f
option with the at
command.
For example, we want to run the loggedin_user_detail.sh
script next week at 4 pm. This script lists logged in users and what processes they are running when the script gets executed at a scheduled time. The content of the script is as follows:
$ cat loggedin_user_detail.sh #!/bin/bash # Filename: loggedin_user_detail.sh # Description: Collecting information of loggedin users users_log_file=~/users_log_file.log echo "List of logged in users list at time 'date'" > $users_log_file users=('who | cut -d' ' -f1 | sort | uniq') echo ${users[*]} >> $users_log_file for i in ${users[*]} do echo "Processes owned by user $i" >> $users_log_file ps u -u $i >> $users_log_file echo done $ chmod +x loggedin_user_detail.sh # Provide execute permission
Now, to run the preceding script at 4 pm next week, we will run the following command:
$at -f loggedin_user_detail.sh 4pm + 1 week warning: commands will be executed using /bin/sh job 42 at Sun Sep 27 16:00:00 2015
We can see that the job has been scheduled to run one week later.
Sometimes, it happens that a task has been scheduled to run at a specific time, but we forget the time at which a task is supposed to run. We can see the already scheduled tasks using one of the atq
or the at
command with the -l
option:
$ atq 33 Mon Sep 21 14:00:00 2015 a skumari 42 Sun Sep 27 16:00:00 2015 a skumari
The atq
command displays jobs scheduled by the current user with the job number, time, and user's name:
$ sudo atq 34 Mon Sep 21 04:00:00 2015 a root 33 Mon Sep 21 14:00:00 2015 a skumari 42 Sun Sep 27 16:00:00 2015 a skumari
We can also remove a scheduled task if the task is no longer required to be performed. Removing a task is also useful when we want to the modify time at which a task is to be executed. To modify time, first remove the scheduled task and then create the same task again with the new time.
For example, we don't want to reboot a system at 1 am instead of 4 am. For this, the root user will first remove the job 34
using the atrm
command:
# atrm 34 $ sudo atq # Updated lists of tasks 33 Mon Sep 21 14:00:00 2015 a skumari 42 Sun Sep 27 16:00:00 2015 a skumari # at 1am warning: commands will be executed using /bin/sh at> reboot at> <EOT> job 47 at Mon Sep 21 01:00:00 2015 $ sudo atq 33 Mon Sep 21 14:00:00 2015 a skumari 42 Sun Sep 27 16:00:00 2015 a skumari 47 Mon Sep 21 01:00:00 2015 a root
We can see that the task scheduled by the root user will now run at 1 am instead of 4 am.
3.15.1.22