読者です 読者をやめる 読者になる 読者になる

破棄されたブログ

このブログは破棄されました。

無題

のどが痛い。

php からプロセスを実行する

php からプロセスを実行する関数には popen() と exec() がある。 (いや、他にもいろいろあるけど割愛) で、違いがよくわからないから調べてみた。

Cygwin だからいろいろとアレ。

大雑把に言うと、同期か非同期かの違いみたい。

php から実行したするのはこのシェルスクリプト

echo `date +'%Y-%m-%d %H:%I:%S'`' proc start'
echo 'PID: '"${$}"
sleep 10
echo `date +'%Y-%m-%d %H:%I:%S'`' proc end'

exec() 関数の場合

実行されるプロセスの終了を待ってから、次の処理が実行される。(同期)

exec という名前だけど、UNIX コマンドの exec とは違い新たにプロセスを生成する。

$ php proc.php &
[1] 7348

$ while true ; do date +'%Y-%m-%d %H:%I:%S'; ps; echo ''; sleep 2; done
2012-10-12 10:10:00
      PID  TTY      STIME COMMAND
      276 pty1    09:56:00 /usr/bin/bash
     7348 pty1    10:09:58 /cygdrive/c/Program Files/PHP/php

php script start 2012-10-12 10:10:02
2012-10-12 10:10:04
      PID  TTY      STIME COMMAND
      276 pty1    09:56:00 /usr/bin/bash
     5892 pty1    10:10:02 /usr/bin/sleep
     7348 pty1    10:09:58 /cygdrive/c/Program Files/PHP/php
     7204 pty1    10:10:02 /usr/bin/sh

(中略)

2012-10-12 10:10:02 proc start
PID: 7204
2012-10-12 10:10:12 proc end
php script end 2012-10-12 10:10:12

2012-10-12 10:10:12
      PID  TTY      STIME COMMAND
      276 pty1    09:56:00 /usr/bin/bash
     7348 pty1    10:09:58 /cygdrive/c/Program Files/PHP/php

[1]+  終了                    php proc.php
2012-10-12 10:10:19
      PID  TTY      STIME COMMAND
      276 pty1    09:56:00 /usr/bin/bash

popen() 関数の場合

実行されるプロセスの終了を待たずに、次の処理が実行される。(非同期)

popen() で実行したプロセスの終了を待ってやらないとパイプでの接続先プロセスが失われるので、 実行されたプロセスでエラーが発生することがある。

なんで、popen() で取得したハンドラが feof() で FALSE を返してる間は php スクリプトを終了しないとか、 pclose() できちんとプロセスを終了させてやったほうがよさそう。(もしくは、そうすべき。)

C 言語での UNIX プログラミングの経験がないため詳しいことはわからないけど、 パイプでの接続先プロセスは php そのものではないみたい。

実行元の php を kill してやれば popen() で実行されたプロセスも kill される。

popen() で実行されたプロセスが生きていれば、php スクリプト自体が終了したあとも php プロセス自体も生き続ける。

$ ps -s
    PID  TTY        STIME COMMAND
    276 pty1     09:56:00 /usr/bin/bash

$ php proc.php &
[1] 6932

$ while true ; do date +'%Y-%m-%d %H:%I:%S'; ps -s; echo ''; sleep 2; done
2012-10-12 10:10:53
    PID  TTY        STIME COMMAND
    276 pty1     09:56:00 /usr/bin/bash
   6932 pty1     10:25:52 /cygdrive/c/Program Files/PHP/php

php script start 2012-10-12 10:25:54
php script end 2012-10-12 10:25:54
tee: 標準出力: Illegal seek
2012-10-12 10:10:56
    PID  TTY        STIME COMMAND
   3220 pty1     10:25:55 /usr/bin/sh
    276 pty1     09:56:00 /usr/bin/bash
   6932 pty1     10:25:52 /cygdrive/c/Program Files/PHP/php
   7636 pty1     10:25:55 /usr/bin/sleep
   6668 pty1     10:25:55 /usr/bin/tee

(中略)

2012-10-12 10:10:04
    PID  TTY        STIME COMMAND
   3220 pty1     10:25:55 /usr/bin/sh
    276 pty1     09:56:00 /usr/bin/bash
   6932 pty1     10:25:52 /cygdrive/c/Program Files/PHP/php
   7636 pty1     10:25:55 /usr/bin/sleep
   6668 pty1     10:25:55 /usr/bin/tee

tee: 書き込みエラー

2012-10-12 10:10:08
    PID  TTY        STIME COMMAND
    276 pty1     09:56:00 /usr/bin/bash
   6932 pty1     10:25:52 /cygdrive/c/Program Files/PHP/php

[1]+  終了                    php proc.php

2012-10-12 10:10:10
    PID  TTY        STIME COMMAND
    924 pty0     09:32:51 /usr/bin/bash

$ ll
合計 3
-rw-r--r-- 1 user group  70 10月 12 10:26 proc.log
-rw-r--r-- 1 user group 172 10月 12 10:25 proc.php
-rw-r--r-- 1 user group 118 10月 12 10:09 proc.sh

$ cat proc.log
2012-10-12 10:10:55 proc start
PID: 3220
2012-10-12 10:10:05 proc end
広告を非表示にする