PHP processen in background starten via shell_exec()

Pagina: 1
Acties:

  • glashio
  • Registratie: Oktober 2001
  • Laatst online: 30-11 17:18

glashio

C64 > AMIGA > PC

Topicstarter
Als ik dit test.php uitvoer in de shell
PHP:
1
2
3
4
5
6
7
8
9
10
#!/usr/local/bin/php
<?php

$start = time();

shell_exec('nohup sleep 5 2> /dev/null &');

echo time() - $start;

?>
Result
5

Het sleep commando wordt wel in een eigen background process gezet, maar het PHP process blijft er wel op wachten :?
Hoe kan ik er voor zorgen dat PHP direct doorgaat met het script zonder op het uitvoercommando te wachten?

> Google Certified Searcher
> Make users so committed to Google that it would be painful to leave
> C64 Gospel
> [SjoQ] = SjoQing


  • Kees
  • Registratie: Juni 1999
  • Laatst online: 14:01

Kees

Serveradmin / BOFH / DoC
Je kan php forken, of het process in de background starten met proc_open.

Een stukje simplified uit mijn scripts:
PHP:
1
2
3
4
5
6
7
                function start($dryrun)
                {
*knip*
                        $this->start = getmicrotime();
                        $this->process = proc_open($this->cmd, $this->descriptorspec, $this->pipes);
*knip*
                }

en cmd is dan een normaal commando, bijvoorbeeld sleep 10.

Vervolgens kun je er dingen op uitvoeren alla
PHP:
1
2
3
4
                function isRunning() {
                        $this->status = proc_get_status($this->process);
                        return $this->status['running'];
                }


Waarbij je in je maincode dan iets hebt als:
PHP:
1
2
3
 $child = new Child("sleep 100");
$child->start();
while ($child->isRunning()) { echo "nop, draait nog\n"; sleep(1); }

"Een serveradmin, voluit een serveradministrator, is dan weer een slavenbeheerder oftewel een slavendrijver" - Rataplan


  • glashio
  • Registratie: Oktober 2001
  • Laatst online: 30-11 17:18

glashio

C64 > AMIGA > PC

Topicstarter
Kees schreef op vrijdag 18 december 2009 @ 14:16:
Je kan php forken, of het process in de background starten met proc_open.
That Should Do the Trick ;)
Omdat het in een oudere PHP4 moet werken heb ik proc_get_status via de processlist laten lopen.
Natuurlijk is dit een rare workaround, maar het script zal niet meerdere keren tegelijk opgestart worden.
Edit: Gefixed via ps -fw --ppid
PHP: sleep.php
1
2
3
4
5
6
#!/usr/local/bin/php
<?php

sleep(3);

?>
PHP: run.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/local/bin/php
<?php

class multiprocess {
  var $maxProcessCnt = 7;
  var $phpscript = '';
  var $unique = 0; 
  var $processes = array();

  function multiprocess($phpscript, $unique) {
    $this->phpscript = $phpscript;
    $this->unique = $unique;
    while($this->monitor()) {
      sleep(1);
    }

    echo "Done...\n";
  }

  function canBeStarted() {
    return true;
  }

  function startProcess($phpscript, $unique) {
    static $desc = array(
      array('pipe', 'r'),
      array('pipe', 'w'),
      array('pipe', 'w')
    );

    $this->processes[$unique] = proc_open("/usr/local/bin/php $phpscript $unique", $desc, $pipes);

    echo "Process #$unique started...\n";
  }

  function stopProcess($unique) {
    proc_close($this->processes[$unique]);
    unset($this->processes[$unique]);

    echo "Process #$unique stopped...\n";
  }

  function monitor() {
    static $phpscript = '';
    if (!$phpscript) {
      $phpscript = preg_quote($this->phpscript);
    }
    $grep = shell_exec('ps -fw --ppid ' . getmypid());
    $running = 0;
    if (preg_match_all("#/usr/local/bin/php $phpscript ([0-9]+)#", $grep, $match)) {
      $procs = $match[0];
      $running = sizeOf($procs);
      foreach(array_keys($this->processes) as $procid) {
        if (!in_array($procid, $procs)) {
          $this->stopProcess($procid);
        }
      }
    }

    for($i = $running; $i < $this->maxProcessCnt; $i++) {
      if ($this->canBeStarted()) {
        $this->startProcess($this->phpscript, ++$this->unique);
        $running++;
      }
    }

    return $running > 0;
  }
}

class mysleep extends multiprocess {
  function canBeStarted() {
    static $cnt = 0;
    return $cnt++ < 30;
  }
}

$mp = @new mysleep('sleep.php', time());

?>
Result
./run.php
Process #1261390668 started...
Process #1261390669 started...
Process #1261390668 stopped...
Process #1261390669 stopped...
Process #1261390670 started...
Process #1261390671 started...
Process #1261390670 stopped...
Process #1261390671 stopped...
Process #1261390672 started...
Process #1261390673 started...
Process #1261390672 stopped...
Process #1261390673 stopped...
Done...

[ Voor 9% gewijzigd door glashio op 21-12-2009 15:42 . Reden: Code herzien ]

> Google Certified Searcher
> Make users so committed to Google that it would be painful to leave
> C64 Gospel
> [SjoQ] = SjoQing