Серфінг по національній мережі я натрапив на цікава стаття (що я привожу сюди текстуально, оскільки це майстерно пояснено), де його автор показує нам, як зробити наші сценарії Bash більш надійними, використовуючи Пастки.
Зробіть ваші сценарії bash більш надійними за допомогою пасток
Уявіть, що у вас є скрипт bash, який запускається щодня кожні шість годин, і що в якийсь момент він виходить з ладу, або той самий сценарій виконується двічі одночасно. Ці дві ситуації є досить дискомфортними, оскільки вимагають виправлення втручання людини або в певний час їх неможливо вирішити, залишаючи систему в непослідовному стані. Рішенням цього, серед іншого, є використання пасток.
Traps - це простий та ефективний спосіб контролювати висновок скриптів bash. Повернемося до тієї самої початкової ситуації, якщо сценарій зупинено вручну, наприклад за допомогою ctrl-c, він переривається, повертаючи вихідний сигнал
INT
а якщо закінчується с
kill
тоді результат буде
TERM
.
Усі можливі коди виходу можна переглянути за допомогою
kill -l
однак найбільш часто використовуються саме
ІНТ, ТЕРМІН, ВИХІД
Якщо сценарій складається, наприклад, із синхронізації файлів із
rsync
Найрозумніше - покладатися на файл блокування, який не дозволяє сценарію запускатися одночасно:
LOCK = "/ var / run / rsync.lock" якщо [! -e $ LOCK]; потім торкніться $ LOCK rsync -avz foo bar rm $ LOCK else echo "rsync вже запущений" fi
На звичайній іспанській мові попередній скрипт перевіряє, чи існує файл блокування, і якщо він не існує, він створює його і пізніше виконує відповідну команду, остаточно видаляючи файл блокування. Якщо файл існує, скрипт просто відправляє користувачеві повідомлення про те, що команда вже запущена.
Однак, коли виникає проблемна ситуація, може статися, що файл блокування не усувається, руйнуючи небажані ефекти. Рішення дуже просте:
LOCK = "/ var / run / rsync.lock" якщо [! -e $ LOCK]; потім захопити "rm -f $ LOCK; вийти" INT TERM EXIT торкнутися $ LOCK rsync -avz foo bar rm $ LOCK trap - INT TERM EXIT ще ехо "rsync вже запущено" fi
Особливість цього рішення полягає в тому, що команда укладена в пастку, так що при отриманні сигналу
ІНТ, ТЕРМІН, ВИХІД
сценарій зупиняється і очищає файл блокування.
Варто сказати, що у сценарії вище може бути ситуація конкуренції між часом перевірки файлу блокування та часом його створення. Можливим рішенням було б використовувати переспрямування та режим noclobber bash, який не перенаправляє на існуючий файл:
LOCK = "/ var / run / rsync.lock" if (set -o noclobber; echo $$> "$ LOCK") 2> / dev / null; потім пастка 'rm -f "$ LOCK"; вихід $? ' INT TERM EXIT rsync -avz foo bar rm -f $ LOCK trap - INT TERM EXIT else echo "rsync вже запущений: $ (cat $ LCK)" fi
Особливістю останнього є те, що він використовується, як я вже говорив, режим noclobber і що файл блокування містить PID процесу, який виконується.
Варто також згадати, що існують і інші рішення, такі як
flock
o
solo
однак у цій публікації я хотів поділитися рішеннями із власними ресурсами bash. З цим ви можете дізнатися трохи більше про пастки чудовий гід.
Чудово! Дякую, що поділились.
Приємна стаття, просто змініть 'echo "rsync вже запущено: $ (cat $ LCK)"' на 'echo "rsync вже запущено: $ (cat $ LOCK)"'
привіт
Дуже цікава стаття, так, сер! Це я зберігаю.
Це дуже корисна команда, яку слід пам’ятати. Я використав його в сценарії, який опублікував у дописі, для видалення деяких файлів, створених сценарієм після його зупинки.
Дуже цікаво, так, сер.