Run command `at ` 5 seconds from now
As part of a slightly complex script, I need to tell a server to run a simulation. Normally, I would achieve this by doing ssh user@server ‘simulation/script’ . However, doing so would keep the ssh session alive until ‘simulation/script’ is done, which is undesirable to me. I recently learned about the at command, and it seems to fit into my problem well.
What I want to do now is to ssh into my server, and at my simulation script to run in 5 seconds (more than enough time for the ssh connection to be closed). Thus, once the ssh connection is closed within 5 seconds, the server will start the simulation without needing the ssh connection to stay alive. What I’m having trouble with is the time expression that at needs in order to schedule a job «5 seconds from now» I have tried the following time expressions, all of which give me errors:
now + 5 seconds now + 5 sec now + 5 s now + 5seconds now + 5sec now + 5 s now+5sec now+5seconds now+5s
Rather than messing around with at , perhaps you just want ssh user@server bash -c ‘»simulation/script &»‘ .
I’m using it inside of a package.json script so I had to do this to prevent the process from being blocked: ( sleep 5 && delayed_command ) & immediate_command . I also added > /dev/null 2>&1 after the delayed_command if you don’t want the output to show up in STDOUT .
@JoshuaPinter this is the only answer that worked. I wanted to display an image using qlmanage for a a few seconds while continuing have a terminal session active, not asleep. Using background & worked fine, tho i did need to wrap in an additional set of prens. using bash 3.2 on macos.
How to Run a Script at a Certain Time on Linux
The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.
To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.
Connect your cluster and start monitoring your K8s costs right away:
1. Overview
More often than not, as system administrators, we have to run scripts at regular time intervals to keep our system infrastructure clean and secure.
These repetitive tasks include system backup, health monitoring, and other maintenance jobs. In such a case, automation is the best and quickest way to achieve the purpose.
This tutorial will expand on different methods of scheduling jobs at a specific time in Linux systems.
2. Cron
cron is a generic software service for scheduling tasks. It comprises two key components: cron daemon (crond) and cron configuration. crond reads the cron configuration to determine when to run which task. It iterates all the files under /var/spool/cron, /etc/crontab, and /etc/cron.d to execute the commands.
Now, let’s get into the nitty-gritty of it.
2.1. crontab
crontab is the command-line utility to manage all cron jobs. The cron packages are available by default in all recent Linux variant systems. If not, we can install it using a package manager:
$ dpkg -l cron dpkg-query: no packages found matching cron $ sudo apt-get update && sudo apt-get upgrade -y $ sudo apt-get install cron -y . . $ dpkg -l cron . . ||/ Name Version Architecture Description +++-====================================-=======================-=======================-============================================================================= ii cron 3.0pl1-128.1ubuntu1 amd64 process scheduling daemon $ systemctl status cron ● cron.service - Regular background program processing daemon Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2021-08-14 20:51:25 IST; 1 weeks 2 days ago . .
The crontab -l command will list all cron jobs. We can add comments using the # symbol:
$ crontab -l # Edit this file to introduce tasks to be run by cron. . . # 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
As the vi editor is generally the preferred tool for editing the cron configuration, let’s change the default editor to vi through the export command and edit the cron table using crontab -e:
$ export EDITOR=vi $ crontab -e # Edit this file to introduce tasks to be run by cron. 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/ . . # [minute] [hours] [day of month] [month] [day of the week] command-to-execute
Each of these fields has an allowed range of integer values:
- minute – 0 to 59
- hour – 0 to 23
- day of month – 1 to 31
- month – 1 to 12
- day of the week – 0 to 7, where 0 or 7 denotes Sunday, 1 is Monday, 2 is Tuesday, and so on, with 6 denoting Saturday
Let’s see a few examples of cron jobs. We’ll reroute the stdout and stderr to /dev/null to suppress the command output during execution:
To run backup.sh at 23:00 hrs (11 pm) daily and blackhole the stdout and stderr to the /dev/null file:
00 23 * * * /home/baeldung/backup.sh > /dev/null 2>&1
The system-wide cron environment variables can be set in /etc/crontab:
$ cat /etc/crontab SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin .
Furthermore, the system administrator has all privileges to restrict cron access through /etc/cron.allow and /etc/cron.deny files.
2.2. cron Special Characters
cron expressions typically contain one or more special characters that help us with scheduling tasks.
The asterisk (*) matches all possible values of a given field. Let’s see it in action:
00 15 * * * /home/baeldung/backups.sh
Here, by using an asterisk in the last three fields (1-31 days, 1-12 months, all days of the week), our backups.sh script will run every day at 3 pm.
The slash (/) denotes the increment of a given range:
02-50/10 * * * * /home/baeldung/monitor-cpu.sh
In the above expression, 2-50/10 in the minute field indicates the second minute of the hour and every 10 minutes thereafter. Therefore, the script will run on the 2nd, 12th, 22nd, 32nd, and 42nd minute of every hour.
The hyphen (-) signifies a continuous range, while the comma (,) separates a list of values.
The symbol at (@) enables the usage of an inbuilt cron scheduler such as @reboot, @hourly, @daily, @monthly, and @yearly. For example, we can schedule a script to execute after every reboot:
@reboot (cd /home/baeldung/monitoring-scripts; bash monitor-memory.sh)
Here, the semicolon (;) appends the commands to the execution list. In this example, first, it goes to the /home/baeldung/monitoring-scripts path and then executes the script monitor-memory.sh.
Our article on cron expressions further elucidates all possible options that cron uses.
Additionally, we can also place the scripts in /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly and /etc/cron.yearly directories for their respective execution:
$ ls -ltr /etc/cron.daily/ total 48 -rwxr-xr-x 1 root root 372 Aug 21 2017 logrotate -rwxr-xr-x 1 root root 1176 Nov 3 2017 dpkg -rwxr-xr-x 1 root root 249 Jan 25 2018 passed .
The above scripts residing in the cron.daily directory execute every day.
Generally, we should avoid running the cron task scheduler for the root user. Likewise, it’s not recommended to have complex code, piping, or redirections directly on the cron command. Instead, we should define complex jobs as scripts and call the scripts from cron.
3. at
at is yet another scheduler service that allows us to execute commands at a specific time, but only once.
The at packages are available by default in all recent Linux variant systems. If not, we can install it using a package manager:
$ which at $ $ sudo apt install at -y . . $ which at /usr/bin/at
We can easily schedule the tasks through the command line by giving the time parameter.
$ date Wed Aug 25 06:49:57 IST 2021 $ date > current-time.txt | at now warning: commands will be executed using /bin/sh job 9 at Wed Aug 25 06:50:21 2021 $ cat current-time.txt Wed Aug 25 06:50:22 IST 2021
The inline command execution helps us to run a script by leveraging the -f option of the at command:
$ at 09:00 -f /home/baeldung/one-time-env-setup.sh
Alternatively, we can schedule the jobs in the at terminal. For the sake of illustration, let’s create a new job that runs at 06:42 hrs to write the date and time into the at-demo.txt file:
$ at 06:42 warning: commands will be executed using /bin/sh at> date > at-demo.txt at> job 2 at Sat Aug 14 06:42:00 2021 $ ls -ltrh total 4.0K -rw-rw-r-- 1 tools tools 29 Aug 14 06:42 at-demo.txt $ cat at-demo.txt Sat Aug 14 06:42:00 IST 2021
We can use the atq command to list the user-scheduled jobs in the at queue.
Let’s read from the left side of the output as job id, date-time, queue letter, and the user. The queue letters can be from a to z and A to Z, where lower-valued letters have lower nice values and higher-valued letters have higher nice values:
$ atq 2 Sat Aug 14 06:42:00 2021 a tools
The atrm command removes the job from the task scheduler list:
$ atq 14 Fri Aug 27 06:42:00 2021 a tools $ atrm 2 $ atq $
4. batch
Interestingly, the batch command is an extended feature of the at command. It executes a command based on CPU load and not on time parameters.
When the system’s average CPU load is less than 1.5, then the system will execute the scheduled commands.
An alternate way of calling the batch command is at -b.
First, let’s see an example of the batch command with a CPU load of less than 1.5.
Usually, the top command helps to identify the current CPU load:
top - 17:20:50 up 11 days, 20:29, 2 users, load average: 0.00, 0.00, 0.00 Tasks: 405 total, 1 running, 306 sleeping, 0 stopped, 0 zombie $ batch warning: commands will be executed using /bin/sh at> date > batch-test.txt at> job 17 at Thu Aug 26 17:21:00 2021 $ ls -ltrh -rw-rw-r-- 1 tools tools 29 Aug 26 17:22 batch-test.txt $ cat batch-test.txt Thu Aug 26 17:22:12 IST 2021
In this case, batch didn’t execute the scheduled command as the CPU load was more than 1.5:
top - 17:24:28 up 11 days, 20:37, 2 users, load average: 6.91, 3.47, 1.38 Tasks: 413 total, 8 running, 306 sleeping, 0 stopped, 0 zombie $ date Thu Aug 26 17:26:45 IST 2021 $ batch warning: commands will be executed using /bin/sh at> date > batch-load-test.txt at> job 19 at Thu Aug 26 17:26:00 2021 $ date Thu Aug 26 17:28:49 IST 2021 $ ls -ltrh batch-load-test.txt ls: cannot access 'batch-load-test.txt': No such file or directory $ atq 19 Thu Aug 26 17:26:00 2021 b tools
We can restrict the users accessing the at and batch services using /etc/at.deny and /etc/at.allow files.
Now, let’s block the user jack from accessing at and batch services by simply adding the username into the /etc/at.deny file:
[email protected]:~$ cat /etc/at.deny | grep jack jack [email protected]:~$ at You do not have permission to use at. [email protected]:~$ batch You do not have permission to use at.
5. Conclusion
To summarize, we explored the different ways of scheduling tasks using cron, at, and batch services. Along the way, we saw the simplicity and flexibility of cron services in the repetitive execution of the jobs.
On the other hand, the at and batch services execute a task only once.