Кунг-фу стиля Linux: мониторинг дисковой подсистемы
Кунг-фу стиля Linux: глобальный поиск и замена строк с помощью ripgrep
Кунг-фу стиля Linux: упрощение работы с awk
Кунг-фу стиля Linux: наблюдение за файловой системой
Кунг-фу стиля Linux: наблюдение за файлами
Кунг-фу стиля Linux: удобный доступ к справке при работе с bash
Кунг-фу стиля Linux: великая сила make
Кунг-фу стиля Linux: устранение неполадок в работе incron
Кунг-фу стиля Linux: расшаривание терминала в браузере
Кунг-фу стиля Linux: синхронизация настроек
Кунг-фу стиля Linux: бесплатный VPN по SSH
Кунг-фу стиля Linux: превращение веб-приложений в полноценные программы
Кунг-фу стиля Linux: утилита marker и меню для командной строки
Кунг-фу стиля Linux: sudo и поворот двух ключей
Кунг-фу стиля Linux: программное управление окнами
Кунг-фу стиля Linux: организация работы программ после выхода из системы
Кунг-фу стиля Linux: регулярные выражения
Кунг-фу стиля Linux: запуск команд
Кунг-фу стиля Linux: разбираемся с последовательными портами
Кунг-фу стиля Linux: базы данных — это файловые системы нового уровня
Кунг-фу стиля Linux: о повторении кое-каких событий сетевой истории
Кунг-фу стиля Linux: PDF для пингвинов
Поддержка Bash
На удивление легко запустить несколько процессов под Bash. Прежде всего, процессы на обеих сторонах конвейера работают вместе, и это, вероятно, самый распространённый способ сценариев с использованием мультипрограммирования. Другими словами, подумайте, что произойдёт, если вы напишете ls | more
.
В старой системе MSDOS первая программа выполнялась до конца, буферизуя вывод во временный файл. Затем будет запускаться вторая программа, считывающая ввод из того же файла. В Linux и большинстве других современных операционных систем, обе программы будут работать вместе с входом второй программы, соединённым с выходом первой программы.
Это легко, потому что программы синхронизируются по входному и выходному каналу. Однако, так же легко запустить несколько программ независимо друг от друга. Ключ использует "& amp;"
для разделения программ или завершения строки сценария.
Достаточно легко преобразовать сценарий вроде:
find /mnt1/usr -name '*.so' >/tmp/libs1
find /mnt2/usr -name '*.so' > /tmp/libs2
# to
find /mnt1/usr -name '*.so' >/tmp/libs1 &
find /mnt2/usr -name '*.so' > /tmp/libs2 &
В первом случае запросы выполняются по одному и продолжается только после выполнения последнего запроса. Во втором случае обе команды выполняются одновременно, и сценарий будет продолжаться, даже если обе команды всё ещё выполняются.
Проблема
Есть только одна проблема. Хотя вы можете выделить несколько программ для совместной работы, эти программы редко не нуждаются в согласовании друг с другом.
Не то чтобы это было полезно запускать их параллельно, но взгляните на вывод этой команды:
alw@Enterprise:~$ banner hello & banner goodbye
[1] 173
# # ###### # # ####
#### #### #### ##### ##### # # ######
# # # # # # #
# # # # # # # # # # # # #
###### ##### # # # #
# # # # # # # ##### # #####
# # # # # # #
# ### # # # # # # # # # #
# # # # # # #
# # # # # # # # # # # #
# # ###### ###### ###### ####
#### #### #### ##### ##### # ######
[1]+ Done banner hello
Не то, что вы ожидали, правда? В зависимости от вашей системы первая программа может (или не может) получить весь свой вывод за один раз. Перемежение вывода — это не совсем то, что вам нужно.
Control
Есть и другие проблемы. Возможно, вы захотите узнать PID нового процесса. Вы можете использовать bash’s job control. Однако на самом деле вам не нужно заходить так далеко. Команда jobs
покажет вам, что вы исполняете в фоновом режиме из текущей оболочки. Если вы добавите -l
или -p
, вы также можете узнать PID.
Более простой способ узнать PID команды — использовать $!
. Конечно, если вы работаете из командной строки оболочки, она также сообщает вам PID последней команды запуска. Например:
ls / & echo PID=$!
[2] 178
PID=178
Ваш номер PID почти наверняка будет другим.
Что дальше?
Вооружили PID, что с ним делать? Есть две вещи, которые вы найдёте наиболее полезными. Сперва, вы можете использовать wait
, чтобы понять, когда процесс (или процессы) завершены.
Ещё вы можете использовать kill
для отправки сигналов фоновой программе. Это выходит за рамки этой статьи, но вы можете использовать сигналы для создания сложной связи между программами или для вызова поведения по умолчанию, такого как завершение.
Пример
Рассмотрим случай, когда у вас есть куча файлов jpeg, и вы хотите преобразовать их в файлы png для веб-сайта с помощью ImageMagick. Вы можете попробовать этот простой скрипт:
#!/bin/bash
for I in *.jpg
do
convert "$I" "png/$(basename "$I" .jpg).png"
done
echo Copying files now...
ls png
Это упростит работу. Предположительно, в последней строке будет следующая команда копирования файла, например sftp
, однако список каталогов использовался только для примера.
Вместо этого вы можете запустить все преобразования сразу, используя преимущества нескольких процессоров, и дождаться их завершения. Без команды ожидания, имитированная копия запускалась бы до того, как преобразования были бы завершены, если только не было очень мало преобразований, которые нужно было сделать.
#!/bin/bash
for I in *.jpg
do
convert "$I" "png/$(basename "$I" .jpg).png" &
done
wait
echo Copying files now...
ls png
Всё ещё есть проблема
Команда ожидания будет ждать любых подпроцессов, активных в оболочке. Возможно, это не то, что вам нужно, хотя в этом случае это, вероятно, нормально. Давайте поправим это:
#!/bin/bash
PIDs=""
for I in *.jpg
do
convert "$I" "png/$(basename "$I" .jpg).png" &
PIDs+="$! "
done
wait $PIDs
echo Copying files...
ls png
Если вы запустите отсчёт времени с множеством файлов, вы увидите большую разницу. На моём ноутбуке с несколькими картинками прямая версия заняла около 40 секунд. С финальной версией на это ушло чуть больше 10 секунд.
В заключении
Довольно легко забыть, что вы можете легко делать больше, чем одну вещь за раз. Конечно, это тоже открывает целый ряд проблем. Если вам нужно защитить свои программы друг от друга, ознакомьтесь с предыдущей публикацией о критических разделах. Не все думают, что bash
— отличный язык программирования, но он на удивление способен на многое, и, хотя он может быть хорош не для всего, он отлично подходит для некоторых задач.
Кунг-фу стиля Linux: мониторинг дисковой подсистемы
Кунг-фу стиля Linux: глобальный поиск и замена строк с помощью ripgrep
Кунг-фу стиля Linux: упрощение работы с awk
Кунг-фу стиля Linux: наблюдение за файловой системой
Кунг-фу стиля Linux: наблюдение за файлами
Кунг-фу стиля Linux: удобный доступ к справке при работе с bash
Кунг-фу стиля Linux: великая сила make
Кунг-фу стиля Linux: устранение неполадок в работе incron
Кунг-фу стиля Linux: расшаривание терминала в браузере
Кунг-фу стиля Linux: синхронизация настроек
Кунг-фу стиля Linux: бесплатный VPN по SSH
Кунг-фу стиля Linux: превращение веб-приложений в полноценные программы
Кунг-фу стиля Linux: утилита marker и меню для командной строки
Кунг-фу стиля Linux: sudo и поворот двух ключей
Кунг-фу стиля Linux: программное управление окнами
Кунг-фу стиля Linux: организация работы программ после выхода из системы
Кунг-фу стиля Linux: регулярные выражения
Кунг-фу стиля Linux: запуск команд
Кунг-фу стиля Linux: разбираемся с последовательными портами
Кунг-фу стиля Linux: базы данных — это файловые системы нового уровня
Кунг-фу стиля Linux: о повторении кое-каких событий сетевой истории
Кунг-фу стиля Linux: PDF для пингвинов
Автор:
ru_vds