The timeout Command in Bash

Faaiq Bilal Feb 15, 2024
  1. the timeout Command in Bash
  2. Use timeout With SIGKILL Signal in Bash
The timeout Command in Bash

This article is an easy guide to setting up a timeout for specific programs using the timeout command by GNU’s coreutils package in Bash.

the timeout Command in Bash

In many situations, such as fetching data from a server or running a function or program with random inputs, the program or function may run for a very long time or indefinitely.

In such cases, stopping the program and preventing it from wasting more time and resources is essential.

This is where a timeout functionality comes in. The user defines a time limit, and then the program is allowed to run until successful completion, and if it takes too long until the user-defined time limit, it is then killed.

Timeout functionality is usually built-in for most programming languages. However, for Bash, it is not built-in and is part of an external package called coreutils.

This package is developed and maintained by GNU and contains implementations of many basic utilities.

The coreutils package can be installed simply by running the command sudo apt-get install -y coreutils in LINUX systems.

You must first have Homebrew installed to get the coreutils on macOS systems. To get Homebrew run the command below in the command terminal.

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

After the complete installation of Homebrew, run the command below.

brew install coreutils
Note
For coreutils commands on macOS, all the commands will have a g prefixed before the name (e.g., gdir or gtimeout).

If you have the coreutils package installed, you can simply use the timeout function, for example:

timeout 10 ping google.com

The above command outputs:

use timeout command

The ping utility in Bash is built-in and continues to run until manually interrupted. By default, ping sends a package every 1 second.

As seen above, the timeout command kills ping after 10 seconds as the number right after the timeout command is the time limit.

Therefore, the command timeout 10 cmd1 means that cmd1 will run until the successful completion or 10 seconds, whichever is earlier. The unit of time for the timeout command is in seconds.

To use a time value measured in minutes, hours, or days, add an m, an h, or a d, respectively.

For example, to set a timeout of 2 minutes:

timeout 2m programToRun

It should be noted that the exit status for a timeout is 124 when the process times out. In the following example, we will use this to check whether or not the process has timed out.

timeout 1 ping 8.8.8.8 -w3
EXIT_STATUS=$?
if [ $EXIT_STATUS -eq 124 ]
then
echo 'Process timed out!'
else
echo 'Process did not timeout.'
fi
exit $EXIT_STATUS

In the above-illustrated example, if the process does not complete in 1 second, the process will time out. The -w3 extension indicates that the address will be pinged thrice.

Hence, this process will always time out, giving the following output.

PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=57 time=40.4 ms
Process timed out!

It is important to note that any internal timeout will also result in the same exit status (124). Hence, this output indicates that either the process timed out using our specified timeout or some internal timeout made it terminate.

Use timeout With SIGKILL Signal in Bash

Typically, the timeout function sends a SIGTERM signal to stop the execution of a program when the time limit is reached. The problem is that some programs may ignore the SIGTERM signal and keep running.

This is where the SIGKILL signal comes in; it immediately stops executing a process and all its child processes and cannot be blocked or ignored. To use a timeout with SIGKILL, we must add the -s flag.

For example:

timeout -s SIGKILL 10 programToRun

When not running timeout directly from the shell, as in running it from a script, it is important to add --foreground to the timeout command.

Many alternatives to the timeout command can be used, all primarily based on the same logic of using some kill signal with sleep and then running the required command or program, which will be stopped as soon as sleep ends.

Example:

(sleep 2 && killall prog) & ./prog

The above code will kill all processes of prog after 2 seconds if the prog has not completed its execution. Such solutions can work but are not as safe and reliable as the timeout command, so it is always better to use timeout instead.