w3resource

Process Management in Bash: Background Processes and Signals

1.

Running a Process in the Background:

Write a Bash script that runs a long-running command (e.g., sleep 30) in the background and prints the process ID (PID) of the background process.

Code:

#!/bin/bash

# Run the sleep command in the background
sleep 30 &

# Get the PID of the last background process
PID=$!

# Print the PID
echo "Background process PID: $PID"

Output:

dt@DESKTOP-3KE0KU4:~$ ./test1.sh
Background process PID: 30
dt@DESKTOP-3KE0KU4:~$ ./test1.sh
Background process PID: 32
dt@DESKTOP-3KE0KU4:~$ ./test1.sh
Background process PID: 34
dt@DESKTOP-3KE0KU4:~$ ./test1.sh
Background process PID: 36
dt@DESKTOP-3KE0KU4:~$ ./test1.sh
Background process PID: 38

Explanation:

In the exercise above,

  • Shebang (#!/bin/bash):
    • Indicates that the script should be interpreted by the Bash shell.
  • Run the Sleep Command in the background:
    • Executes the sleep 30 command in the background, causing the script to pause for 30 seconds without blocking the shell.
  • Get the PID of the last background process:
    • Captures the Process ID (PID) of the last background process using the special variable $!.
  • Print the PID:
    • Displays the PID of the background process using the "echo" command, confirming its value to the user.

2.

Bringing a Background Process to the Foreground:

Write a Bash script that starts a background process, lists all jobs, and then brings the background process to the foreground.

Code:

#!/bin/bash

# Run a sleep command in the background
sleep 30 &

# List all jobs
jobs

# Bring the background process to the foreground
fg %1

Output:

dt@DESKTOP-3KE0KU4:~$ ./test1.sh
[1]+  Running                 sleep 30 &
./test1.sh: line 10: fg: no job control

Explanation:

In the exercise above,

  • Shebang (#!/bin/bash):
    • Specifies that the script should be interpreted by the Bash shell.
  • Run a Sleep Command in the Background:
    • Executes the "sleep 30" command in the background, causing the script to pause for 30 seconds without blocking the shell.
  • List All Jobs:
    • Prints a list of all currently running jobs in the shell session using the jobs command.
  • Bring the Background Process to the Foreground:
    • Brings the background process with job ID %1 (which corresponds to the first job in the list) to the foreground using the "fg" command, allowing interaction with the process.

3.

Sending a Signal to a Process:

Write a Bash script that runs a command in the background, waits for 5 seconds, and then sends the SIGTERM signal to terminate the process.

Code:

#!/bin/bash

# Run the sleep command in the background
echo "Starting a background process (sleep 30)..."
sleep 30 &

# Get the PID of the last background process
PID=$!
echo "Background process started with PID: $PID"

# Wait for 5 seconds
echo "Waiting for 5 seconds before sending SIGTERM..."
sleep 5

# Send SIGTERM signal to terminate the process
echo "Sending SIGTERM signal to process with PID: $PID"
kill -SIGTERM $PID

# Verify if the process is terminated
if kill -0 $PID 2>/dev/null; then
  echo "Process $PID is still running."
else
  echo "Process $PID has been terminated."
fi

Output:

rg@DESKTOP-3KE0KU4:~$ ./test1.sh
Starting a background process (sleep 30)...
Background process started with PID: 51
Waiting for 5 seconds before sending SIGTERM...
Sending SIGTERM signal to process with PID: 51
Process 51 has been terminated.
./test1.sh: line 25:    51 Terminated              sleep 30

Explanation:

In the exercise above,

  • Starting a Background Process:
    • echo "Starting a background process (sleep 30)...": Informs the user that a background process is starting.
  • Displaying the PID:
    • echo "Background process started with PID: $PID": Displays the PID of the background process.
  • Waiting Period:
    • echo "Waiting for 5 seconds before sending SIGTERM...": Notifies the user about the waiting period before sending the signal.
  • Sending SIGTERM Signal:
    • echo "Sending SIGTERM signal to process with PID: $PID": Informs the user that the SIGTERM signal is being sent to the background process.
  • Verifying Termination:
    • Adds a check to see if the process is still running after attempting to send the SIGTERM signal:

4.

Handling Signals in a Script:

Write a Bash script that traps the SIGINT signal (Ctrl+C) and prints a message instead of terminating.

Code:

#!/bin/bash

# Function to handle SIGINT
handle_sigint() {
  echo "Caught SIGINT signal! Exiting gracefully..."
  exit 0
}

# Trap SIGINT signal
trap handle_sigint SIGINT

# Infinite loop to keep the script running
while true; do
  echo "Running... Press Ctrl+C to terminate."
  sleep 1
done

Output:

dt@DESKTOP-3KE0KU4:~$ ./test1.sh
Running... Press Ctrl+C to terminate.
Running... Press Ctrl+C to terminate.
Running... Press Ctrl+C to terminate.
Running... Press Ctrl+C to terminate.
^CCaught SIGINT signal! Exiting gracefully...

Explanation:

In the exercise above,

  • Function to Handle SIGINT:
    • handle_sigint(): This function now includes an exit 0 command to terminate the script gracefully when Ctrl+C is pressed.
  • Trap SIGINT Signal:
    • trap handle_sigint SIGINT: This traps the SIGINT signal (Ctrl+C) and invokes the handle_sigint function when the signal is received.
  • Running Message:
    • echo "Running... Press Ctrl+C to terminate.": This message is displayed each second to indicate that the script is running and how to terminate it..

5.

Ignoring Signals:

Write a Bash script that ignores the SIGHUP signal.

Code:

#!/bin/bash

# Function to handle SIGINT
handle_sigint() {
  echo "Caught SIGINT signal! Exiting gracefully..."
  exit 0
}

# Ignore SIGHUP signal
trap '' SIGHUP

# Trap SIGINT signal
trap handle_sigint SIGINT

# Infinite loop to keep the script running
while true; do
  echo "Running... Press Ctrl+C to terminate."
  sleep 1
done

Output:

rg@DESKTOP-3KE0KU4:~$ ./test1.sh
Running... Press Ctrl+C to terminate.
Running... Press Ctrl+C to terminate.
Running... Press Ctrl+C to terminate.
Running... Press Ctrl+C to terminate.
^CCaught SIGINT signal! Exiting gracefully...
rg@DESKTOP-3KE0KU4:~$ vi test1.sh

Explanation:

In the exercise above,

  • Function to Handle SIGINT:
    • handle_sigint(): This function includes an exit 0 command to terminate the script gracefully when Ctrl+C is pressed.
  • Ignore SIGHUP Signal:
    • trap '' SIGHUP: This ignores the SIGHUP signal.
  • Trap SIGINT Signal:
    • trap handle_sigint SIGINT: This traps the SIGINT signal (Ctrl+C) and invokes the handle_sigint function when the signal is received.
  • Running Message:
    • echo "Running... Press Ctrl+C to terminate.": This message is displayed each second to indicate that the script is running and how to terminate it.

6.

Using nohup to Run a Process:

Write a Bash script that uses nohup to run a long-running command that continues to run even after the terminal is closed.

Code:

#!/bin/bash

# Run a command with nohup in the background that generates output
echo "Starting a background process with nohup that generates output..."
nohup bash -c 'for i in {1..30}; do echo "Output $i"; sleep 1; done' &

# Get the PID of the last background process
PID=$!
echo "Background process started with PID: $PID"

# Wait for 5 seconds
echo "Waiting for 5 seconds before sending SIGTERM..."
sleep 5

# Send SIGTERM signal to terminate the process
echo "Sending SIGTERM signal to process with PID: $PID"
kill -SIGTERM $PID

# Verify if the process is terminated
sleep 1  # Give a moment for the process to terminate
if kill -0 $PID 2>/dev/null; then
  echo "Process $PID is still running."
else
  echo "Process $PID has been terminated."
fi

Output:

dt@DESKTOP-3KE0KU4:~$ ./test1.sh
Starting a background process with nohup that generates output...
Background process started with PID: 168
Waiting for 5 seconds before sending SIGTERM...
nohup: appending output to 'nohup.out'
Sending SIGTERM signal to process with PID: 168
./test1.sh: line 20:   168 Terminated              nohup bash -c 'for i in {1..30}; do echo "Output $i"; sleep 1; done'
Process 168 has been terminated.
dt@DESKTOP-3KE0KU4:~$ cat nohup.out
Output 1
Output 2
Output 3
Output 4
Output 5

Explanation:

In the exercise above,

  • Shebang (#!/bin/bash):
    • Indicates that the script should be interpreted by the Bash shell.
  • Start the Background Process with nohup:
    • Executes a command in the background using "nohup", ensuring it continues running even if the shell exits. The command is a Bash loop (for i in {1..30}; do echo "Output $i"; sleep 1; done) that generates output for 30 iterations with a 1-second delay between each.
  • Get the PID of the Background Process:
    • Captures the Process ID (PID) of the last background process using the special variable "$!".
  • Wait for 5 seconds:
    • Pauses the script execution for 5 seconds using "sleep 5", allowing the background process to run for a brief period.
  • Send SIGTERM Signal to Terminate the Process:
    • Sends a "SIGTERM" signal to the background process with PID "$PID" using the kill -SIGTERM $PID command, initiating its termination.
  • Verify the Process Termination:
    • Checks if the process with PID "$PID" is still running using "kill -0 $PID 2>/dev/null".
    • If the process is still running, prints a message indicating so; otherwise, prints a message confirming its termination.

7.

Listing All Processes:

Write a Bash script that lists all currently running processes using ps command.

Code:

#!/bin/bash

# List all currently running processes
ps aux

Output:

rg@DESKTOP-3KE0KU4:~$ ./test1.sh
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   8952   596 ?        Ssl  08:10   0:00 /init ro
root       106  0.0  0.0   8952   580 tty1     Ss   08:47   0:00 /init ro
rg         107  0.0  0.0  15104  3572 tty1     S    08:47   0:00 -bash
rg         181  0.0  0.0  13204  1360 tty1     S    10:36   0:00 /bin/bash ./test1.sh
rg         182  0.0  0.0  15664  1852 tty1     R    10:36   0:00 ps aux

Explanation:

In the exercise above,

  • Shebang (#!/bin/bash):
    • Indicates that the script should be interpreted by the Bash shell.
  • List All Currently Running Processes:
    • Displays a list of all currently running processes, including those owned by all users ('aux' flags) using the "ps" command.
    • The "ps" command with the 'aux' options shows detailed information about all processes currently running on the system.

8.

Monitoring a Process:

Write a Bash script that monitors the status of a specific process by its PID and prints its status every 5 seconds.

Code:

#!/bin/bash

# Run a sleep command in the background
sleep 30 &

# Get the PID of the last background process
PID=$!

# Monitor the process status every 5 seconds
while kill -0 $PID 2>/dev/null; do
  echo "Process $PID is still running..."
  sleep 5
done

echo "Process $PID has terminated."

Output:

dt@DESKTOP-3KE0KU4:~$ ./test1.sh
Process 190 is still running...
Process 190 is still running...
Process 190 is still running...
Process 190 is still running...
Process 190 is still running...
Process 190 is still running...
Process 190 has terminated.

Explanation:

In the exercise above,

  • Shebang (#!/bin/bash):
    • Specifies that the script should be interpreted by the Bash shell.
  • Run a Sleep Command in the background:
    • Executes the sleep 30 command in the background, causing the script to pause for 30 seconds without blocking the shell.
  • Get the PID of the last background process:
    • Captures the Process ID (PID) of the last background process using the special variable '$!'.
  • Monitor the process status:
    • Enters a "while" loop that continues as long as the process with the captured PID is running.
    • Uses the kill -0 $PID command to check if the process with PID '$PID' is still running.
    • Prints a message indicating that the process is still running every 5 seconds using the echo command and pauses execution for 5 seconds with sleep 5.
  • Process termination message:
    • After the loop exits (when the process terminates), prints a message indicating that the process with the captured PID has terminated.

9.

Using pkill to Terminate Processes by Name:

Write a Bash script that runs multiple instances of a command and then uses pkill to terminate all instances of that command.

Code:

#!/bin/bash

# Run multiple instances of the sleep command in the background
sleep 100 &
sleep 100 &
sleep 100 &

# Wait for a few seconds
sleep 2

# Terminate all instances of the sleep command
pkill sleep


Output:

dt@DESKTOP-3KE0KU4:~$ ./test1.sh
./test1.sh: line 12:   200 Terminated              sleep 100
./test1.sh: line 12:   201 Terminated              sleep 100
./test1.sh: line 12:   202 Terminated              sleep 100

Explanation:

In the exercise above,

  • Shebang (#!/bin/bash):
    • Specifies that the script should be interpreted by the Bash shell.
  • Run multiple instances of the sleep command in the background:
    • Executes three instances of the "sleep 100" command concurrently in the background, causing the script to pause for 100 seconds each without blocking the shell.
  • Wait for a few seconds:
    • Pauses the script execution for 2 seconds using the sleep 2 command, allowing the background processes to run for a short duration.
  • Terminate all instances of the sleep command:
    • Terminates all instances of the "sleep" command using the "pkill sleep" command, ensuring that any remaining background processes are stopped abruptly.

10.

Writing a Daemon Script:

Write a Bash script that runs as a daemon, performing a specific task (e.g., logging the date and time to a file) every 10 seconds.

Code:

#!/bin/bash

# Run as a daemon
while true; do
  # Log the date and time to a file
  echo "$(date)" >> /tmp/daemon.log
  sleep 10
done &


Output:

dt@DESKTOP-3KE0KU4:~$ ./test1.sh
 
dt@DESKTOP-3KE0KU4:~$ cat /tmp/daemon.log
Mon May 27 11:08:49 IST 2020
Mon May 27 11:08:59 IST 2020
Mon May 27 11:09:09 IST 2020
Mon May 27 11:09:19 IST 2020
Mon May 27 11:09:29 IST 2020
Mon May 27 11:09:39 IST 2020
Mon May 27 11:09:49 IST 2020
Mon May 27 11:09:59 IST 2020
Mon May 27 11:10:09 IST 2020

Explanation:

In the exercise above,

  • Shebang (#!/bin/bash):
    • Indicates that the script should be interpreted by the Bash shell.
  • Run as a Daemon:
    • Starts an infinite loop (while true; do) to run continuously in the background.
  • Log Date and Time to a File:
    • Appends the current date and time to the file /tmp/daemon.log using the echo "$(date)" >> /tmp/daemon.log command. This logs the timestamp periodically.
  • Pause execution:
    • Pause script execution for 10 seconds using the "sleep 10" command before the next iteration of the loop.
  • Run in the background:
    • The entire loop is executed in the background (denoted by & at the end of the loop), allowing the script to continue running independently while the main shell prompt remains available for other commands.

Bash Editor:


More to Come !

Do not submit any solution of the above exercises at here, if you want to contribute go to the appropriate exercise page.



Become a Patron!

Follow us on Facebook and Twitter for latest update.

It will be nice if you may share this link in any developer community or anywhere else, from where other developers may find this content. Thanks.

https://www.w3resource.com/bash-script-exercises/process-management.php