sleep-command-bash-script

Bash Sleep Command: A Quick Guide to Use It in Your Scripts

Why would you make your Bash script sleep?

We usually want a script to run fast, but not always…

In this article you will learn why and which command you can use for that.

Let’s look at three scenarios in which you would need to your script to “sleep”:

  1. Instead of running a command immediately, you want to schedule its execution X seconds in the future.
  2. A program takes long time to process a set of files and when the processing is complete it generates a file to indicate that. You can write a script that checks if that file exists and sleeps for a certain period of time if it doesn’t. Otherwise executes the next step of the process based on the files generated by the first program.
  3. You are calling a third party API programmatically and you know that the API doesn’t allow more than 60 requests per minute. Sleeping for X seconds allows you to make sure you don’t go over the number of requests per minute allowed by the API provider.

The command to suspend the execution of a script in Linux is the sleep command.

The basic syntax is very simple:

sleep seconds 

First of all, here is what happens if you run it in the command line:

[ec2-user@ip-172-1-2-3 ~]$ sleep 5
[ec2-user@ip-172-1-2-3 ~]$  

In this case after executing the sleep 5 command Linux returned the shell back after 5 seconds.

Scenario 1: Using the Sleep Command to Delay the Execution of Another Command in a Bash Script

I will write a simple script to show the exact behaviour of the sleep command…

…considering that the previous example couldn’t really show that the sleep command returned the shell back after 5 seconds.

Let’s write a script that does what I have explained in Scenario 1, it delays the execution of a command by X seconds (in this case 5 seconds).

It’s almost like executing a command at a specific time following the same principle of job schedulers.

So, create a very simple Bash script called delay_cmd.sh:

#!/bin/bash
   
date
sleep 5
date
uptime 

The date command is used to print the current date before and after the sleep command, in this way you can see that the script is suspended for 5 seconds.

After 5 seconds the uptime command is executed.

[ec2-user@ip-172-1-2-3 test_scripts]$ ./delay_cmd.sh 
Tue  7 Apr 22:21:17 UTC 2020
Tue  7 Apr 22:21:22 UTC 2020
 22:21:22 up 8 days,  1:03,  1 user,  load average: 0.00, 0.00, 0.00 

Makes sense?

In theory we can write the same script in a single line:

#!/bin/bash
   
date; sleep 5; date; uptime 

This is because the semicolon is used in Linux to separate different commands and execute them sequentially.

In other words, Linux makes sure each command completes before executing the next one.

Scenario 2: Write a Script that Uses the Sleep Command to Wait for Another Bash Script to Complete

In this example I will create two scripts:

  1. program_1.sh: sleeps for 30 seconds and then it creates a file called stage1.complete. This basically simulates a program that takes long time to complete a specific task and confirms the completion of its execution by creating the stage1.complete file.
  2. program_2.sh: uses a while loop and at every iteration checks if the stage1.complete file exists. If it doesn’t it sleeps for 6 seconds, if the file exists it prints the message “File stage1.complete exists. Stage 1 complete, starting Stage 2…“.

Here is program_1.sh:

#!/bin/bash 

sleep 30
touch stage1.complete 

The touch command is used by the first program to create the stage1.complete file after 30 seconds from the moment the script is executed.

And program_2.sh is the following, we will be using a Bash if else statement to implement it:

#!/bin/bash
   
while true
do
  if [ ! -f stage1.complete ]; then
    echo "File stage1.complete doesn't exist. Sleeping for 6 seconds..."
    sleep 6
  else
    echo "File stage1.complete exists. Stage 1 complete, starting Stage 2..."
    rm stage1.complete
    exit
  fi
done 

In the second script we have an infinite loop. At every iteration the script:

  • Checks if the file stage1.complete is present.
  • If the file doesn’t exist it sleeps for 6 seconds
  • If the file exists it removes the stage1.complete file and stops the execution using the Bash exit command.

Before executing the two scripts make sure they are both executable using the chmod +x command:

chmod +x program_*.sh

So, let’s run the scripts…

We will run program_1.sh first, we will run it in the background so that we can run program_2.sh immediately after that in the same terminal:

