[Настройка Linux, Разработка под Linux] Многозадачность в shell скриптах
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Иногда, при написании скрипта на shell хочется выполнять какие-то действия в несколько потоков. Подходящими ситуациями могут быть, например, сжатие большохо количества больших файлов на многопроцессорном хосте и передача файлов по широкому каналу, на котором ограничена скорость индивидуального соединения.
Все примеры написаны на bash, но (с минимальными изменениями) будут работать в ksh. В csh тоже есть средстава управления фоновыми процессами, поэтому подобных подход тоже может быть использован.
JOB CONTROL
Так называется секция в man bash где описаны подробности, на случай если вы любите читать man. Мы используем следующие простые возможности:
command & — запускает команду в фоне
jobs — печатает список фоновых команд
Простой пример, не выполняющий никаких полезных действий. Из файла test.txt читаются числа, и параллельно запускается 3 процесса, которые спят соответствующее количество секунд. Каждые три секунды проверяется число запущенных процессов, и если их меньше трех, запускается новый. Запуск фонового процесса вынесен в отдельную функцию mytask, но можно запускть его непосредственно в цикле.
test.sh
SPL
#!/bin/bash
NJOBS=3 ; export NJOBS
function mytask () {
echo sleeping for $1
sleep $1
}
for i in $( cat test.txt )
do
while [ $(jobs | wc -l ) -ge $NJOBS ]
do
sleep 3
done
echo executing task for $i
mytask $i &
done
echo waiting for $( jobs | wc -l ) jobs to complete
wait
Входные данные:
test.txt
SPL
60
50
30
21
12
13
Обратите внимание на wait после цикла, команда ждет завершения исполняющихся в фоне процессов. Без нее скрипт будет завершен сразу после завершения цикла и все фоновые процессы будут прерваны. Возможно именно этот wait упоминается в известном меме «oh, wait!!!».
Завершение фоновых процессов.
Если прервать скрипт по Ctrl-C, он будет убит со всеми фоновыми процессами, т.к. все процессы работающие в терминале получают сигналы от клавиатуры (например, SIGINT). Если же скрипт убить из другого терминала командой kill, то фоновые процессы останутся работать до завершения и об этом нужно помнить.
Заголовок спойлера
SPL
user@somehost ~/tmp2 $ ps -ef | grep -E «test|sleep»
user 1363 775 0 12:31 pts/5 00:00:00 ./test.sh
user 1368 1363 0 12:31 pts/5 00:00:00 ./test.sh
user 1370 1368 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 60
user 1373 1363 0 12:31 pts/5 00:00:00 ./test.sh
user 1375 1373 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 50
user 1378 1363 0 12:31 pts/5 00:00:00 ./test.sh
user 1382 1378 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 30
user 1387 1363 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 3
user 1389 556 0 12:31 pts/2 00:00:00 grep --colour=auto -E test|sleep
user@somehost ~/tmp2 $ kill 1363
user@somehost ~/tmp2 $ ps -ef | grep -E «test|sleep»
user 1368 1 0 12:31 pts/5 00:00:00 ./test.sh
user 1370 1368 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 60
user 1373 1 0 12:31 pts/5 00:00:00 ./test.sh
user 1375 1373 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 50
user 1378 1 0 12:31 pts/5 00:00:00 ./test.sh
user 1382 1378 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 30
user 1399 556 0 12:32 pts/2 00:00:00 grep --colour=auto -E test|sleep
Эту ситуацию можно обработать, перехватывая нужные сигналы, для чего в начале скрипта добавим обработчик:
trap
SPL
function pids_recursive() {
cpids=`pgrep -P $1|xargs`
echo $cpids
for cpid in $cpids;
do
pids_recursive $cpid
done
}
function kill_me () {
kill -9 $( pids_recursive $$ | xargs )
exit 1
}
#не обязательно
#trap 'echo trap SIGINT; kill_me ' SIGINT
trap 'echo trap SIGTERM; kill_me' SIGTERM
kill -L выводит список существующих сигналов, при необходимости можно добавить обработчики для нужных.
===========
Источник:
habr.com
===========
Похожие новости:
- [Настройка Linux, Системное администрирование] Файловый сервер на Samba, видимый отовсюду
- [Программирование, .NET, C#, Разработка под Linux, Разработка под Windows] Генерация типизированных ссылок на элементы управления Avalonia с атрибутом x:Name с помощью C# SourceGenerator
- [*nix] Использование локального .bashrc через ssh и консолидация истории выполнения команд
- [Python, Разработка под Linux] Разработка механизма распараллеливания кода на языке python с использованием docker-контейнеров
- [Настройка Linux, Разработка на Raspberry Pi, DIY или Сделай сам] Как сделать из планшетного USB-сканера сетевой с памятью, используя Raspberry Pi. Видеолекция с демонстрацией
- [Обработка изображений, Разработка под Linux, Софт] GIMP исполнилось 25 лет
- [Информационная безопасность, Open source, Разработка под Linux, Процессоры] Новые патчи Linux защищают процессоры Intel от последних уязвимостей, так что Hyper-Threading можно не отключать
- [Разработка мобильных приложений, Разработка под Android, Разработка под MacOS, Разработка под Linux, Разработка под Windows] Разработка мобильных приложений на Python. Создание анимаций в Kivy. Part 2
- [Open source, Google Chrome, Разработка под Linux] Ubuntu Web Remix — альтернатива Chrome OS c браузером Firefox вместо Google Chrome
- [Разработка под Linux, Смартфоны] Началось массовое производство смартфона Librem 5
Теги для поиска: #_nastrojka_linux (Настройка Linux), #_razrabotka_pod_linux (Разработка под Linux), #_bash, #_mnogopotochnost_na_shell (многопоточность на shell), #_ksh, #_csh, #_nastrojka_linux (
Настройка Linux
), #_razrabotka_pod_linux (
Разработка под Linux
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 09:01
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Иногда, при написании скрипта на shell хочется выполнять какие-то действия в несколько потоков. Подходящими ситуациями могут быть, например, сжатие большохо количества больших файлов на многопроцессорном хосте и передача файлов по широкому каналу, на котором ограничена скорость индивидуального соединения. Все примеры написаны на bash, но (с минимальными изменениями) будут работать в ksh. В csh тоже есть средстава управления фоновыми процессами, поэтому подобных подход тоже может быть использован. JOB CONTROL Так называется секция в man bash где описаны подробности, на случай если вы любите читать man. Мы используем следующие простые возможности: command & — запускает команду в фоне jobs — печатает список фоновых команд Простой пример, не выполняющий никаких полезных действий. Из файла test.txt читаются числа, и параллельно запускается 3 процесса, которые спят соответствующее количество секунд. Каждые три секунды проверяется число запущенных процессов, и если их меньше трех, запускается новый. Запуск фонового процесса вынесен в отдельную функцию mytask, но можно запускть его непосредственно в цикле. test.shSPL#!/bin/bash
NJOBS=3 ; export NJOBS function mytask () { echo sleeping for $1 sleep $1 } for i in $( cat test.txt ) do while [ $(jobs | wc -l ) -ge $NJOBS ] do sleep 3 done echo executing task for $i mytask $i & done echo waiting for $( jobs | wc -l ) jobs to complete wait Входные данные: test.txtSPL60
50 30 21 12 13 Обратите внимание на wait после цикла, команда ждет завершения исполняющихся в фоне процессов. Без нее скрипт будет завершен сразу после завершения цикла и все фоновые процессы будут прерваны. Возможно именно этот wait упоминается в известном меме «oh, wait!!!». Завершение фоновых процессов. Если прервать скрипт по Ctrl-C, он будет убит со всеми фоновыми процессами, т.к. все процессы работающие в терминале получают сигналы от клавиатуры (например, SIGINT). Если же скрипт убить из другого терминала командой kill, то фоновые процессы останутся работать до завершения и об этом нужно помнить. Заголовок спойлераSPLuser@somehost ~/tmp2 $ ps -ef | grep -E «test|sleep»
user 1363 775 0 12:31 pts/5 00:00:00 ./test.sh user 1368 1363 0 12:31 pts/5 00:00:00 ./test.sh user 1370 1368 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 60 user 1373 1363 0 12:31 pts/5 00:00:00 ./test.sh user 1375 1373 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 50 user 1378 1363 0 12:31 pts/5 00:00:00 ./test.sh user 1382 1378 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 30 user 1387 1363 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 3 user 1389 556 0 12:31 pts/2 00:00:00 grep --colour=auto -E test|sleep user@somehost ~/tmp2 $ kill 1363 user@somehost ~/tmp2 $ ps -ef | grep -E «test|sleep» user 1368 1 0 12:31 pts/5 00:00:00 ./test.sh user 1370 1368 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 60 user 1373 1 0 12:31 pts/5 00:00:00 ./test.sh user 1375 1373 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 50 user 1378 1 0 12:31 pts/5 00:00:00 ./test.sh user 1382 1378 0 12:31 pts/5 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 30 user 1399 556 0 12:32 pts/2 00:00:00 grep --colour=auto -E test|sleep Эту ситуацию можно обработать, перехватывая нужные сигналы, для чего в начале скрипта добавим обработчик: trapSPLfunction pids_recursive() {
cpids=`pgrep -P $1|xargs` echo $cpids for cpid in $cpids; do pids_recursive $cpid done } function kill_me () { kill -9 $( pids_recursive $$ | xargs ) exit 1 } #не обязательно #trap 'echo trap SIGINT; kill_me ' SIGINT trap 'echo trap SIGTERM; kill_me' SIGTERM kill -L выводит список существующих сигналов, при необходимости можно добавить обработчики для нужных. =========== Источник: habr.com =========== Похожие новости:
Настройка Linux ), #_razrabotka_pod_linux ( Разработка под Linux ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 09:01
Часовой пояс: UTC + 5