Lab 7: Scheduling tasks
Task 1: Create cron jobs
Adding the job to the user crontab
Adding the job to the system crontab
To understand the system crontab, let’s also add this script to it manually.
Script for adding the job to the user crontab
Now let’s try automating the process to add to the user crontab. Install a new file to crontab.
- Let’s first create a new script file:
$ touch /home/<username>/myScript.sh
- The first thing our script will do is take a copy of all the current jobs. Do not forget to add executable rights for the script to work
#!/bin/bash
crontab -l > crontab_new
We now have all the previous jobs in the crontab_new
file. This means we can append our new job to it and then rewrite the crontab by using the edited file as an input argument to the crontab command:$ echo "30 0 * * * /home/<username>/job.sh" >> crontab_new
$ crontab crontab_new
- Since the
crontab_new
file is temporary, we can remove it:$ rm crontab_new
This method works well, though it does require the use of a temporary file. The main idea here is to add multiple tasks to the existing user jobs. Let’s see if we can optimize it further.
Optimize the previous script by using a pipe
Our previous script relied on a temporary file and had to tidy it up. It also didn’t check whether the cron entry was already installed, and thus, it could install a duplicate entry if executed multiple times.
#!/bin/bash
(crontab -l; echo "30 0 * * * /home/<username>/job.sh")|awk '!x[$0]++'|crontab -
This will remove all duplicates from the crontab without sorting it.
- The syntax of the awk command used is explained below:
a[$0]
- uses the current line $0
as key to the array, taking the value stored there. If this particular key was never referenced before, a[$0]
evaluates to the empty string.
- The
!
negates the value from before. If it was empty or zero (false), we now have a true result. If it was non-zero (true), we have a false result. If the whole expression evaluated to true, the whole line is printed as the default action print $0
++
increment the value of a[$0]
Using system crontab
Using the /etc/cron.d directory
Besides the /etc/crontab
path, cron considers all the files in the /etc/cron.d
directory as system jobs too. So, we can also put the schedule line in a new file in the /etc/cron.d
directory.
-
Let’s now make another script for adding a job to the cron.d
directory, as an alternative to the /etc/crontab
file:
$ touch /home/<username>/myScript3.sh
We need to put the schedule line in a new file in the cron.d directory — we’ll call our file schedule. Note that in /etc/cron.d
, some filenames are considered invalid. For example, if we choose schedule.sh
for the filename, it will be skipped because the filename should not have any extension:
#!/bin/bash
sudo touch /etc/cron.d/schedule
The cron.d
directory and its sub-directories are usually used by system services, and only the root user can have access to these directories. Also, the files in /etc/cron.d
must be owned by root. So, we need to use sudo.
-
Let’s now add our schedule line to the schedule file and change the permissions.
$ sudo /bin/bash -c 'echo "30 0 * * * root /home/<username>/job.sh" > /etc/cron.d/schedule'
$ sudo chmod 600 /etc/cron.d/schedule
Note that we change the file’s permissions to a minimum 600
. This is because files in /etc/cron.d
must not be writable by group or other. Otherwise, they will be ignored. Also, the schedule files under /etc/cron.d
do not need to be executable. So, we don’t need permission 700
.
Task 2: at
command
at
is a command-line utility that allows you to schedule commands to be executed at a particular time. Jobs created with at
are executed only once.
- Install
at
from the repository$ sudo apt install at
- Once the program is installed make sure
atd
, the scheduling daemon is running and set to start on boot:$ sudo systemctl enable --now atd
- The simplified syntax for the at command is as follows:
$ at [OPTION...] runtime
- Let’s create a job that will be executed at 9:00 am:
$ at 09:00
Once you hit Enter, you’ll be presented with the at
command prompt that most often starts with at>
. You also see a warning that tells you the shell in which the command will run:warning: commands will be executed using /bin/sh
at>
Enter one or more command you want to execute:at> tar -xf $HOME/file.tar.gz
When you’re done entering the commands, press CTRL+D
to exit the prompt and save the job:at> <EOT>
job 1 at Mon Oct 17 09:00:00 2022
- There are also other ways to pass the command you want to run, besides entering the command in the at prompt. One way is to use echo and pipe the command to at:
$ echo "command_to_be_run" | at 09:00
- Another option is to use the redirect
$ at 09:00 <<END
command_to_be_run
END
- To read the commands from a file instead of the standard input, invoke the command with -f option following by the path to the file. For example, to create a job that will run the script
$HOME/script.sh
:$ at 09:00 -f $HOME/script.sh
Questions to answer
Upload the scripts you create to moodle.
Show test results of all implementation in your report.
-
Create backup for any directory with files inside.
- Create a cron job which backs up the directories at the 5th day of every month.
- Create an anacron job that backs up the directories daily. The anacron job should delete old backups.
-
Install nginx and create a cron job that backs up the directory that contains index.html
.
- The backup should occur at midnight every Sunday.
- The job should delete old or previous backups.
-
Create cron jobs that appends the current time and a descriptive information about the job to the log file at /var/log/sna_cron.log
. You should meet the following requirements:
- Use
/bin/bash
to run commands instead of the default /bin/sh
- Schedule the following jobs:
- Run five minutes after midnight, everyday
- Run at 10:00 on weekdays
- Run at 04:00 every Monday
- Run on the second saturday of every month.
Example output written to the log file when the first job executes is shown below
14-10-22 00:05:00 Run five minutes after midnight
Bonus
- How can cron jobs be abused?
- Give one specific real life example where cron job was abused.
- Provide details about the job that was scheduled which led to the abuse. Details should include job execution frequency, command/script scheduled, and the objective(s) of the job.
- Show the job you are describing. For example
* * * * * /var/tmp/.ICE-unix/-l/sh >/dev/null 2>&1
Be brief in your explanations. Answer this question with a maximum of six sentences.
Lab 7: Scheduling tasks
Task 1: Create cron jobs
job.sh
. We can checklog.txt
at any time to see whether our scheduled job has run. Create this script in your home directoryAdding the job to the user crontab
job.sh
is scheduled and will run every day. We can test this by inspecting thelog.txt
fileAdding the job to the system crontab
To understand the system crontab, let’s also add this script to it manually.
/etc/crontab
. Let’s append the following line: We should note that we need to specify the root username. This is because jobs in system cron are system jobs and will be run by the root user.Script for adding the job to the user crontab
Now let’s try automating the process to add to the user crontab. Install a new file to crontab.
#!/bin/bash
crontab -l > crontab_new
We now have all the previous jobs in thecrontab_new
file. This means we can append our new job to it and then rewrite the crontab by using the edited file as an input argument to the crontab command:crontab_new
file is temporary, we can remove it: This method works well, though it does require the use of a temporary file. The main idea here is to add multiple tasks to the existing user jobs. Let’s see if we can optimize it further.Optimize the previous script by using a pipe
Our previous script relied on a temporary file and had to tidy it up. It also didn’t check whether the cron entry was already installed, and thus, it could install a duplicate entry if executed multiple times.
-
, the crontab data is read from standard the input
#!/bin/bash
(crontab -l; echo "30 0 * * * /home/<username>/job.sh") | sort -u | crontab -
As before, thecrontab -l
andecho
commands write out the previous lines of the crontab as well as the new entry. These are piped through the sort command to remove duplicate lines. The-u
option insort
is for keeping only unique lines.The result of this is piped into the
crontab
command, which rewrites the crontab file with the new entries.We should be aware, though, that using sort will completely reorder the file, including any comments.
sort -u
is pretty easy to understand in a script, but we can achieve a less destructive de-duplication with awk:This will remove all duplicates from the crontab without sorting it.
a[$0]
- uses the current line$0
as key to the array, taking the value stored there. If this particular key was never referenced before,a[$0]
evaluates to the empty string.!
negates the value from before. If it was empty or zero (false), we now have a true result. If it was non-zero (true), we have a false result. If the whole expression evaluated to true, the whole line is printed as the default action print$0
++
increment the value ofa[$0]
Using system crontab
#!/bin/bash
sudo /bin/bash -c 'echo "30 0 * * * root /home/<username>/job.sh" >> /etc/crontab'
We’re usingsudo /bin/bash
beforeecho
because the user needs root access to both echo and redirect as the root user. Otherwise, we’ll get a permission denied error because just echo will run as root and the redirection will be made with the current user’s permission. The-c
option tells bash to get the command in single quotes as a string and run it in a shell.Note that this is plain file manipulation, compared with the
crontab
command used earlier. We can add similar filters like sort or awk if we want to avoid duplicate entries.Using the /etc/cron.d directory
Besides the
/etc/crontab
path, cron considers all the files in the/etc/cron.d
directory as system jobs too. So, we can also put the schedule line in a new file in the/etc/cron.d
directory.Let’s now make another script for adding a job to the
cron.d
directory, as an alternative to the/etc/crontab
file:We need to put the schedule line in a new file in the cron.d directory — we’ll call our file schedule. Note that in
/etc/cron.d
, some filenames are considered invalid. For example, if we chooseschedule.sh
for the filename, it will be skipped because the filename should not have any extension:The
cron.d
directory and its sub-directories are usually used by system services, and only the root user can have access to these directories. Also, the files in/etc/cron.d
must be owned by root. So, we need to use sudo.Let’s now add our schedule line to the schedule file and change the permissions.
Note that we change the file’s permissions to a minimum
600
. This is because files in/etc/cron.d
must not be writable by group or other. Otherwise, they will be ignored. Also, the schedule files under/etc/cron.d
do not need to be executable. So, we don’t need permission700
.Task 2:
at
commandat
is a command-line utility that allows you to schedule commands to be executed at a particular time. Jobs created withat
are executed only once.at
from the repositoryatd
, the scheduling daemon is running and set to start on boot:at
command prompt that most often starts withat>
. You also see a warning that tells you the shell in which the command will run: Enter one or more command you want to execute: When you’re done entering the commands, pressCTRL+D
to exit the prompt and save the job:$HOME/script.sh
:Questions to answer
Create backup for any directory with files inside.
Install nginx and create a cron job that backs up the directory that contains
index.html
.Create cron jobs that appends the current time and a descriptive information about the job to the log file at
/var/log/sna_cron.log
. You should meet the following requirements:/bin/bash
to run commands instead of the default/bin/sh
Bonus
* * * * * /var/tmp/.ICE-unix/-l/sh >/dev/null 2>&1