Перейти к содержимому

Как запустить одновременно два процесса linux

  • автор:

Как запустить два процесса одновременно

Здравствуйте! Мне необходимо запустить одновременную трансляцию видео- и аудиопотоков на определенный IP. Подскажите пожалуйста, как запустить два процесса одновременно:

arecord -f cd -D plughw:1,0 | ffmpeg -i — -acodec libmp3lame -ab 8k -ac 1 -re -f rtp rtp://192.168.0.101:8082

avconv -f video4linux2 -s 160×120 -v debug -i /dev/video0 -vcodec mpeg2video -r 25 -pix_fmt yuv420p -me_method epzs -b 2600k -bt 256k -f rtp rtp://192.168.0.101:8083

Каждый из них безостановочно вываливает кучу сообщений и запустить второй процесс одновременно с первым, пока тот не закончится, не получается. Подскажите пожалуйста, как это организовать в скрипте.

MNorin.com

Блог про Linux, Bash и другие информационные технологии

Параллельное выполнение в bash

Параллельное выполнение в bash

В большинстве командных оболочек команды выполняются по умолчанию последовательно. И это, в принципе, нормально. Потому что человек с системой взаимодействует последовательно, обычно нет необходимости несколько команд выполнять параллельно. Bash в этом смысле тоже не исключение. Но при автоматизации возможность параллельного выполнения может быть полезной. Давайте посмотрим, как организовать параллельное выполнение в bash.

Использование фонового режима

Для организации параллельной работы нескольких программ часто используется запуск в фоновом режиме при помощи знака амперсанда — &. Например:

command1 &

Команда будет работать в фоне, при этом из текущей оболочки можно выполнять команды. Таким образом уже можно распараллелить какие-то действия. Можно запустить сразу несколько команд таким образом и дождаться, пока они все отработают. Для ожидания запущенных дочерних процессов используется команда wait. Эта команда без параметров ожидает окончания работы всех дочерних процессов, соответственно, для ожидания окончания 5 процессов понадобится выполнить команду всего 1 раз. В принципе, это легко реализуется через цикл. Например, так:

for i in do # запуск одного фонового процесса sleep 10 && echo $i & done # ожидание окончания работы wait echo Finished

И результат работы этого скрипта:

$ ./wait5.sh 1 5 4 2 3 Finished

Как видите, с виду одинаковые команды завершились не в том порядке, в котором мы их запустили. Давайте посмотрим теперь общее время выполнения скрипта.

$ time ./wait5.sh 4 5 2 3 1 Finished real 0m10.029s user 0m0.000s sys 0m0.008s

Общее время работы скрипта чуть больше 10 секунд, что доказывает, что наши команды выполнились параллельно, а увеличение времени выполнения говорит о том, что они были запущены не в одно и то же время, были небольшие таймауты между запусками. Но они были очень маленькими, поэтому такой запуск пяти процессов занимает практически такое же время, как запуск одного.

Использование пайпа

При использовании пайпов, которые перенаправляют вывод одной программы на вход другой, процессы выполняются параллельно. Отсюда вытекает еще один способ параллельного выполнения нескольких команд — перенаправить между ними какие-то данные с помощью пайпа. Например:

program1 | program2 | program3

Тут важно помнить вот что: если вам не нужно передавать реально какие-то данные между программами, то надо предварительно убедиться, что входные данные эти программы получат в виде опций командной строки и не будут использовать те данные, которые были переданы им с помощью пайпа. Хотя здесь, в принципе, возможен такой вариант:

command1 --option > dev/null | command2 param1 param2 > /dev/null | command3

Этот вариант до использования в скриптах, естественно, нужно обязательно проверить в ручном режиме и посмотреть в страницах руководств используемых программ (если там есть такая информация), что имеет больший приоритет — опции командной строки или стандартный поток ввода, потому что некоторые программы могут игнорировать командную строку, если данные передаются через стандартный поток ввода.

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

