Введение
Процессы Linux являются основными компонентами операционной системы, которые выполняют программы и выполняют задачи. При разработке шелл-скриптов часто необходимо запускать несколько процессов одновременно и убедиться, что они завершатся перед продолжением последующих операций.
В этом лабораторном занятии (LabEx) вы узнаете о команде wait в шелл-скриптах Linux. Эта мощная утилита позволяет родительским процессам приостановить выполнение до завершения их дочерних процессов, запущенных в фоновом режиме. Освоив техники ожидания завершения процессов, вы сможете создавать более эффективные скрипты, которые правильно координируют несколько одновременных операций.
Понимание ожидания завершения процессов является важным аспектом системного администрирования, автоматизации и разработки надежных шелл-скриптов. Вы научитесь запускать процессы в фоновом режиме, ожидать их завершения и обрабатывать их статусы завершения, чтобы обеспечить надежное выполнение скрипта.
Понимание процессов Linux и фонового выполнения
На этом этапе вы узнаете о процессах Linux и о том, как запускать команды в фоновом режиме с использованием оператора &.
Что такое процессы Linux?
Процесс в Linux представляет собой экземпляр запущенной программы. Каждый процесс имеет уникальный идентификатор процесса (Process ID, PID) и выполняется независимо от других процессов. Когда вы запускаете команду в терминале, вы запускаете процесс.
Запуск процессов в фоновом режиме
Обычно, когда вы запускаете команду в терминале, вам нужно дождаться ее завершения, прежде чем можно будет запустить другую команду. Однако вы можете запустить команду в фоновом режиме, добавив амперсанд & в конце команды.
Давайте попробуем это:
Перейдите в каталог проекта:
cd ~/projectСоздайте простой скрипт, который имитирует длительную задачу:
nano long_task.shДобавьте следующее содержимое в скрипт:
#!/bin/bash echo "Starting long task with PID $$" sleep 5 echo "Long task completed"Сохраните файл, нажав
Ctrl+O, затемEnter, и выйдите, нажавCtrl+X.Сделайте скрипт исполняемым:
chmod +x long_task.shЗапустите скрипт обычным образом:
./long_task.shВы увидите вывод, похожий на следующий:
Starting long task with PID 1234 Long task completedОбратите внимание, что вам пришлось ждать завершения скрипта, прежде чем получить обратно приглашение командной строки.
Теперь запустите скрипт в фоновом режиме:
./long_task.sh &Вы увидите вывод, похожий на следующий:
[1] 1235 Starting long task with PID 1235[1]- это номер задания (job number), а1235- это PID. Обратите внимание, что вы сразу же получаете приглашение командной строки.Через примерно 5 секунд вы увидите:
Long task completed [1]+ Done ./long_task.shЭто означает, что фоновый процесс завершился.
Когда вы запускаете команду в фоновом режиме, оболочка (shell) не ждет ее завершения, прежде чем позволить вам вводить дополнительные команды. Это полезно для одновременного выполнения нескольких задач.
Использование команды wait для синхронизации процессов
На этом этапе вы узнаете, как использовать команду wait для синхронизации процессов, заставляя родительский процесс ждать завершения фоновых процессов.
Что такое команда wait?
Команда wait используется в шелл-скриптах для приостановки выполнения скрипта до завершения одного или нескольких фоновых процессов. Это особенно полезно, когда вам нужно убедиться, что определенные задачи завершатся перед переходом к последующим операциям.
Использование команды wait без аргументов
При использовании без аргументов команда wait ждет завершения всех фоновых процессов.
Давайте создадим скрипт, который демонстрирует это:
Перейдите в каталог проекта:
cd ~/projectСоздайте новый скрипт:
nano wait_demo.shДобавьте следующее содержимое в скрипт:
#!/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!"Сохраните файл и выйдите из редактора, нажав
Ctrl+O, затемEnter, и в концеCtrl+X.Сделайте скрипт исполняемым:
chmod +x wait_demo.shЗапустите скрипт:
./wait_demo.shВы увидите вывод, похожий на следующий:
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!
Обратите внимание, что сообщение "All background tasks have completed!" появляется только после завершения обеих длительных задач. Это демонстрирует, как команда wait приостанавливает выполнение скрипта до завершения всех фоновых процессов.
Использование команды wait с определенным PID
Вы также можете использовать команду wait для ожидания завершения определенного процесса, указав его PID:
Создайте еще один скрипт:
nano wait_pid_demo.shДобавьте следующее содержимое:
#!/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!"Сохраните файл и выйдите из редактора, нажав
Ctrl+O, затемEnter, и в концеCtrl+X.Сделайте скрипт исполняемым:
chmod +x wait_pid_demo.shЗапустите скрипт:
./wait_pid_demo.shВывод показывает, что скрипт ждет завершения каждого процесса по отдельности.
Переменная $! содержит PID последнего запущенного фонового процесса. Это позволяет вам сохранить PID и использовать его позже с командой wait.
Обработка возвращаемого статуса команды wait
На этом этапе вы узнаете, как получить и обработать возвращаемый статус команды wait, который отражает статус завершения фоновых процессов.
Понимание статуса выхода и возврата
В Linux каждая команда возвращает статус выхода при завершении. Статус выхода 0 обычно означает успешное выполнение, в то время как ненулевое значение указывает на ошибку или какую - то форму неудачи.
Команда wait возвращает статус выхода команды, на которую она ждет. Если ожидается завершение нескольких процессов, она возвращает статус выхода последнего завершившегося процесса.
Давайте создадим скрипты, чтобы продемонстрировать это:
Перейдите в каталог проекта:
cd ~/projectСоздайте скрипт, который завершается успешно:
nano success_task.shДобавьте следующее содержимое:
#!/bin/bash echo "Starting success task" sleep 2 echo "Success task completed successfully" exit 0 ## Exit with success statusСохраните и выйдите, нажав
Ctrl+O, затемEnter, и в концеCtrl+X. Затем сделайте его исполняемым:chmod +x success_task.shСоздайте скрипт, который завершается с ошибкой:
nano fail_task.shДобавьте следующее содержимое:
#!/bin/bash echo "Starting fail task" sleep 3 echo "Fail task encountered an error" exit 1 ## Exit with error statusСохраните и выйдите, нажав
Ctrl+O, затемEnter, и в концеCtrl+X. Затем сделайте его исполняемым:chmod +x fail_task.shТеперь создайте скрипт, который получает статус ожидания:
nano wait_status_demo.shДобавьте следующее содержимое:
#!/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" fiСохраните и выйдите, нажав
Ctrl+O, затемEnter, и в концеCtrl+X. Затем сделайте его исполняемым:chmod +x wait_status_demo.shЗапустите скрипт:
./wait_status_demo.shВы увидите вывод, похожий на следующий:
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
Это демонстрирует, как можно использовать возвращаемый статус команды wait для определения того, завершились ли фоновые процессы успешно или нет, что является важной частью обработки ошибок в шелл - скриптах.
Завершение практического приложения
На этом последнем этапе вы примените полученные знания для создания более сложного скрипта, который имитирует процесс подготовки системы. Этот скрипт будет координировать несколько фоновых задач и обеспечивать их успешное завершение перед переходом к следующим действиям.
Создание скриптов подготовки
Сначала мы создадим два скрипта, которые имитируют различные задачи подготовки:
Перейдите в каталог проекта:
cd ~/projectСоздайте первый скрипт подготовки:
nano decorate_hall.shДобавьте следующее содержимое:
#!/bin/bash echo "Decorating the hall..." sleep 3 echo "Hanging decorations..." sleep 2 echo "Decoration complete." exit 0Сохраните и выйдите, нажав
Ctrl+O, затемEnter, и в концеCtrl+X. Затем сделайте его исполняемым:chmod +x decorate_hall.shСоздайте второй скрипт подготовки:
nano cook_feast.shДобавьте следующее содержимое:
#!/bin/bash echo "Preparing ingredients..." sleep 2 echo "Cooking main dishes..." sleep 3 echo "Preparing desserts..." sleep 1 echo "Cooking complete." exit 0Сохраните и выйдите, нажав
Ctrl+O, затемEnter, и в концеCtrl+X. Затем сделайте его исполняемым:chmod +x cook_feast.sh
Создание основного скрипта координации
Теперь создадим основной скрипт, который будет координировать эти задачи подготовки:
Создайте основной скрипт:
nano prepare_feast.shДобавьте следующее содержимое:
#!/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 0Сохраните и выйдите, нажав
Ctrl+O, затемEnter, и в концеCtrl+X. Затем сделайте его исполняемым:chmod +x prepare_feast.shЗапустите основной скрипт:
./prepare_feast.shВы увидите вывод всех задач подготовки, выполняющихся параллельно, и основной скрипт будет ждать завершения каждой задачи перед объявлением общего успеха.
Понимание скрипта
Рассмотрим ключевые части основного скрипта:
- Мы запускаем каждую задачу подготовки в фоновом режиме с помощью
& - Мы получаем PID каждой задачи с помощью
$! - Мы ждем завершения каждой задачи с помощью
wait $pid - Мы проверяем статус выхода каждой задачи
- Мы создаем файл подтверждения с результатами
Этот подход позволяет нам:
- Запускать несколько задач параллельно
- Отслеживать успех/неудачу каждой задачи
- Прерывать общий процесс, если любая из задач завершается с ошибкой
- Создавать запись о результатах
Это распространенная схема в системном администрировании и автоматизации скриптов, где необходимо координировать и отслеживать несколько процессов.
Резюме
В этом практическом занятии вы научились эффективно управлять и синхронизировать процессы в Linux с использованием команды wait. Это важное умение позволяет создавать более сложные шелл - скрипты, которые могут координировать несколько одновременных операций.
Ключевые концепции, которые вы освоили, включают:
- Запуск процессов в фоновом режиме с использованием оператора
& - Использование команды
waitдля приостановки выполнения до завершения фоновых процессов - Ожидание завершения конкретных процессов по их PID
- Получение и обработка возвращаемого статуса команды
wait - Реализация обработки ошибок для фоновых процессов
- Координация нескольких одновременных задач в практическом сценарии
Эти навыки являются фундаментальными для системного администрирования, автоматизации и написания шелл - скриптов в Linux - средах. Правильное управление синхронизацией процессов позволяет создавать более эффективные скрипты, которые используют параллелизм, сохраняя при этом правильную последовательность зависимых операций.
Будь то разработка систем сборки, скриптов развертывания или инструментов системного администрирования, способность координировать несколько процессов является важным навыком, который позволит создавать более мощные и эффективные решения.



