Назад | Перейти на главную страницу

как запустить несколько сценариев оболочки параллельно

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

Так, cat.sh, dog.sh, и foo.sh каждый запускает сценарий PHP. Каждый сценарий оболочки запускает приложение PHP в цикле, поэтому оно запускается вечно, засыпая после каждого запуска.

Пытаюсь понять, как одновременно запускать скрипты параллельно. См. Вывод приложений PHP в окне stdout / term.

Я подумал, что может сработать что-то вроде следующего:

foo.sh > &2
dog.sh > &2
cat.sh > &2

В сценарии оболочки этого было бы достаточно, но он не работает.

foo.sh, runs foo.php once, and it runs correctly
dog.sh, runs dog.php in a never ending loop. it runs as expected
cat.sh, runs cat.php in a never ending loop
 *** this never runs!!!

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

У кого-нибудь есть идеи, как я могу заставить эти скрипты работать параллельно?

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

Попробуй это:

foo.sh >foo.out 2>foo.err &
dog.sh >dog.out 2>dog.err &
cat.sh >cat.out 2>cat.err &

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

В качестве альтернативы пусть каждый из ваших сценариев оболочки запускает связанный .php сценарий, который вы, по-видимому, вызываете, с той же семантикой, что и выше. В этом сценарии ваш foo.sh может содержать:

#!/bin/bash
php foo.php >foo.out 2>foo.err &

Наконец, если вам нужна настоящая параллельная работа, проверьте GNU Parallel.

Примечание: если вы действительно хотите, чтобы вывод выводился на экран / терминал, вы можете отключить перенаправление вывода:

foo.sh &

Однако помните, что одновременное выполнение нескольких команд может вызвать запутанный вывод (теперь вы можете знать, какой вывод или какие ошибки были вызваны какой командой), и если вы выйдете из системы, вывод некуда будет уходить.

Это можно сделать с помощью параллельной команды.

Красивые примеры: параллельно

[me@neo]<bash><~> 19
05:51 Tue Mar 05 > man -f parallel
parallel (1) - run programs in parallel

-

parallel -j 3 -- "sh foo.sh" "sh dog.sh" "sh cat.sh"

Это запустит одновременно 3 скрипта.

parallel sh -c "echo hi; sleep 2; echo bye" -- 1 2 3

По умолчанию запускается столько процессов, выполняемых одной командой, в зависимости от количества процессоров.

parallel -j 3 sh -c "echo hi; sleep 2; echo bye" -- 1 2 3

Это заставит выполнять 3 процесса одновременно, даже если у вас всего 2 процессора.

Пример:

[me@neo]<bash><~> 31 
06:09 Tue Mar 05 > parallel -j 10 sh -c "echo Hello World; sleep 3; echo Good morning" -- $(seq 1 10)

Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Good morning
Good morning
Good morning
Good morning
Good morning
Good morning
Good morning
Good morning
Good morning
Good morning

У Криса есть хорошая общая идея для большинства сценариев: заканчивайте каждую команду с & и они уйдут на задний план. Тем не менее, вот кое-что, что я храню для некоторых более сложных задач. Позвольте представить вам мой удобный скрипт панели инструментов, parallel-exec.pl

    #!/usr/bin/perl
    use threads;
    use Thread::Queue;

    my @workers;
    my $num_threads = shift;
    my $dbname = shift;
    my $queue = new Thread::Queue;

    for (0..$num_threads-1) {
            $workers[$_] = new threads(\&worker);
                    print "TEST!\n";
    }

    while ($_ = shift @ARGV) {
            $queue->enqueue($_);
    }

    sub worker() {
            while ($file = $queue->dequeue) {
                    system ('./parser.pl', $dbname, $file);
            }
    }

    for (0..$num_threads-1) { $queue->enqueue(undef); }
    for (0..$num_threads-1) { $workers[$_]->join; }

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

или .. вы можете сделать это так:

threads=20
tempfifo=$PMS_HOME/$$.fifo

trap "exec 1000>&-;exec 1000<&-;exit 0" 2
mkfifo $tempfifo
exec 1000<>$tempfifo
rm -rf $tempfifo

for ((i=1; i<=$threads; i++))
do
    echo >&1000
done

for ((j=1; j<=1000; j++))
do
    read -u1000
    {
        echo $j
        echo >&1000
    } &
done

wait
echo "done!!!!!!!!!!"

каждый раз он запускает 20 потоков параллельно.

надеюсь, это поможет :)

Попробуй это:

./Cat.sh &
./Dog.sh & 
./foo.sh &

Они будут работать в фоновом режиме.

Для большего контроля над процессами вставьте их в скрипт Python с помощью модуля многопроцессорности.

import multiprocessing as mp 
import os
def Run(script_name):
       os.system('./'+script _name+'.sh)
Pool=[]
For s in [your script list]:
     p=mp.Process(target =Run ,args=(s,))
     Pool.append(p)
For p in P:
     p.start()
Fort p in P:
     p.join()