LINUX.ORG.RU

wait в for loop'е

 


0

1

Здравствуйте.
Допустим, есть конструкция вида:

perl $HOME/test.pl 1 > $HOME/test1.log &
perl $HOME/test.pl 2 > $HOME/test2.log &
perl $HOME/test.pl 3 > $HOME/test3.log & wait
Как засунуть ее в цикл for? Так?
for n in `seq 1 $COUNT`
do
    perl $HOME/test.pl $n > $HOME/test$n.log &
done
& wait;
Т.е. нужно в цикле for запустить COUNT процессов и дождаться выполнения ВСЕХ их.

★★★★★

Последнее исправление: kovrik (всего исправлений: 1)

Собирай пид во временный файл и проверяй циклом while. Я перелопатил таким образом скрипт синхронизации зеркал арча для параллельного rsync'а.

В твоём случае будет похоже на что-нибудь вида:

#!/bin/sh

TMP_FILE=/tmp/worker.tmp

for n in `seq 1 $COUNT`
do
    perl $HOME/test.pl $n > $HOME/test$n.log &
    echo "p-pid $!">>$TMP_FILE
done

while(true);do
    KEY="1";
    for rpid in `grep 'p-pid' $TMP_FILE|awk '{print \$2}'`;do
        IS_ACTIVE=`ps ax|grep $rpid|grep -v 'grep'|grep 'perl'`;
        if [ "$IS_ACTIVE" != "" ];then
            KEY="0";
        fi
    done
    if [ "$KEY" == "1" ];then
        break;
    fi
sleep 5;

nickleiten ★★★
()
Ответ на: комментарий от nickleiten

Находил в инете похожие решения (правда, немного для другой задачи).
Но, может, можно проще? Мне же по сути не важно запущены ли они СЕЙЧАС. Мне нужно лишь чтобы он дождался выполнения всех.
Или иначе никак?

kovrik ★★★★★
() автор топика
wait [n ...]
Wait for each specified process and return its termination status. Each n may be a process ID or a job specification; if
a job spec is given, all processes in that job's pipeline are waited for.



то есть, стартуешь всё, из $! берешь пид, а потом wait pid1 pid2 pid2

aol ★★★★★
()
Ответ на: комментарий от kovrik

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

Dob
()

А если в for-loop'е создать строковую переменную:

COMMAND=''
for n in `seq 1 $COUNT`
do
    COMMAND=$COMMAND."perl $HOME/test.pl $n > $HOME/test$n.log & "
done
COMMAND=$COMMAND.' wait'
А потом `$COMMAND` ?

kovrik ★★★★★
() автор топика
Ответ на: комментарий от kovrik

пачитай умных книжек, и не говори всякого не подумав! ;)

aol ★★★★★
()
Ответ на: комментарий от Dob

PID --уникальное значение в системе!

а можно по подробней? ссылку на документацию.

оставлю тут пару цитат: http://rus-linux.net/kos.php?name=papers/proc/proc_lin.html

Когда создается новый процесс, ядро присваивает ему идентификатор – PID. Когда выполнение процесса завершилось, идентификатор освобождается и может быть присвоен другому процессу. Присвоение идентификаторов происходит последовательно по возрастанию, начиная с единицы. Идентификатор нового процесса обычно больше, чем идентификатор процесса, созданного ранее. Если идентификатор уже достиг максимально возможного значения, следующий процесс получит минимальный из свободных идентификаторов и цикл продолжается. В системе не может быть двух процессов с одинаковыми идентификаторами и на время жизни процесса его идентификатор не меняется.

http://linux.die.net/man/5/proc

/proc/sys/kernel/pid_max (since Linux 2.5.34) This file specifies the value at which PIDs wrap around (i.e., the value in this file is one greater than the maximum PID). The default value for this file, 32768, results in the same range of PIDs as on earlier kernels. On 32-bit platforms, 32768 is the maximum value for pid_max. On 64-bit systems, pid_max can be set to any value up to 2^22 (PID_MAX_LIMIT, approximately 4 million).

так что ситуация описанная тут: http://www.linux.org.ru/forum/development/9054834?cid=9054914 (комментарий), вполне возможна

anonymous
()
Ответ на: комментарий от kovrik

А чем не устраивает просто wait после запуска в фоне всех ожидаемых процессов?

Elyas ★★★★★
()
Ответ на: комментарий от kovrik

Но, может, можно проще?

Может. Через сопроцессы.

Deleted
()

Чем не угодил wait без аргументов, который ждёт завершения всех фоновых процессов данного шелла? Ровно как это делала исходная версия скрипрта.

См. http://pubs.opengroup.org/onlinepubs/009695399/utilities/wait.html

for n in `seq 1 $COUNT`
do
    perl $HOME/test.pl $n > $HOME/test$n.log &
done
wait
unterwulf
()
Ответ на: комментарий от anonymous

Именно так. Другое дело, что нельзя будет делать wait не child процессов.

Чем не угодил wait без аргументов, который ждёт завершения всех фоновых процессов данного шелла? Ровно как это делала исходная версия скрипрта.

Спасибо! Думал так сделать, но не был уверен в работоспособности такого варианта.

kovrik ★★★★★
() автор топика
Ответ на: комментарий от anonymous

имеется ввиду не может существовать единовременно несколько процессов с идентичным ID!

Dob
()
Ответ на: комментарий от zolden

Что не так с новичками?

PID --уникальное значение в системе!

Единовременно в памяти не может находиться несколько процессов с идентичным ID

Dob
()
Ответ на: комментарий от Dob

Ты искренне заблуждаешься, прочитай ещё раз формулировку вопроса коврика

zolden ★★★★★
()

Можно просто поставить moreutils:

time parallel-moreutils -j3 sh -c 'echo start; sleep $0; echo end' -- 1 2 3

... 0.02s user 0.00s system 0% cpu 3.047 total
anonymous
()

Как засунуть ее в цикл for? Так?

А проверить? просто wait должно хватить.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.