[perl] Паралельное выполнение команд?

migel

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

artimon

Э. fork?

migel

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

Barbie29

можно какннить так например:

#!/usr/bin/perl -w
use strict;
use IO::Handle;
$SIG{INT} = sub { die "дочерний процесс $$ убит по KILLINT\n" };
die "can't fork: $!" unless defined (my $kid = fork;
if ($kid) {
open F, "tail -f /var/log/httpd/access_log|";
F->autoflush(1);
print "process $$ write\n", $_ while <F>;
close F;
waitpid($kid,0);
} else {
open F, "tail -f /var/log/httpd/error_log|";
F->autoflush(1);
print "process $$ write\n", $_ while <F>;
close F;
exit;
}

migel

не понятно как вообще функционирует потомок, объясни, плиз!

#!/usr/bin/perl -w
use strict; - это зачем?
use IO::Handle; - а это нужно?
$SIG{INT} = sub { die "дочерний процесс $$ убит по KILLINT\n" };
- не понятно вообще :(
die "can't fork: $!" unless defined (my $kid = fork;
if ($kid) {
...то что должен делать потомок...
например $result=`dir`
waitpid($kid,0); - это нужно?
} else {
...то что делает родитель..
например, Process($result)
exit;
}

я правильно понял смысл программы?

Barbie29

предыдущий пример не верен, он оставляет в процессах tail -f помимо собственных чайлдов, вот вроде как верно:

#!/usr/bin/perl -w
use strict;
use IO::Handle;
use IPC::Open2;
$SIG{INT} = sub { die "дочерний процесс $$ убит по KILLINT\n" };
die "can't fork: $!" unless defined (my $kid = fork;
if ($kid) {
my $pid = open2(\*RDRFH, \*WTRFH, 'tail -f /var/log/httpd/access_log');
RDRFH->autoflush(1);
print "process $$ write\n", $_ while <RDRFH>;
kill -9 => $pid;
waitpid($kid,0);
} else {
my $pid = open2(\*RDRFH, \*WTRFH, 'tail -f /var/log/httpd/error_log');
RDRFH->autoflush(1);
print "process $$ write\n", $_ while <RDRFH>;
kill -9 => $pid;
exit;
}

Barbie29

use strict; - это зачем?
это чтобы следить за поведением переменных, если код болшой, чтобы дважды не юзать переменную .и потом не запутаться. подробнее смотри в perldoc -f strict
use IO::Handle; - а это нужно?
Угу, оно отключает буферизацию дескриптора потока F функцией autoflush (perldoc -f autoflush)
$SIG{INT} = sub { die "дочерний процесс $$ убит по KILLINT\n" };
- не понятно вообще
Это переопределение сигнала ctrl+c, сколько бы ты не
наплодил потомков в fork'ами, по закрытию самого первого процесса, который плодит все остальные, будет происходить убийство всех остальных.
waitpid($kid,0); - это нужно?
да, обязтаельно, если у тебя долгоиграющий процесс, оно его прибьет по нажатию ctrl+c . perldoc -f waitpid
ты мне скажи, че те надо, я те сделаю, так проще будет

Barbie29

не понятно как вообще функционирует потомок, объясни, плиз!
у тебя прога разделяется на две проги, одна в условии если её пид, другая в условии иначе.
Если у тебя два вечноиграющих процесса с выводом на консоль, то тебе надо делать вроде того, что в исправленном примере. если тебе просто надо одновременно запустить две команды и получить вывод обоих, то пиши просто qx[date & df] или $x=`date & df` (правда как разделить вывод одного от другого - это к bash-отцам, я не умею). Если тебе просто надо одновременно исполнить две команды, работа которых вывести данные и завершться, то всех этих наворотов с буферизациями и процей туфтой не надо. Код будет так выглядеть:

[observ vilf]$ cat xxxx.pl
#!/usr/bin/perl -w
use strict;
$SIG{INT} = sub { die "дочерний процесс $$ убит по KILLINT\n" };
die "can't fork: $!" unless defined (my $kid = fork;
if ($kid) {
print "process ",$$," read this:\n",qx[date];
waitpid($kid,0);
} else {
print "process ",$$," read this:\n",qx[df];
exit;
}
[observ vilf]$ perl xxxx.pl
process 16378 read this:
Пнд Сен 5 17:40:09 GMT 2005
process 16379 read this:
Файловая система 1K-блоков Исп Доступно Исп% смонтирована на
/dev/hda1 2086024 1787348 192652 91% /
/dev/hda2 68902964 46587732 20215136 70% /mnt/data
/dev/hdc2 151803428 126629132 17463096 88% /mnt/sata
/dev/ram0 5807 831 4676 16% /mnt/ramdisk
//izabella/tmp 1929056 918112 1010944 48% /iz_tmp
[observ vilf]$

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

migel

мне нужно одновременно запустить выполняться несколько системных команд (дочерних процессов, видимо которые должны передать результат выполнения родителю, а он их обработает и выведет на экран.
`date & df` не подойдет, т.к. я под винду пишу
насколько я понял, твоя программа как раз и делает то, что мне нужно.
спасибо, сейчас буду пытаться подправить ее под уже написанное.

Barbie29

ху, тогда юзай форк с самыми простейшими вещами (тут в основном про юниксспецифику написано хотя я вообще мало представляю. работает ли под виндой форк и как работает... я с винды слез года 4 назад...

migel

да вроде работает..
по крайне мере у меня есть прога с fork (в которой правда нифига непонятно но она прекрасно работает.
Оставить комментарий
Имя или ник:
Комментарий: