Ожидание процессов в Linux

LinuxLinuxBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

Процессы Linux являются основными компонентами операционной системы, которые выполняют программы и выполняют задачи. При разработке шелл-скриптов часто необходимо запускать несколько процессов одновременно и убедиться, что они завершатся перед продолжением последующих операций.

В этом лабораторном занятии (LabEx) вы узнаете о команде wait в шелл-скриптах Linux. Эта мощная утилита позволяет родительским процессам приостановить выполнение до завершения их дочерних процессов, запущенных в фоновом режиме. Освоив техники ожидания завершения процессов, вы сможете создавать более эффективные скрипты, которые правильно координируют несколько одновременных операций.

Понимание ожидания завершения процессов является важным аспектом системного администрирования, автоматизации и разработки надежных шелл-скриптов. Вы научитесь запускать процессы в фоновом режиме, ожидать их завершения и обрабатывать их статусы завершения, чтобы обеспечить надежное выполнение скрипта.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL linux(("Linux")) -.-> linux/BasicFileOperationsGroup(["Basic File Operations"]) linux(("Linux")) -.-> linux/FileandDirectoryManagementGroup(["File and Directory Management"]) linux(("Linux")) -.-> linux/ProcessManagementandControlGroup(["Process Management and Control"]) linux(("Linux")) -.-> linux/VersionControlandTextEditorsGroup(["Version Control and Text Editors"]) linux/BasicFileOperationsGroup -.-> linux/chmod("Permission Modifying") linux/FileandDirectoryManagementGroup -.-> linux/cd("Directory Changing") linux/ProcessManagementandControlGroup -.-> linux/wait("Process Waiting") linux/VersionControlandTextEditorsGroup -.-> linux/nano("Simple Text Editing") subgraph Lab Skills linux/chmod -.-> lab-271433{{"Ожидание процессов в Linux"}} linux/cd -.-> lab-271433{{"Ожидание процессов в Linux"}} linux/wait -.-> lab-271433{{"Ожидание процессов в Linux"}} linux/nano -.-> lab-271433{{"Ожидание процессов в Linux"}} end

Понимание процессов Linux и выполнение в фоновом режиме

На этом этапе вы узнаете о процессах Linux и о том, как запускать команды в фоновом режиме с использованием оператора &.

Что такое процессы Linux?

Процесс в Linux представляет собой экземпляр запущенной программы. Каждый процесс имеет уникальный идентификатор процесса (Process ID, PID) и выполняется независимо от других процессов. Когда вы запускаете команду в терминале, вы запускаете процесс.

Запуск процессов в фоновом режиме

Обычно, когда вы запускаете команду в терминале, вам нужно дождаться ее завершения, прежде чем можно будет запустить другую команду. Однако вы можете запустить команду в фоновом режиме, добавив амперсанд & в конце команды.

Давайте попробуем это:

  1. Перейдите в каталог проекта:

    cd ~/project
  2. Создайте простой скрипт, который имитирует длительную задачу:

    nano long_task.sh
  3. Добавьте следующее содержимое в скрипт:

    #!/bin/bash
    echo "Starting long task with PID $$"
    sleep 5
    echo "Long task completed"
  4. Сохраните файл, нажав Ctrl+O, затем Enter, и выйдите, нажав Ctrl+X.

  5. Сделайте скрипт исполняемым:

    chmod +x long_task.sh
  6. Запустите скрипт обычным образом:

    ./long_task.sh

    Вы увидите вывод, похожий на следующий:

    Starting long task with PID 1234
    Long task completed

    Обратите внимание, что вам пришлось ждать завершения скрипта, прежде чем получить обратно приглашение командной строки.

  7. Теперь запустите скрипт в фоновом режиме:

    ./long_task.sh &

    Вы увидите вывод, похожий на следующий:

    [1] 1235
    Starting long task with PID 1235

    [1] - это номер задания (job number), а 1235 - это PID. Обратите внимание, что вы сразу же получаете приглашение командной строки.

  8. Через примерно 5 секунд вы увидите:

    Long task completed
    [1]+  Done                    ./long_task.sh

    Это означает, что фоновый процесс завершился.

