Автор Гілка: Perl & exec  (Прочитано 3686 раз)

Відсутній Smith

  • Новачок
  • *
  • дописів: 37
  • Карма: +0/-0
  • Kharkiv LUG
Perl & exec
« : 2007-01-03 17:00:38 »
 Вiтаю!
 Скажiть будьласка як отримати pid процеса, який я стартую з перловського скрипта, тобто:

 exec "wget http://example.com/foo.rar"

 менi потiбен pid wget'a. Дивився в гуглi, але так и не змiг знайти щось корисне.

 дякую за допомогу!
« Змінено: 2007-01-03 17:01:11 від Smith »

Відсутній Володимир Лісівка

  • Адміністратор ЩОДО
  • Видавець
  • *****
  • дописів: 3820
  • Карма: +11/-0
  • Програміст
Re: Perl & exec
« Відповідей #1 : 2007-01-03 22:29:53 »
Вiтаю!
 Скажiть будьласка як отримати pid процеса, який я стартую з перловського скрипта, тобто:

 exec "wget http://example.com/foo.rar"

 менi потiбен pid wget'a. Дивився в гуглi, але так и не змiг знайти щось корисне.

 дякую за допомогу!

Цитую man perlfunc
Цитата
      exec LIST
       exec PROGRAM LIST
               The "exec" function executes a system command and never returns-- use "system" instead of "exec" if
               you want it to return.  It fails and returns false only if the command does not exist and it is
               executed directly instead of via your system’s command shell (see below).

pid wget-а буде точнісінько такий самий, який був у perl-a перед exec.

$ perl -e 'print "perl pid: $$\n"; exec "/bin/bash", "-c", "echo bash pid: \$\$";'
perl pid: 6352
bash pid: 6352
[Fedora Linux]

zzandy

  • Гість
Re: Perl & exec
« Відповідей #2 : 2007-01-03 22:42:27 »
На скільки я пам'ятаю, exeс усюди так працює - одна програма виконує exec і перетворюється в іншу.

Відсутній nevi

  • Новачок
  • *
  • дописів: 1
  • Карма: +0/-0
  • I Love YaBB 2!
Re: Perl & exec
« Відповідей #3 : 2007-01-20 13:30:11 »
Вiтаю!
 Скажiть будьласка як отримати pid процеса, який я стартую з перловського скрипта, тобто:

 exec "wget http://example.com/foo.rar"

 менi потiбен pid wget'a. Дивився в гуглi, але так и не змiг знайти щось корисне.

 дякую за допомогу!

exec() у Perl'і виконує системний виклик exec (або execvp), який запускає вказану йому аргументом програму у контексті поточного процесу, тобто, у нашому випадку, wget отримає той же pid, що і сам Perl-овий скрипт. Фактично, wget як-би "продовжить" потік виконання скрипта.

Щоб отримати wget з іншим pid'ом, потрібно використовувати system() або fork'ати вручну, приблизно так:

       $child_program = "/path/to/wget";
        if ($pid = fork){
                #батьківський процес - сам скрипт продовжує виконання тут, асинхронно до породженого процесу
                #wget буде мати pid == $pid
                #тут треба ставити хандлер для SIGCHLD, виконувати waitpid, тощо, див. мануал
        }else{
                #породжений процес
                die "fork() failed: $!\n" unless defined $pid; # на всякий випадок; тут $pid == 0 якщо все ок
                exec($child_program) or die "exec($child_program) failed: $!\n";
        }

Різниця між способом з system() і способом з fork() у тому, що з system() - синхронний варіант, скрипт автоматично чекає на завершення породженого нащадка, а з fork()-ом - асинхронний, можна далі щось робити у скрипті, поки виконується wget. Крім того, з system() ми не отримуємо значення pid'у system()-нутого :-) процесу.