Введение
При выполнении скрипт часто создаёт временные файлы или запускает фоновые процессы. Если пользователь прерывает скрипт, например нажатием Ctrl+C, эти временные файлы нередко остаются в системе и засоряют её.
Чтобы этого не происходило, скрипту нужно уметь определять момент остановки и выполнять необходимые действия по очистке.
В Linux для перехвата сигналов прерывания и событий завершения используется команда trap. Сигналы — один из способов, с помощью которых операционная система взаимодействует с процессами. Например, нажатие Ctrl+C обычно отправляет процессу сигнал SIGINT, предлагая ему остановиться.
Это позволяет определить процедуру «при выходе», чтобы перед завершением скрипт успел удалить созданные им временные данные.
В этой лабораторной работе вы:
- Создадите скрипт, который генерирует временные файлы.
- Прервете скрипт, чтобы увидеть оставшиеся файлы.
- Настроите trap, чтобы временные файлы автоматически удалялись при завершении.
Создайте долгий процесс
Сначала создайте скрипт, имитирующий длительную задачу. Он создаст временный файл, а затем будет бесконечно приостанавливаться.
Долгие процессы часто используются в задачах администрирования. Скрипт может отслеживать журнал, ожидать ввод, опрашивать сервис или последовательно обрабатывать задания. Чем дольше он работает, тем важнее очистка после прерывания.
Создайте и откройте файл long_process.sh в каталоге проекта:
cd ~/project
nano long_process.sh
Введите следующий код:
#!/bin/bash
## Create a temporary file
touch temp_data.txt
echo "Temporary file 'temp_data.txt' created."
## Fall asleep (Simulate a long job)
echo "Process is running. Press Ctrl+C to stop..."
while true; do
sleep 1
done
Сохраните файл (Ctrl+O, Enter) и выйдите из редактора (Ctrl+X).
Сделайте файл исполняемым:
chmod +x long_process.sh
Проблема: если запустить этот скрипт, а затем остановить его с помощью Ctrl+C, файл temp_data.txt останется на диске. Это считается плохой практикой: при многократных запусках дисковое пространство может заполниться ненужными файлами.
Временные файлы — классический пример, но такая же проблема может возникнуть с файлами блокировок, сокетами, точками монтирования или вспомогательными фоновыми процессами. Очистка нужна для того, чтобы система после завершения работы оставалась в предсказуемом состоянии.
Определите функцию очистки
Чтобы правильно выполнять очистку, рекомендуется определить отдельную функцию, содержащую всю логику очистки.
Отдельная функция делает скрипт более структурированным. Кроме того, одну и ту же логику очистки можно повторно использовать при разных вариантах завершения, не копируя её в нескольких местах.
Снова откройте скрипт:
nano long_process.sh
Добавьте функцию cleanup в начало скрипта:
#!/bin/bash
## Define the cleanup function
cleanup() {
echo ""
echo "Cleaning up temporary files..."
rm -f temp_data.txt
echo "Cleanup complete."
}
## Create a temporary file
touch temp_data.txt
echo "Temporary file 'temp_data.txt' created."
## Simulate a long-running process
echo "Process is running. Press Ctrl+C to stop..."
while true; do
sleep 1
done
Сохраните файл и выйдите из редактора.
На этом этапе функция определена, но скрипт ещё не знает, когда её вызывать.
Настройте trap для перехвата сигналов
Теперь с помощью команды trap сообщите Bash: «Если вы получите сигнал прерывания, например после нажатия Ctrl+C, выполните функцию cleanup».
Это один из наглядных примеров того, как скрипт оболочки реагирует на события операционной системы, а не только на текстовый ввод. Сигнал — это асинхронное сообщение от системы или пользователя процессу, а trap даёт скрипту возможность преднамеренно отреагировать на него.
Откройте скрипт:
nano long_process.sh
Добавьте команду trap после определения функции, но до начала основной логики.
#!/bin/bash
cleanup() {
echo ""
echo "Cleaning up temporary files..."
rm -f temp_data.txt
echo "Cleanup complete."
exit
}
## Register the trap
## SIGINT = Ctrl+C
## EXIT = Any exit (success or failure)
trap cleanup SIGINT EXIT
## The rest of the script...
touch temp_data.txt
echo "Temporary file 'temp_data.txt' created."
echo "Process is running. Press Ctrl+C to stop..."
while true; do
sleep 1
done
Разбор аргументов trap:
cleanup: команда или функция, которую нужно выполнить;SIGINT: сигнал, отправляемый при нажатииCtrl+C;EXIT: псевдосигнал, срабатывающий при любом завершении скрипта.
Использование одновременно SIGINT и EXIT делает очистку надёжнее. SIGINT обрабатывает обычное прерывание с клавиатуры, а EXIT служит более общим механизмом защиты при нормальном завершении и многих ошибках.
Сохраните файл и выйдите из редактора.
Проверьте очистку
Теперь убедитесь, что механизм работает.
Запустите скрипт:
./long_process.sh
Скрипт создаст temp_data.txt и начнёт выполняться.
Прервите его, нажав Ctrl+C.
Вы должны увидеть такой вывод:
^C
Cleaning up temporary files...
Cleanup complete.
Наконец, проверьте, что файл удалён:
ls temp_data.txt
Команда должна вернуть сообщение об ошибке, похожее на это:
ls: cannot access 'temp_data.txt': No such file or directory
Команда trap успешно перехватила сигнал остановки и выполнила код очистки до завершения скрипта.
Это профессиональная привычка при написании скриптов: если скрипт создаёт временное состояние, он должен также определять, как это состояние удалить. trap — один из основных инструментов Bash для такой задачи.
Итоги
В этой лабораторной работе вы научились создавать надёжные скрипты с помощью Trap.
- Сигналы: вы узнали, что
Ctrl+Cотправляет процессу сигналSIGINT. - Trap: вы использовали
trapдля перехвата сигналов и выполнения определённого кода. - Очистка: вы автоматизировали служебные операции, чтобы поддерживать систему в чистом состоянии.
Профессиональные скрипты всегда обрабатывают варианты завершения, чтобы предотвращать повреждение данных и появление оставшихся файлов.



