Unix / Linux - Signals and Traps

Hello there, future computer wizards! Today, we're diving into the fascinating world of Unix/Linux signals and traps. Don't worry if you're new to programming - I'll guide you through this adventure step by step, just like I've done for countless students over my years of teaching. So, let's embark on this exciting journey together!

Unix / Linux - Signals and Traps

What are Signals?

Imagine you're in a busy restaurant kitchen. The chef (let's call him Chef Unix) needs to communicate with his staff quickly. Instead of shouting over the noise, he uses a system of hand signals. That's pretty much what signals are in the Unix/Linux world - a way for processes to communicate quickly and efficiently.

Signals are software interrupts sent to a program to indicate that an important event has occurred. These events can range from user requests to exceptional runtime occurrences.

List of Signals

Just like Chef Unix might have different hand signals for "more salt," "hurry up," or "take a break," Unix/Linux systems have a variety of signals for different purposes. Let's look at some of the most common ones:

Signal Name Signal Number Description
SIGHUP 1 Hangup detected on controlling terminal or death of controlling process
SIGINT 2 Interrupt from keyboard (Ctrl+C)
SIGQUIT 3 Quit from keyboard (Ctrl+)
SIGKILL 9 Kill signal (cannot be caught or ignored)
SIGTERM 15 Termination signal
SIGSTOP 17, 19, 23 Stop the process (cannot be caught or ignored)

Default Actions

When a signal is sent to a process, the process will take a default action unless instructed otherwise. These default actions are like the instinctive responses of our kitchen staff. For example:

  1. Terminate the process
  2. Ignore the signal
  3. Dump core
  4. Stop the process
  5. Continue a stopped process

Sending Signals

Now, let's learn how to send these signals. In Unix/Linux, we use the kill command to send signals to processes. Don't let the name fool you - kill doesn't always terminate processes; it's just a way to send signals.

Here's how you can use it:

kill -signal_name process_id

For example, to send a SIGTERM signal to process 1234:

kill -SIGTERM 1234

Or, using the signal number:

kill -15 1234

Trapping Signals

What if our kitchen staff could decide how to respond to Chef Unix's signals instead of always following the default reaction? That's what signal trapping allows in programming.

In shell scripts, we use the trap command to catch signals and specify what to do when they're received. Here's the basic syntax:

trap command signal(s)

Let's look at an example:

#!/bin/bash

trap "echo Bonjour!" SIGINT SIGTERM

echo "It's a trap!"
while true
do
    sleep 60
done

In this script, if it receives either SIGINT or SIGTERM, it will print "Bonjour!" instead of terminating. It's like telling our kitchen staff, "When the chef signals to stop, say 'Bonjour!' instead of actually stopping."

Cleaning Up Temporary Files

One common use of traps is to clean up temporary files before a script exits. Here's an example:

#!/bin/bash

# Create a temporary file
temp_file=$(mktemp)

# Set up a trap to remove the temporary file on exit
trap "rm -f $temp_file" EXIT

# Use the temporary file
echo "Hello, World!" > $temp_file
cat $temp_file

# The temporary file will be automatically removed when the script exits

This script creates a temporary file, writes to it, reads from it, and then automatically removes it when the script exits, thanks to the trap.

Ignoring Signals

Sometimes, you might want to ignore certain signals. In our kitchen analogy, this would be like telling a chef, "No matter how many times you signal for more salt, I'm not adding any more!"

Here's how you can ignore a signal:

trap "" SIGINT

This tells the script to do nothing when it receives a SIGINT signal.

Resetting Traps

What if you want to go back to the default behavior after trapping a signal? You can reset a trap like this:

trap - SIGINT

This removes the trap for SIGINT, reverting to the default behavior.

Here's a more complete example:

#!/bin/bash

# Initially, trap SIGINT
trap "echo You can't stop me!" SIGINT

echo "Try to stop me with Ctrl+C..."
sleep 10

# Now, reset the trap
trap - SIGINT

echo "Okay, now you can stop me with Ctrl+C..."
sleep 10

echo "If you see this, you didn't stop me!"

This script first traps SIGINT, then resets it after 10 seconds. It's like telling our kitchen staff, "Ignore the stop signal for 10 seconds, then go back to normal."

And there you have it, folks! We've journeyed through the land of Unix/Linux signals and traps. Remember, practice makes perfect. Try writing your own scripts, play around with different signals, and soon you'll be conducting your own orchestra of processes like a true maestro. Happy coding!

Credits: Image by storyset