Когда вы запускаете команду в фоновом режиме, оболочка (shell) не ждет ее завершения, прежде чем позволить вам вводить дополнительные команды. Это полезно для одновременного выполнения нескольких задач.

Использование команды wait для синхронизации процессов

На этом этапе вы узнаете, как использовать команду wait для синхронизации процессов, заставляя родительский процесс ждать завершения фоновых процессов.

Что такое команда wait?

Команда wait используется в шелл-скриптах для приостановки выполнения скрипта до завершения одного или нескольких фоновых процессов. Это особенно полезно, когда вам нужно убедиться, что определенные задачи завершатся перед переходом к последующим операциям.

Использование команды wait без аргументов

При использовании без аргументов команда wait ждет завершения всех фоновых процессов.

Давайте создадим скрипт, который демонстрирует это:

  1. Перейдите в каталог проекта:

    cd ~/project
  2. Создайте новый скрипт:

    nano wait_demo.sh
  3. Добавьте следующее содержимое в скрипт:

    #!/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!"
  4. Сохраните файл и выйдите из редактора, нажав Ctrl+O, затем Enter, и в конце Ctrl+X.

  5. Сделайте скрипт исполняемым:

    chmod +x wait_demo.sh
  6. Запустите скрипт:

    ./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:

  1. Создайте еще один скрипт:

    nano wait_pid_demo.sh
  2. Добавьте следующее содержимое:

    #!/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!"
  3. Сохраните файл и выйдите из редактора, нажав Ctrl+O, затем Enter, и в конце Ctrl+X.

  4. Сделайте скрипт исполняемым:

    chmod +x wait_pid_demo.sh
  5. Запустите скрипт:

    ./wait_pid_demo.sh

    Вывод показывает, что скрипт ждет завершения каждого процесса по отдельности.

Переменная $! содержит PID последнего запущенного фонового процесса. Это позволяет вам сохранить PID и использовать его позже с командой wait.

Обработка возвращаемого статуса команды wait

На этом этапе вы узнаете, как получить и обработать возвращаемый статус команды wait, который отражает статус завершения фоновых процессов.

Понимание статуса выхода и возврата

В Linux каждая команда возвращает статус выхода при завершении. Статус выхода 0 обычно означает успешное выполнение, в то время как ненулевое значение указывает на ошибку или какую - то форму неудачи.

Команда wait возвращает статус выхода команды, на которую она ждет. Если ожидается завершение нескольких процессов, она возвращает статус выхода последнего завершившегося процесса.

Давайте создадим скрипты, чтобы продемонстрировать это:

  1. Перейдите в каталог проекта:

    cd ~/project
  2. Создайте скрипт, который завершается успешно:

    nano success_task.sh
  3. Добавьте следующее содержимое:

    #!/bin/bash
    echo "Starting success task"
    sleep 2
    echo "Success task completed successfully"
    exit 0 ## Exit with success status
  4. Сохраните и выйдите, нажав Ctrl+O, затем Enter, и в конце Ctrl+X. Затем сделайте его исполняемым:

    chmod +x success_task.sh
  5. Создайте скрипт, который завершается с ошибкой:

    nano fail_task.sh
  6. Добавьте следующее содержимое:

    #!/bin/bash
    echo "Starting fail task"
    sleep 3
    echo "Fail task encountered an error"
    exit 1 ## Exit with error status
  7. Сохраните и выйдите, нажав Ctrl+O, затем Enter, и в конце Ctrl+X. Затем сделайте его исполняемым:

    chmod +x fail_task.sh
  8. Теперь создайте скрипт, который получает статус ожидания:

    nano wait_status_demo.sh
  9. Добавьте следующее содержимое:

    #!/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
  10. Сохраните и выйдите, нажав Ctrl+O, затем Enter, и в конце Ctrl+X. Затем сделайте его исполняемым:

    chmod +x wait_status_demo.sh
  11. Запустите скрипт:

    ./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 для определения того, завершились ли фоновые процессы успешно или нет, что является важной частью обработки ошибок в шелл - скриптах.

