Introduction
Linux processes are fundamental components of the operating system that execute programs and perform tasks. When developing shell scripts, it's often necessary to run multiple processes concurrently and ensure they complete before continuing with subsequent operations.
In this lab, you will learn about the wait command in Linux shell scripting. This powerful tool allows parent processes to pause execution until their background child processes have completed. By mastering process waiting techniques, you can create more efficient scripts that properly coordinate multiple concurrent operations.
Understanding process waiting is essential for system administration, automation, and developing robust shell scripts. You will learn how to start background processes, wait for their completion, and handle their exit statuses to ensure reliable execution flow.
Understanding Linux Processes and Background Execution
In this step, you will learn about Linux processes and how to run commands in the background using the & operator.
What are Linux Processes?
A process in Linux is an instance of a running program. Each process has a unique Process ID (PID) and runs independently of other processes. When you run a command in the terminal, you start a process.
Running Processes in the Background
Normally, when you run a command in the terminal, you need to wait for it to complete before you can run another command. However, you can run a command in the background by appending an ampersand & at the end of the command.
Let's try this out:
Navigate to your project directory:
cd ~/projectCreate a simple script that simulates a long-running task:
nano long_task.shAdd the following content to the script:
#!/bin/bash echo "Starting long task with PID $$" sleep 5 echo "Long task completed"Save the file by pressing
Ctrl+O, thenEnter, and exit withCtrl+X.Make the script executable:
chmod +x long_task.shRun the script normally:
./long_task.shYou'll see output like:
Starting long task with PID 1234 Long task completedNotice that you had to wait for the script to complete before getting your command prompt back.
Now run the script in the background:
./long_task.sh &You'll see output like:
[1] 1235 Starting long task with PID 1235The
[1]is the job number, and1235is the PID. Notice that you get your command prompt back immediately.After about 5 seconds, you'll see:
Long task completed [1]+ Done ./long_task.shThis indicates that the background process has completed.
When you run a command in the background, the shell doesn't wait for it to complete before allowing you to enter more commands. This is useful for running multiple tasks concurrently.
Using the wait Command to Synchronize Processes
In this step, you will learn how to use the wait command to synchronize processes, making the parent process wait for the completion of background processes.
What is the wait Command?
The wait command is used in shell scripts to pause the execution of the script until one or more background processes have completed. This is particularly useful when you need to ensure that certain tasks finish before proceeding with subsequent operations.
Using wait Without Arguments
When used without arguments, the wait command waits for all background processes to complete.
Let's create a script that demonstrates this:
Navigate to your project directory:
cd ~/projectCreate a new script:
nano wait_demo.shAdd the following content to the script:
#!/bin/bash echo "Starting background tasks..." ## Start two background tasks ./long_task.sh & ./long_task.sh & echo "Waiting for all background tasks to complete..." wait echo "All background tasks have completed!"Save and exit the editor by pressing
Ctrl+O, thenEnter, and finallyCtrl+X.Make the script executable:
chmod +x wait_demo.shRun the script:
./wait_demo.shYou'll see output similar to:
Starting background tasks... Starting long task with PID 1236 Starting long task with PID 1237 Waiting for all background tasks to complete... Long task completed Long task completed All background tasks have completed!
Notice that the message "All background tasks have completed!" only appears after both long tasks have finished. This demonstrates how the wait command pauses the script until all background processes complete.
Using wait with a Specific PID
You can also use wait to wait for a specific process by providing its PID:
Create another script:
nano wait_pid_demo.shAdd the following content:
#!/bin/bash echo "Starting background tasks..." ## Start two background tasks and capture their PIDs ./long_task.sh & pid1=$! ./long_task.sh & pid2=$! echo "First process PID: $pid1" echo "Second process PID: $pid2" echo "Waiting for the first task to complete..." wait $pid1 echo "First task has completed!" echo "Waiting for the second task to complete..." wait $pid2 echo "Second task has completed!"Save and exit the editor by pressing
Ctrl+O, thenEnter, and finallyCtrl+X.Make the script executable:
chmod +x wait_pid_demo.shRun the script:
./wait_pid_demo.shThe output will show that the script waits for each process individually.
The $! variable contains the PID of the most recently executed background process. This allows you to capture and later use the PID with the wait command.
Handling wait Return Status
In this step, you will learn how to capture and handle the return status of the wait command, which reflects the exit status of the background processes.
Understanding Exit and Return Status
In Linux, every command returns an exit status when it completes. An exit status of 0 typically indicates success, while a non-zero value indicates an error or some form of failure.
The wait command returns the exit status of the waited-for command. If multiple processes are waited for, it returns the exit status of the last process that terminated.
Let's create scripts to demonstrate this:
Navigate to your project directory:
cd ~/projectCreate a script that succeeds:
nano success_task.shAdd the following content:
#!/bin/bash echo "Starting success task" sleep 2 echo "Success task completed successfully" exit 0 ## Exit with success statusSave and exit by pressing
Ctrl+O, thenEnter, and finallyCtrl+X. Then make it executable:chmod +x success_task.shCreate a script that fails:
nano fail_task.shAdd the following content:
#!/bin/bash echo "Starting fail task" sleep 3 echo "Fail task encountered an error" exit 1 ## Exit with error statusSave and exit by pressing
Ctrl+O, thenEnter, and finallyCtrl+X. Then make it executable:chmod +x fail_task.shNow create a script that captures the wait status:
nano wait_status_demo.shAdd the following content:
#!/bin/bash echo "Running a successful background task..." ./success_task.sh & wait wait_status=$? echo "Wait returned with status: $wait_status" if [ $wait_status -eq 0 ]; then echo "The background task succeeded!" else echo "The background task failed with status: $wait_status" fi echo "" echo "Running a failing background task..." ./fail_task.sh & wait wait_status=$? echo "Wait returned with status: $wait_status" if [ $wait_status -eq 0 ]; then echo "The background task succeeded!" else echo "The background task failed with status: $wait_status" fiSave and exit by pressing
Ctrl+O, thenEnter, and finallyCtrl+X. Then make it executable:chmod +x wait_status_demo.shRun the script:
./wait_status_demo.shYou'll see output similar to:
Running a successful background task... Starting success task Success task completed successfully Wait returned with status: 0 The background task succeeded! Running a failing background task... Starting fail task Fail task encountered an error Wait returned with status: 1 The background task failed with status: 1
This demonstrates how you can use the return status of the wait command to determine whether background processes completed successfully or not, which is essential for error handling in shell scripts.
Completing a Practical Application
In this final step, you will apply what you've learned to create a more complex script that simulates a system preparation process. This script will coordinate multiple background tasks and ensure they all complete successfully before proceeding.
Creating the Preparation Scripts
First, we'll create two scripts that simulate different preparation tasks:
Navigate to your project directory:
cd ~/projectCreate the first preparation script:
nano decorate_hall.shAdd the following content:
#!/bin/bash echo "Decorating the hall..." sleep 3 echo "Hanging decorations..." sleep 2 echo "Decoration complete." exit 0Save and exit by pressing
Ctrl+O, thenEnter, and finallyCtrl+X. Then make it executable:chmod +x decorate_hall.shCreate the second preparation script:
nano cook_feast.shAdd the following content:
#!/bin/bash echo "Preparing ingredients..." sleep 2 echo "Cooking main dishes..." sleep 3 echo "Preparing desserts..." sleep 1 echo "Cooking complete." exit 0Save and exit by pressing
Ctrl+O, thenEnter, and finallyCtrl+X. Then make it executable:chmod +x cook_feast.sh
Creating the Main Coordination Script
Now, let's create the main script that will coordinate these preparation tasks:
Create the main script:
nano prepare_feast.shAdd the following content:
#!/bin/bash echo "=== Preparation Ceremony Started ===" echo "Starting all preparation tasks..." ## Start the preparations in the background ./decorate_hall.sh & decoration_pid=$! ./cook_feast.sh & cooking_pid=$! echo "All tasks started. Waiting for completion..." ## Wait for decoration to finish wait $decoration_pid decoration_status=$? if [ $decoration_status -eq 0 ]; then echo "Decoration completed successfully." else echo "Error: Decoration failed with status $decoration_status" exit 1 fi ## Wait for cooking to finish wait $cooking_pid cooking_status=$? if [ $cooking_status -eq 0 ]; then echo "Cooking completed successfully." else echo "Error: Cooking failed with status $cooking_status" exit 1 fi ## All preparations completed successfully echo "=== All preparations completed successfully! ===" echo "The ceremony can now begin." ## Create a verification file to indicate successful completion echo "decoration_status=$decoration_status" > preparation_results.txt echo "cooking_status=$cooking_status" >> preparation_results.txt echo "overall_status=0" >> preparation_results.txt exit 0Save and exit by pressing
Ctrl+O, thenEnter, and finallyCtrl+X. Then make it executable:chmod +x prepare_feast.shRun the main script:
./prepare_feast.shYou'll see the output of all the preparation tasks running concurrently, and the main script waiting for each to complete before declaring the overall success.
Understanding the Script
Let's examine key parts of the main script:
- We start each preparation task in the background using
& - We capture each task's PID using
$! - We wait for each task to complete using
wait $pid - We check the exit status of each task
- We create a verification file with the results
This approach allows us to:
- Run multiple tasks concurrently
- Monitor the success/failure of each task
- Abort the overall process if any individual task fails
- Create a record of the results
This is a common pattern in system administration and automation scripts, where multiple processes need to be coordinated and monitored.
Summary
In this lab, you have learned how to effectively manage and synchronize processes in Linux using the wait command. This important skill enables you to create more sophisticated shell scripts that can coordinate multiple concurrent operations.
The key concepts you've mastered include:
- Running processes in the background using the
&operator - Using the
waitcommand to pause execution until background processes complete - Waiting for specific processes by their PID
- Capturing and handling the return status of the
waitcommand - Implementing error handling for background processes
- Coordinating multiple concurrent tasks in a practical scenario
These skills are fundamental for system administration, automation, and shell scripting in Linux environments. By properly managing process synchronization, you can create more efficient scripts that make use of concurrency while still maintaining the proper sequence of dependent operations.
Whether you're developing build systems, deployment scripts, or system administration tools, the ability to coordinate multiple processes is an essential skill that will allow you to create more powerful and efficient solutions.