Давайте рассмотрим такую практическую задачу — запустить 100 процессов параллельно, но так, чтобы работало одновременно не более 10 процессов. В общем, достаточно простая задача. Предположим, что все процессы работают произвольное количество времени. Пусть запуск одной задачи будет выглядеть как запуск команды sleep со случайным параметром от 0 до 29. Тогда скрипт будет выглядеть следующим образом:

#!/bin/bash RANDOM=10 JOBS_COUNTER=0 MAX_CHILDREN=10 MY_PID=$$ for i in do echo Cycle counter: $i JOBS_COUNTER=$((`ps ax -Ao ppid | grep $MY_PID | wc -l`)) while [ $JOBS_COUNTER -ge $MAX_CHILDREN ] do JOBS_COUNTER=$((`ps ax -Ao ppid | grep $MY_PID | wc -l`)) echo Jobs counter: $JOBS_COUNTER sleep 1 done sleep $(($RANDOM % 30)) & done echo Finishing children . # wait for children here while [ $JOBS_COUNTER -gt 1 ] do JOBS_COUNTER=$((`ps ax -Ao ppid | grep $MY_PID | wc -l`)) echo Jobs counter: $JOBS_COUNTER sleep 1 done echo Done

Смысл этого скрипта в целом такой: ограничиваем максимально число дочерних фоновых процессов так, чтобы их одновременно было не более 10. Как только один процесс заканчивает свою работу, запускаем следующий. И так далее, пока не выполним 100 фоновых задач. Для порядка отслеживаем в скрипте окончание работы дочерних процессов после запуска последних, только потом заканчиваем работу самого скрипта.

Таким простым способом можно ограничить количество одновременно запущенных фоновых задач в скрипте и при этом отслеживать, сколько из них в данный момент работают. Чтобы было более понятно, запустите скрипт и увидите, когда запускается следующие итерации цикла, и когда изменяется количество дочерних процессов.

Похожие посты:

  • Различие скобок в bash
  • Bash. Как обойтись без goto
  • Как вернуть фоновую программу в терминал
  • Несколько способов ускорить bash-скрипты
  • Скрипт, который работает и в Linux, и в Windows
  • Как информацию программы top перенаправить на обработку другой программе?
  • Фейковый SMTP-сервер на bash
  • Анализ состава локальной сети при помощи команды ping
  • logrotate: настройка ротации логов
  • Установка программ в Debian при помощи tasksel
  • Нажмите здесь, чтобы поделиться контентом на Facebook. (Открывается в новом окне)
  • Нажмите, чтобы поделиться на LinkedIn (Открывается в новом окне)
  • Нажмите, чтобы поделиться на Reddit (Открывается в новом окне)
  • Нажмите, чтобы поделиться на Twitter (Открывается в новом окне)
  • Нажмите, чтобы поделиться записями на Tumblr (Открывается в новом окне)
  • Нажмите, чтобы поделиться записями на Pinterest (Открывается в новом окне)
  • Нажмите, чтобы поделиться записями на Pocket (Открывается в новом окне)
  • Нажмите, чтобы поделиться в Telegram (Открывается в новом окне)
  • Нажмите, чтобы поделиться в WhatsApp (Открывается в новом окне)
  • Нажмите, чтобы поделиться в Skype (Открывается в новом окне)

Как запустить два процесса одновременно?

Задача про Producer&Consumer. Цель задачи в том, что есть два процесса и один общий буфер информации. Один процесс заполняет буфер, а другой берет оттуда информацию. Как я понял нужно использовать fork(). Если буфер пуст, то взять инфу нельзя, а если полон, то нельзя заполнять.
Я разобрался с fork(), при вызову этого метода, мы дублируем весь процесс после него. Один выполняется отцом, а другой сыном. Сейчас, когда я пишу, то всегда сначала выполняется отец, а потом сын. Как сделать что-бы они работали одновременно? Ну, или чередовались хаотично а не 1010101010 (1 — отец, 0 — сын)

  • Вопрос задан более трёх лет назад
  • 1090 просмотров

Комментировать
Решения вопроса 0
Ответы на вопрос 3

Lobotomist

Igor Deyashkin @Lobotomist
Software Developer