[ec2-user@ip-172-1-2-3 ]$ ./program_1.sh &
[1] 13527
[ec2-user@ip-172-1-2-3 ]$ ./program_2.sh 
File stage1.complete doesn't exist. Sleeping for 6 seconds...
File stage1.complete doesn't exist. Sleeping for 6 seconds...
File stage1.complete doesn't exist. Sleeping for 6 seconds...
File stage1.complete doesn't exist. Sleeping for 6 seconds...
File stage1.complete doesn't exist. Sleeping for 6 seconds...
File stage1.complete exists. Stage 1 complete, starting Stage 2...
[1]+  Done                    ./program_1.sh 

As expected the second script keeps sleeping for 6 seconds until it finds the file stage1.complete file, and then it stops it execution.

Scenario 3: Using the Sleep Command to Control the Number of Calls per Minute to an Third Party API

If you want to call an API using a Bash script you can use the curl command.

Using curl to call an API is simple, let’s take for example the following API endpoint:

https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22 

We will write a Bash script that uses curl to perform a GET request against it and uses the sleep command to limit the number of API calls in a certain period of time.

This is done to avoid going over any potential limits imposed by the API provider.

This is the script I have written:

#!/bin/bash
   
COUNTER=1 

while [ $COUNTER -lt 3 ]
do
  printf "\n\n### Executing API call number $COUNTER (`date`) ###\n\n"
  curl "https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22"
  COUNTER=$(($COUNTER+1))
  sleep 10
done 

Few things about this script:

  • The COUNTER variable is used to count the number of API calls to be executed before exiting from the while loop.
  • cURL is used to perform the GET requests against the API endpoint.
  • At every iteration of the while loop we suspend the script for 10 seconds with the sleep command to limit the number of API calls to one every 10 seconds.
  • We increment the COUNTER variable using the arithmetic operator $(( )).

So, execute the script:

[ec2-user@ip-172-1-2-3 ]$ ./call_api.sh 
 
### Executing API call number 1 (Tue  7 Apr 23:23:14 UTC 2020) ###
 
{"coord":{"lon":-0.13,"lat":51.51},"weather":[{"id":300,"main":"Drizzle","description":"light intensity drizzle","icon":"09d"}],"base":"stations","main":{"temp":280.32,"pressure":1012,"humidity":81,"temp_min":279.15,"temp_max":281.15},"visibility":10000,"wind":{"speed":4.1,"deg":80},"clouds":{"all":90},"dt":1485789600,"sys":{"type":1,"id":5091,"message":0.0103,"country":"GB","sunrise":1485762037,"sunset":1485794875},"id":2643743,"name":"London","cod":200}
 
### Executing API call number 2 (Tue  7 Apr 23:23:25 UTC 2020) ###
 
{"coord":{"lon":-0.13,"lat":51.51},"weather":[{"id":300,"main":"Drizzle","description":"light intensity drizzle","icon":"09d"}],"base":"stations","main":{"temp":280.32,"pressure":1012,"humidity":81,"temp_min":279.15,"temp_max":281.15},"visibility":10000,"wind":{"speed":4.1,"deg":80},"clouds":{"all":90},"dt":1485789600,"sys":{"type":1,"id":5091,"message":0.0103,"country":"GB","sunrise":1485762037,"sunset":1485794875},"id":2643743,"name":"London","cod":200}

[ec2-user@ip-172-1-2-3 ]$  

As expected two API calls are executed and then the execution of the while loop stops because the value of the variable COUNTER is 3.

Conclusion

I have showed you different ways to use the sleep command in a Bash script.

And in the process I have covered a lot of different things:

  • Running scripts in the background.
  • Using the arithmetic operator.
  • Infinite while loops.
  • Counter variables.
  • Calling an API using curl.
  • Creating and removing files.
  • Setting executable permissions for Bash scripts.
  • Using the semicolon to run commands sequentially.

I hope it makes all sense!

And you? How else would you use the sleep command in Bash? 🙂


Related FREE Course: Decipher Bash Scripting

Share knowledge with your friends!

Leave a Reply

Your email address will not be published. Required fields are marked *