Situatie
OK, that’s enough computer time. You can give processes time limits, setting a maximum time they can run for with the timeout
command. Here’s a tutorial to putting limits on running programs with this command.
Solutie
What Does timeout Do For You?
The timeout
command allows you to set a limit on the length of time a program will run for. But why would you want to do that?
One case is when you know exactly how long you want a process to run for. A common use-case is to have timeout
control a logging or data-capture program so that the log files don’t relentlessly devour your hard drive space.
Another case is when you don’t know how long you want a process to run for, but you do know you don’t want it to run indefinitely. You might have a habit of setting processes running, minimizing the terminal window, and forgetting about them.
Some programs–even simple utilities—can generate network traffic at levels that can impede the performance of your network. Or they can tie up the resources on a target device, slowing down its performance. (ping
, I’m looking at you.) Leaving these types of programs running for extended periods while you’re away from your computer is bad practice.
timeout
is part of the GNU Core Utils so Linux and Unix-like operating systems such as macOS all have timeout built right in. There’s nothing to install; you can use it right out of the box.
Getting Started With timeout
Here’s a simple example. For example, with its default command-line options, the ping
command will run until you stop it by hitting Ctrl+C. If you don’t interrupt it, it’ll just keep going.
ping 192.168.4.28
By using timeout
, we can make sure ping
doesn’t run on and on, chewing up network bandwidth and pestering whatever device is being pinged.
This next command uses timeout
to time-limit ping
. We’re allowing 15 seconds of run time for ping
.
timeout 15 ping 192.168.4.28
After 15 seconds timeout
terminates the ping
session and we are returned to the command line prompt.
Using timeout With Other Time Units
Note that we didn’t have to add an “s” behind the 15. timeout
assumes the value is in seconds. You could add an “s,” but it really makes no difference.
To use a time value measured in minutes, hours or days add an “m,” an “h,” or a “d.”
To have ping run for three minutes, use the following command:
timeout 3m ping 192.168.4.28
ping
will run for three minutes before timeout
steps in and halts the ping
session.
Limiting Data Capture With timeout
Some data capture files can grow big very quickly. To prevent such files becoming unwieldy or even problematic in size, limit the amount of time the capture program is allowed to run.
In this example, we’re using tcpdump
, a network traffic capture tool. On the test machines that this article was researched on, tcpdump
was already installed in Ubuntu Linux and Fedora Linux. It had to be installed on Manjaro Linux and Arch Linux, with the following command:
sudo pacman -Syu tcpdump
We can run tcpdump
for 10 seconds with its default options, and redirect its output to a file called capture.txt with the following command:
timeout 10 sudo tcpdump > capture.txt
(tcpdump
has its own options to save captured network traffic to a file. This is a quick hack because we’re discussing timeout
, not tcpdump
.)
tcpdump
starts capturing network traffic and we wait for 10 seconds. And 10 seconds comes and goes and tcpdump
is still running, and capture.txt is still growing in size. It’s going to take a hasty Ctrl+C to halt tcpdump
.
Checking the size of capture.txt with ls
shows that it grew to 209K in a matter of seconds. That file was growing fast!
ls -lh capture.txt
What happened? Why didn’t timeout
stop tcpdump
?
It’s all to do with signals.
Sending The Right Signal
When timeout
wants to stop a program it sends the SIGTERM signal. This politely asks the program to terminate. Some programs may choose to ignore the SIGTERM signal. When that happens, we need to tell timeout
to be a little more forceful.
We can do that by asking timeout
to send the SIGKILL signal instead.
The SIGKILL signal cannot be “caught, blocked or ignored”—it always gets through. SIGKILL doesn’t politely ask the program to stop. SIGKILL hides around the corner with a stopwatch and a cosh.
We can use the -s
(signal) option to tell timeout
to send the SIGKILL signal.
timeout -s SIGKILL 10 sudo tcpdump > capture.txt
This time, as soon as 10 seconds have elapsed, tcpdump
is stopped.
Asking Politely First
We can ask timeout
to try to stop the program using SIGTERM, and to only send in SIGKILL if SIGTERM didn’t work.
To do this, we use the -k
(kill after) option. The -k
option requires a time value as a parameter.
In this command, we’re asking timeout
to let dmesg
run for 30 seconds, and to then terminate it with the SIGTERM signal. If dmesg
is still running after 40 seconds, it means the diplomatic SIGTERM was ignored and timeout
should send in SIGKILL to finish the job.
dmesg
is a utility that can monitor the kernel ring buffer messages and display them in a terminal window.
timeout -k 40 30 dmseg -w
dmesg
runs for 30 seconds and stops when it receives the SIGTERM signal.
We know it wasn’t SIGKILL that stopped dmesg
because SIGKILL always leaves a one-word obituary in the terminal window: “Killed.” That didn’t happen in this case.
Retrieving the Program’s Exit Code
Well-behaved programs pass a value back to the shell when they terminate. This is known as an exit code. Typically this is used to tell the shell–or whatever process launched the program— whether problems were encountered by the program as it ran.
timeout
provides its own exit code, but we may not care about that. We are probably more interested in the exit code from the process that timeout
is controlling.
This command lets ping
run for five seconds. It is pinging a computer called Nostromo, which is on the test network that was used to research this article.
timeout 5 ping Nostromo.local
The command runs for five seconds and timeout
terminates it. We can then check the exit code using this command:
echo $?
The exit code is 124. This is the value timeout
uses to indicate the program was terminated using SIGTERM. If SIGKILL terminates the program, the exit code is 137.
If we interrupt the program with Ctrl+C the exit code from timeout
is zero.
timeout 5 ping Nostromo.local
echo $?
If the execution of the program ends before timeout
terminates it, timeout
can pass the exit code from the program back to the shell.
For this to happen the program must come to a halt of its own accord (in other words, it is not terminated by timeout
), and we must use the --preserve-status
option.
If we use the -c
(count) option with a value of five ping
will only fire off five requests. If we give timeout
a duration of one minute, ping
will have definitely terminated by itself. We can then check the exit value using echo
.
timeout --preserve-status 1m ping -c 5 Nostromo.local
echo $?
ping
completes its five ping requests and terminates. The exit code is zero.
To verify the exit code is coming from ping
, let’s force ping
to generate a different exit code. If we try to send ping requests to a non-existent IP address, ping
will fail with an error exit code. We can then use echo
to check that the exit code is non-zero.
timeout --preserve-status 1m ping -c 5 NotHere.local
echo $?
The ping
command obviously cannot reach the non-existent device, so it reports the error and closes down. The exit code is two. This is the exit code ping
uses for general errors.
Setting Ground Rules
timeout
is all about providing some boundaries to running programs. If there’s a danger the log files might overrun your hard drive or that you might forget you left a network tool running, wrap them in timeout
and let your computer self-regulate.
Leave A Comment?