Создание практического приложения

На этом последнем этапе вы примените полученные знания для создания более сложного скрипта, который имитирует процесс подготовки системы. Этот скрипт будет координировать несколько фоновых задач и обеспечивать их успешное завершение перед переходом к следующим действиям.

Создание скриптов подготовки

Сначала мы создадим два скрипта, которые имитируют различные задачи подготовки:

  1. Перейдите в каталог проекта:

    cd ~/project
  2. Создайте первый скрипт подготовки:

    nano decorate_hall.sh
  3. Добавьте следующее содержимое:

    #!/bin/bash
    echo "Decorating the hall..."
    sleep 3
    echo "Hanging decorations..."
    sleep 2
    echo "Decoration complete."
    exit 0
  4. Сохраните и выйдите, нажав Ctrl+O, затем Enter, и в конце Ctrl+X. Затем сделайте его исполняемым:

    chmod +x decorate_hall.sh
  5. Создайте второй скрипт подготовки:

    nano cook_feast.sh
  6. Добавьте следующее содержимое:

    #!/bin/bash
    echo "Preparing ingredients..."
    sleep 2
    echo "Cooking main dishes..."
    sleep 3
    echo "Preparing desserts..."
    sleep 1
    echo "Cooking complete."
    exit 0
  7. Сохраните и выйдите, нажав Ctrl+O, затем Enter, и в конце Ctrl+X. Затем сделайте его исполняемым:

    chmod +x cook_feast.sh

Создание основного скрипта координации

Теперь создадим основной скрипт, который будет координировать эти задачи подготовки:

  1. Создайте основной скрипт:

    nano prepare_feast.sh
  2. Добавьте следующее содержимое:

    #!/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
  3. Сохраните и выйдите, нажав Ctrl+O, затем Enter, и в конце Ctrl+X. Затем сделайте его исполняемым:

    chmod +x prepare_feast.sh
  4. Запустите основной скрипт:

    ./prepare_feast.sh

    Вы увидите вывод всех задач подготовки, выполняющихся параллельно, и основной скрипт будет ждать завершения каждой задачи перед объявлением общего успеха.

Понимание скрипта

Рассмотрим ключевые части основного скрипта:

  • Мы запускаем каждую задачу подготовки в фоновом режиме с помощью &
  • Мы получаем PID каждой задачи с помощью $!
  • Мы ждем завершения каждой задачи с помощью wait $pid
  • Мы проверяем статус выхода каждой задачи
  • Мы создаем файл подтверждения с результатами

Этот подход позволяет нам:

  1. Запускать несколько задач параллельно
  2. Отслеживать успех/неудачу каждой задачи
  3. Прерывать общий процесс, если любая из задач завершается с ошибкой
  4. Создавать запись о результатах

Это распространенная схема в системном администрировании и автоматизации скриптов, где необходимо координировать и отслеживать несколько процессов.

Резюме

В этом практическом занятии вы научились эффективно управлять и синхронизировать процессы в Linux с использованием команды wait. Это важное умение позволяет создавать более сложные шелл - скрипты, которые могут координировать несколько одновременных операций.

Ключевые концепции, которые вы освоили, включают:

  • Запуск процессов в фоновом режиме с использованием оператора &
  • Использование команды wait для приостановки выполнения до завершения фоновых процессов
  • Ожидание завершения конкретных процессов по их PID
  • Получение и обработка возвращаемого статуса команды wait
  • Реализация обработки ошибок для фоновых процессов
  • Координация нескольких одновременных задач в практическом сценарии

Эти навыки являются фундаментальными для системного администрирования, автоматизации и написания шелл - скриптов в Linux - средах. Правильное управление синхронизацией процессов позволяет создавать более эффективные скрипты, которые используют параллелизм, сохраняя при этом правильную последовательность зависимых операций.

Будь то разработка систем сборки, скриптов развертывания или инструментов системного администрирования, способность координировать несколько процессов является важным навыком, который позволит создавать более мощные и эффективные решения.