Лаб. работа "Управление процессами в Shell"

Лабораторная работа по теме “Управление процессами в языке Shell”


Цель работы

Получить практические навыки управления процессами в операционных системах семейства UNIX/Linux с использованием командного интерпретатора Shell. Научиться запускать, останавливать, отслеживать процессы, управлять их состоянием и приоритетом, а также автоматизировать эти задачи с помощью скриптов.

Теоретическая часть

Процессы в UNIX/Linux

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

Состояния процесса

Процесс может находиться в одном из следующих состояний:

  • Running/Runnable (R): Процесс выполняется или готов к выполнению и ожидает своей очереди на использование процессора.
  • Sleeping (S): Процесс ожидает завершения какого-либо события (например, ввода-вывода). Большинство процессов большую часть времени находятся в этом состоянии.
  • Stopped (T): Процесс остановлен (приостановлен), например, сигналом SIGSTOP или комбинацией клавиш Ctrl+Z.
  • Zombie (Z): Процесс-зомби — это дочерний процесс, который завершил свое выполнение, но его родительский процесс еще не считал его код завершения. Он не потребляет ресурсы процессора, но занимает место в таблице процессов.

Фоновые и приоритетные процессы

  • Приоритетные (Foreground) процессы выполняются в текущей сессии терминала. Они блокируют командную строку до своего завершения. Вы можете взаимодействовать с ними через стандартные потоки ввода/вывода.
  • Фоновые (Background) процессы выполняются независимо от терминала. Командная строка освобождается сразу после их запуска. Для запуска процесса в фоновом режиме в конце команды добавляется амперсанд (&).

Команды для управления процессами

КомандаОписаниеПример использования
psПоказывает информацию о текущих активных процессах.ps aux (показать все процессы всех пользователей)
topИнтерактивный диспетчер процессов. Показывает список процессов в реальном времени.top
htopУлучшенная версия top с более удобным интерфейсом.htop
jobsПоказывает список фоновых задач, запущенных в текущей сессии.jobs -l (показать PID)
fgПереводит фоновую задачу в приоритетный режим.fg %1 (перевести задачу №1)
bgВозобновляет остановленную задачу в фоновом режиме.bg %2 (возобновить задачу №2)
killПосылает сигнал процессу (по умолчанию SIGTERM).kill 1234
pkillПосылает сигнал процессам по их имени.pkill firefox
pgrepНаходит PID процессов по их имени.pgrep bash
killallАналогично pkill, но может иметь отличия в синтаксисе.killall node

Сигналы

Сигналы — это основной механизм межпроцессного взаимодействия в UNIX. Они используются для уведомления процессов о событиях.

СигналНомерОписание
SIGHUP1Hangup. Часто используется для перезагрузки конфигурации демонов.
SIGINT2Interrupt. Сигнал прерывания (аналог Ctrl+C).
SIGKILL9Kill. Безусловное завершение процесса. Процесс не может перехватить этот сигнал.
SIGTERM15Terminate. Сигнал завершения (по умолчанию для kill). Процесс может перехватить его и корректно завершить работу.
SIGSTOP19Stop. Приостанавливает выполнение процесса (не может быть перехвачен).
SIGCONT18Continue. Возобновляет выполнение процесса, остановленного SIGSTOP.

Для отправки конкретного сигнала используется флаг, например: kill -9 <PID> или kill -SIGKILL <PID>.

Необходимое программное обеспечение

  1. Операционная система на базе Linux (например, Ubuntu, CentOS) или macOS.
  2. Эмулятор терминала.
  3. Командный интерпретатор bash (установлен по умолчанию в большинстве систем).
  4. Текстовый редактор (например, nano, vim или VS Code).

Ход работы

Задание 1: Запуск и мониторинг процессов

  1. Откройте терминал.

  2. Запустите команду, которая будет выполняться длительное время. Мы будем использовать sleep. Эта команда просто ждет указанное количество секунд.

    1sleep 600
    
  3. Пока команда выполняется, она блокирует терминал. Откройте второй терминал.

  4. Во втором терминале найдите процесс sleep с помощью команды ps. Используйте grep для фильтрации вывода.

    1ps aux | grep sleep
    
  5. Запишите PID (второй столбец) и PPID (третий столбец) найденного процесса. Обратите внимание, что в выводе может быть и сам процесс grep sleep.

  6. Попробуйте найти тот же процесс с помощью pgrep.

    1pgrep sleep
    
  7. Завершите процесс sleep из второго терминала, используя команду kill и его PID, который вы записали ранее.

    1kill <PID процесса sleep>
    
  8. Вернитесь в первый терминал. Вы должны увидеть сообщение “Terminated” или подобное, и командная строка снова станет доступной.

