2009-09-19 26 views
6

W jaki sposób skrypt PHP może uruchomić inny skrypt PHP, a następnie zakończyć działanie, pozostawiając drugi skrypt uruchomiony?Czy skrypt PHP może uruchomić inny skrypt PHP i zakończyć?

Czy istnieje również sposób, aby drugi skrypt poinformował skrypt PHP, kiedy osiągnie konkretną linię?

+0

Czy "curl" może pomóc w tym? Masz pomysł? –

+0

Curl? Być może za pomocą żądania 'head', ale jestem sceptyczny –

+0

- jeśli pierwszy skrypt zostanie zakończony, w jaki sposób drugi skrypt poinformuje o pierwszym? - czy jest to strona internetowa czy skrypt konsoli? –

Odpowiedz

7

Oto jak to zrobić. Powiesz przeglądarce, aby przeczytała pierwsze N ​​znaków wyjściowych, a następnie zamknij połączenie, podczas gdy twój skrypt będzie działał, dopóki nie zostanie ukończony.

<?php 
ob_end_clean(); 
header("Connection: close"); 
ignore_user_abort(); // optional 
ob_start(); 
echo ('Text the user will see'); 
$size = ob_get_length(); 
header("Content-Length: $size"); 
ob_end_flush();  // Will not work 
flush();   // Unless both are called ! 

// At this point, the browser has closed connection to the web server 

// Do processing here 
include('other_script.php'); 

echo('Text user will never see'); 
?> 
+1

Czy możesz wyjaśnić swój kod trochę? Na przykład, spłukiwanie powoduje, że przeglądarka myśli o zakończeniu żądania HTTP? –

+0

Tak, to działa! Proszę również zamieścić tę odpowiedź na to pytanie - http://stackoverflow.com/questions/1436575/can-a-php-script-trick-the-browser-into-thinking-the-http-request-is-over –

+0

Redagowałem odpowiedź, aby ją trochę wyjaśnić. –

1

Oto ujęcie w ciemności: możesz spróbować użyć funkcji wykonawczych php dla systemu operacyjnego z &.

exec("./somescript.php &"); 

Dodatkowo, jeśli to nie pomoże, można spróbować

exec("nohup ./somescript.php &"); 

Edit: nohup is a POSIX command to ignore the HUP (hangup) signal, enabling the command to keep running after the user who issues the command has logged out. The HUP (hangup) signal is by convention the way a terminal warns depending processes of logout.

+0

'nohup' ?? Co to oznacza? –

3

Możesz to skutecznie osiągnąć przez forking, a następnie dzwoniąc pod numer include lub .

parent.php:

<?php 

    $pid = pcntl_fork(); 
    if ($pid == -1) { 
     die("couldn't fork"); 
    } else if ($pid) { // parent script 
     echo "Parent waiting at " . date("H:i:s") . "\n"; 
     pcntl_wait($status); 
     echo "Parent done at " . date("H:i:s") . "\n"; 
    } else { 
     // child script 
     echo "Sleeper started at " . date("H:i:s") . "\n"; 
     include('sleeper.php'); 
     echo "Sleeper done at " . date("H:i:s") . "\n"; 
    } 

?> 

sleeper.php:

<?php 
sleep(3); 
?> 

wyjściowa:

 
$ php parent.php 
Sleeper started at 01:22:02 
Parent waiting at 01:22:02 
Sleeper done at 01:22:05 
Parent done at 01:22:05 

Jednak rozwidlania nie natury umożliwiają dowolną komunikację między procesami, dzięki czemu Musiał znaleźć inny sposób poinformowania rodzica, że ​​dziecko dotarło do konkretnej linii, tak jak prosiłeś e pytanie.

+0

+1 Nie sądzę, że dokładnie to, czego chciał, ale nadal bardzo przydatne –

+0

Możesz zapewnić dwustronną komunikację za pośrednictwem metod gniazda (patrz http://www.php.net/manual/en/ref.sockets.php) . –

0

Jeśli nie chcesz budować rozszerzenia pcntl, dobrym rozwiązaniem jest użycie proc_open().

http://www.php.net/manual/en/function.proc-open.php

Używaj razem z stream_select() więc proces PHP może spać aż coś się dzieje z procesem potomnym utworzonego.

To skutecznie utworzy proces w tle, bez blokowania macierzystego procesu PHP. Ty PHP możesz czytać i pisać do STDIN, STDOUT, STDERR.

Aby załadować przeglądarkę (zatrzymać wskaźnik postępu ładowania), możesz skorzystać z informacji podanych przez Milan Babuškov.

Kluczem do tego, aby przeglądarka uznała, że ​​żądanie HTTP zostało zakończone, jest wysłanie jej treści o długości. Aby to zrobić, możesz rozpocząć buforowanie żądania, a następnie przepłukać je po wysłaniu nagłówka Content-Length.

np

<?php 

ob_start(); 

// render the HTML page and/or process stuff 

header('Content-Length: '.ob_get_length()); 
ob_flush(); 
flush(); 

// can do more processing 

?> 
0

Można utworzyć żądanie i zamknąć połączenie tuż po odbywa są zapisywane.

Sprawdź kod w http://drupal.org/project/httprl, co możesz zrobić (żądanie niezablokowania). Planuję popchnąć tę bibliotekę na github, gdy tylko go poprawię; coś, co można uruchomić poza drupalem. To powinno zrobić to, czego szukasz.