Такое ощущение, что вы пытаетесь придумать свой конвейер (pipe). Возможно, я вас не так понял, но думаю, что проще всего, чтобы у вас было две программы:
1. Producer, генерит какие-то данные в stdout
2. Consumer, принимает данные из stdin
И запускаете их таким макаром:

Ответ написан более трёх лет назад
Нравится 1 9 комментариев
annozzer @annozzer Автор вопроса

Не совсем, загвоздка в том, что Consumer и Producer должны быть в одной программе, и как я понял в конвеере мы получаем output в виде 1010101010 или 11111100000 (возможно я не прав).

Lobotomist

Igor Deyashkin @Lobotomist

Думаю, вам стоит добавить немного конкретики в ваш вопрос — что именно делает ваша программа. Потому что пока я плохо представляю зачем вам может понадобиться передавать данные между экземплярами одной программы.

annozzer @annozzer Автор вопроса

Igor Deyashkin: Представим что есть, за которым сидят два человека, один повар, другой клиент. Посреди стола стоит тарелка(представим что в тарелку вмещается только 5 стейков) куда повар кладет стейки, а клиент их съедает. приготовил-съел-приготовил-съел это 1010. Мне нужно сделать так, что-бы выходной output получился наподобие 111010011000(дальше он есть не может так как тарелка пуста поэтому процесс клиент должен уснуть а повар работать, и наоборот если тарелка полная.) Проблема заключается в том, что я могу сделать так, что-бы тарелка заполнялась и пустела по определенной закономерности, например приготовил 2 стейка, съел один и так далее пока тарелка не заполнится, и наоборот после заполнения. Но мне нужно сделать, что-бы они ели и готовили с разной скорость которая постоянно меняется. Например повар приготовил 4 стейка, клиент 3, приготовил еще 3, клиент съел все 4, а потом повар приготовил 1 стейк, он и его съел, а потом сразу 5, но почему-то клиент съел только 2, а потом повар приготовил еще один.

annozzer @annozzer Автор вопроса

Lobotomist

Igor Deyashkin @Lobotomist

По-моему, конвейером это решается. Я имел ввиду не аналогию — а описать, что вы пытаетесь в своей программе сделать. Что это за поток данных? Почему вам это нужно, чтобы одна и та же программа была и поваром и клиентом? Чем не подходит вариант сделать две программы — одну повора, другую клиента?

Выполнение сразу нескольких команд в командной строке

В командной строке Linux можно объединять сразу несколько команд в одну строку (в один запуск). Например, вам нужно выполнить сначала одну команду, за ней вторую и так далее. Но вы хотите сразу вбить в командной строке одну инструкцию, которая все сделает. Для этого можно воспользоваться служебными символами.

Выполнение команд последовательно

Например, мы хотим выполнить сначала одну команду. Затем, когда она отработает (вернет управление в командную строку), нам нужно запустить вторую команду. Для этого служит символ точка с запятой ;. Таким образом, если вы выполните в терминале:

mycommand1; mycommand2; mycommand3

то сначала запустится первая команда mycommand1, а когда управление вернется в терминал, то запустится вторая и так далее.

Для теста попробуйте выполнить (в Ubuntu):

gnome-terminal; gedit

Это называется последовательным выполнением команд. Вне зависимости от того, как выполнилась предыдущая команда, вторая команда должна будет запуститься. Можно выполнять команды в зависимости от того, как отработала предыдущая для этого служат символы && и ||.

Зависимое выполнение команд

Символы && и || означают не что иное, как логическое И и ИЛИ. Поэтому когда мы пишем:

mycommand1 && mycommand2 && mycommand3

то это означает, что команда mycommand2 будет выполнена только в том случае, если команда mycommand1 была выполнена успешно. Каждая следующая команда выполняется только при успешном выполнении предыдущей.

Если выполнить конструкцию:

mycommand1 || mycommand2 || mycommand3

то команда mycommand2 будет выполнена только, если mycommand1 вернула ошибку. Каждая следующая команда запускается только если предыдущая вернула ошибку.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *