The following function takes an array of shell commands and executes them. It is able to execute up to $nb_max_process at the same time. As soon as one process is terminated, another one is executed. Quite useful if you want to batch process commands on a multi-processor or multi-core environment.
The example below tries to convert to PNG a list of SVG files submitted on the command line (using Inkscape).
(it's quick and dirty but works very well for me)
#!/usr/bin/php
<?php
function pool_execute($commandes,$nb_max_process) {
$pool=array();
for($i=0;$i<$nb_max_process;$i++) {
$pool[$i]=FALSE;
}
while(count($commandes)>0) {
$commande=array_shift($commandes);
$commande_lancee=FALSE;
while($commande_lancee==FALSE) {
usleep(50000);
for($i=0;$i<$nb_max_process and $commande_lancee==FALSE;$i++) {
if($pool[$i]===FALSE) {
$pool[$i]=proc_open($commande,array(),$foo);
$commande_lancee=TRUE;
} else {
$etat=proc_get_status($pool[$i]);
if($etat['running']==FALSE) {
proc_close($pool[$i]);
$pool[$i]=proc_open($commande,array(),$foo);
$commande_lancee=TRUE;
}
}
}
}
}
}
$fichiers=$argv;
array_shift($fichiers);
$commandes=array();
foreach($fichiers as $fichier) {
$entree=$fichier;
$sortie=basename($fichier,'.svg').".png";
$commandes[]='inkscape --file='.escapeshellarg($entree).' --export-area-canvas --export-png='.escapeshellarg($sortie);
}
pool_execute($commandes,4);
説明
array proc_get_status
( resource $process
)
proc_get_status() は、proc_open() で開かれたプロセスに関する情報を取得します。
返り値
成功時は集められた情報の配列、失敗時は FALSE 。 返される配列は次のような要素を持ちます:
| 要素 | 型 | 説明 |
|---|---|---|
| command | string | proc_open() に指定されたコマンド文字列。 |
| pid | int | プロセス ID |
| running | bool | もしプロセスがまだ動いている場合は、TRUE 、すでに終了している場合は FALSE。 |
| signaled | bool | 子プロセスが、キャッチされていないシグナルにより終了した場合に TRUE となります。Windows では常に FALSE にセットされます。 |
| stopped | bool | 子プロセスが、シグナルにより停止した時に TRUE となります。 Windows では常に FALSE にセットされます。 |
| exitcode | int | プロセスが返した終了コード (running が FALSE の時のみ意味を持ちます)。 正しい値を返すのは関数を最初にコールした時のみで、次に コールした際には -1 を返します。 |
| termsig | int | プロセスを終了させたシグナルの番号です (signaled が TRUE の時のみ意味を持ちます)。 |
| stopsig | int | プロセスを停止させたシグナルの番号です (stopped が TRUE の時のみ意味を持ちます)。 |
proc_get_status
webmaster at rouen dot fr
09-Jul-2008 01:49
09-Jul-2008 01:49
strrev xc.noxeh@ellij
05-Jun-2008 01:12
05-Jun-2008 01:12
You can NOT rely on pid+1.
You could prefix exec to the command string, this will replace the /bin/sh script with the real thing you want to exec (use only if you don't do 'scary things' like pipes, output redirection, multiple commands, however if you know how they work, go ahead).
If you prefix exec, the /bin/sh process will only start your process, and the PID will be the same.
damien at cyg dot net
13-Jun-2007 06:06
13-Jun-2007 06:06
Alternatively, if you're calling a subsequent php script using proc_open, you can have that process echo its own actual PID in the output.
Also, if you go through the /proc filesystem on linux, you can read through /proc/12345 where 12345 is the pid returned by proc_get_status (the pid of the /bin/sh instance) and it will list its child processes within.
andy dot shellam at mailnetwork dot co dot uk
05-Apr-2007 05:16
05-Apr-2007 05:16
Further to my previous note, I've found out the PID returned is the PID of the shell (/bin/sh) that then runs the actual command requested.
I've raised this as bug #41003.
andy dot shellam at mailnetwork dot co dot uk
05-Apr-2007 04:58
05-Apr-2007 04:58
To the poster above, same here on FreeBSD 6.1, PHP 5.2.1.
To get the correct PID to use for posix_kill I have to add 1 to the PID returned from proc_get_status.