Задание 2: Управление фоновыми задачами

  1. В терминале запустите sleep 600 в фоновом режиме.

    1sleep 600 &
    

    Командная строка сразу освободится. Система выведет номер задачи (например, [1]) и ее PID.

  2. Проверьте список фоновых задач.

    1jobs
    
  3. Снова запустите еще один процесс в фоне.

    1ping localhost > /dev/null &
    
  4. Еще раз посмотрите на список задач. Теперь их должно быть две.

    1jobs -l
    
  5. Переведите первую задачу (sleep) в приоритетный режим.

    1fg %1
    

    Терминал снова заблокирован.

  6. Приостановите выполнение текущей задачи, нажав Ctrl+Z. Командная строка освободится, а задача получит статус “Stopped”.

  7. Проверьте статус задач командой jobs.

  8. Возобновите выполнение остановленной задачи, но уже в фоновом режиме.

    1bg %1
    
  9. Убедитесь, что задача снова выполняется в фоне (jobs).

  10. Завершите обе фоновые задачи, используя pkill.

    1pkill sleep
    2pkill ping
    
  11. Проверьте, что задачи исчезли из списка jobs.

Задание 3: Использование сигналов

  1. Запустите процесс top.

  2. Откройте второй терминал и найдите PID процесса top.

    1pgrep top
    
  3. Отправьте процессу top сигнал SIGSTOP, чтобы приостановить его.

    1kill -STOP <PID процесса top>
    

    Вернитесь в первый терминал и убедитесь, что top “замер”.

  4. Во втором терминале отправьте сигнал SIGCONT, чтобы возобновить его работу.

    1kill -CONT <PID процесса top>
    

    top снова должен “ожить”.

  5. Теперь отправьте ему сигнал SIGTERM (по умолчанию).

    1kill <PID процесса top>
    

    Процесс top должен корректно завершиться.

Задание 4: Создание скрипта-наблюдателя

Создайте скрипт, который проверяет, запущен ли определенный процесс, и если нет, то запускает его. Это типичная задача для обеспечения работы сервисов.

  1. Создайте файл watcher.sh с помощью текстового редактора.

    1nano watcher.sh
    
  2. Добавьте в него следующий код:

     1#!/bin/bash
     2
     3# Имя процесса, за которым будем следить.
     4# Для примера возьмем простой веб-сервер на Python.
     5PROCESS_NAME="python3"
     6# Команда для запуска процесса.
     7# Запускает веб-сервер в текущей директории на порту 8000 в фоне.
     8START_COMMAND="python3 -m http.server 8000 &"
     9
    10echo "Starting watcher script..."
    11
    12# Ищем PID процесса. Флаг -f ищет по всей командной строке.
    13pgrep -f "http.server" > /dev/null
    14
    15# $? содержит код возврата последней команды. 0 - успешно (процесс найден).
    16if [ $? -eq 0 ]; then
    17    echo "Process is already running."
    18    # Можно вывести PID для информации
    19    pgrep -f "http.server" | xargs echo "PID:"
    20else
    21    echo "Process not found. Starting it..."
    22    # Выполняем команду запуска. eval нужен для корректной обработки &
    23    eval $START_COMMAND
    24    echo "Process started."
    25fi
    26
    27echo "Watcher script finished."
    
  3. Сделайте скрипт исполняемым.

    1chmod +x watcher.sh
    
  4. Запустите скрипт в первый раз. Он должен сообщить, что запускает процесс.

    1./watcher.sh
    
  5. Проверьте, что процесс действительно запущен.

    1ps aux | grep "http.server"
    
  6. Запустите скрипт еще раз. Теперь он должен сообщить, что процесс уже работает.

    1./watcher.sh
    
  7. Вручную завершите процесс веб-сервера.

    1pkill -f "http.server"
    
  8. Снова запустите скрипт. Он должен опять запустить процесс.

Задания для самостоятельной работы

  1. Скрипт-уборщик: Напишите скрипт cleaner.sh, который находит и завершает все процессы sleep, запущенные текущим пользователем. Скрипт должен выводить PID каждого завершаемого процесса. Подсказка: используйте ps -u $USER и awk или pgrep -u $USER sleep.

  2. Анализ процесса-зомби:

    • Теория: Опишите своими словами, что такое процесс-зомби, почему он возникает и как от него избавиться.
    • Практика (необязательно, продвинутый уровень): Используя язык C, напишите небольшую программу, которая создает зомби-процесс. Для этого родительский процесс должен создать дочерний (fork()) и не вызывать wait() или waitpid() после того, как дочерний процесс завершится (exit()). Скомпилируйте и запустите программу. С помощью ps aux | grep 'Z' убедитесь, что зомби-процесс появился в системе.

Контрольные вопросы

  1. Что такое PID и PPID?
  2. В чем разница между фоновым и приоритетным процессом? Как запустить процесс в фоне?
  3. Какое действие выполняет комбинация клавиш Ctrl+Z?
  4. В чем принципиальное отличие сигналов SIGTERM и SIGKILL?
  5. Что такое “зомби-процесс” и представляет ли он опасность для системы?
  6. Как с помощью одной команды найти PID процесса с именем nginx?
  7. Для чего используется команда jobs?
← Лаб. работа "Язык командного энтерпритатора … Лаб. работа "Управление файловой системой в … →