Wie schließe ich eine Verbindung vorzeitig?

99

Ich versuche, einen AJAX-Aufruf (über JQuery) auszuführen, der einen ziemlich langen Prozess initiiert. Ich möchte, dass das Skript einfach eine Antwort sendet, die angibt, dass der Prozess gestartet wurde, aber JQuery gibt die Antwort erst zurück, wenn das PHP-Skript ausgeführt wurde.

Ich habe dies mit einem "close" -Header (unten) und auch mit Ausgabepufferung versucht. beides scheint nicht zu funktionieren. Irgendwelche Ideen? oder muss ich das in JQuery tun?

<?php

echo( "We'll email you as soon as this is done." );

header( "Connection: Close" );

// do some stuff that will take a while

mail( '[email protected]', "okay I'm done", 'Yup, all done.' );

?>
Eric_WVGG
quelle
Haben Sie Ihren Ausgabepuffer mit ob_flush () geleert und es hat nicht funktioniert?
Vinko Vrsalovic

Antworten:

87

Die folgende PHP-Handbuchseite (inkl. Benutzerhinweise) enthält mehrere Anweisungen zum Schließen der TCP-Verbindung zum Browser, ohne das PHP-Skript zu beenden:

Angeblich erfordert es etwas mehr als das Senden eines engen Headers.


OP bestätigt dann: yup, das hat den Trick gemacht: Verweis auf User Note # 71172 (Nov 2006) hier kopiert:

Das Schließen der Browserverbindung des Benutzers, während Ihr PHP-Skript ausgeführt wird, ist seit [PHP] 4.1 ein Problem, als das Verhalten von register_shutdown_function()so geändert wurde, dass die Benutzerverbindung nicht automatisch geschlossen wurde.

sts at mail dot xubion dot hu Veröffentlichte die ursprüngliche Lösung:

<?php
header("Connection: close");
ob_start();
phpinfo();
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();
sleep(13);
error_log("do something in the background");
?>

Was funktioniert gut , bis Sie ersetzen phpinfo()für echo('text I want user to see');in diesem Fall die Header werden nie gesendet!

Die Lösung besteht darin, die Ausgabepufferung explizit zu deaktivieren und den Puffer zu löschen, bevor Sie Ihre Header-Informationen senden. Beispiel:

<?php
ob_end_clean();
header("Connection: close");
ignore_user_abort(true); // just to be safe
ob_start();
echo('Text the user will see');
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush(); // Strange behaviour, will not work
flush(); // Unless both are called !
// Do processing here 
sleep(30);
echo('Text user will never see');
?>

Ich habe gerade 3 Stunden damit verbracht, dies herauszufinden, hoffe es hilft jemandem :)

Getestet in:

  • IE 7.5730.11
  • Mozilla Firefox 1.81

Später im Juli 2010 verknüpfte Arctic Fire in einer verwandten Antwort zwei weitere Benutzerhinweise, die Folgemaßnahmen zu den oben genannten waren:

Joeri Sebrechts
quelle
7
Ja, das hat den Trick gemacht: php.net/manual/en/features.connection-handling.php#71172
Eric_WVGG
1
Autor und @ Timbo White, Ist es möglich, eine Verbindung vorzeitig zu schließen, ohne die Größe des Inhalts zu kennen? IE, ohne vor dem Schließen Inhalte erfassen zu müssen.
Skibulk
3
Hacker und beschissene Webbrowser können den HTTP-Header zum Schließen der Verbindung immer noch ignorieren und den Rest der Ausgabe abrufen. Stellen Sie sicher, dass das, was als Nächstes kommt, nicht vertraulich ist. vielleicht ein ob_start (); um alles zu unterdrücken: p
hanshenrik
3
Hinzufügen von fastcgi_finish_request (); wurde gesagt, um die Verbindung erfolgreich zu schließen, wenn das oben genannte nicht funktioniert. In meinem Fall konnte mein Skript jedoch nicht weiter ausgeführt werden. Verwenden Sie es daher mit Vorsicht.
Eric Dubé
@RichardSmith Da der Connection: closeHeader von der anderen Software im Stack überschrieben werden kann, z. B. der Reverse-Proxy bei einem CGI (ich habe dieses Verhalten bei Nginx beobachtet). Siehe die Antwort von @hanshenrik dazu. Wird im Allgemeinen Connection: closeauf der Clientseite ausgeführt und sollte nicht als Antwort auf diese Frage betrachtet werden. Die Verbindung sollte von der Serverseite aus geschlossen werden .
7heo.tk
56

Es ist notwendig, diese 2 Header zu senden:

Connection: close
Content-Length: n (n = size of output in bytes )

Da Sie die Größe Ihrer Ausgabe kennen müssen, müssen Sie Ihre Ausgabe puffern und dann in den Browser leeren:

// buffer all upcoming output
ob_start();
echo "We'll email you as soon as this is done.";

// get the size of the output
$size = ob_get_length();

// send headers to tell the browser to close the connection
header("Content-Length: $size");
header('Connection: close');

// flush all output
ob_end_flush();
ob_flush();
flush();

// if you're using sessions, this prevents subsequent requests
// from hanging while the background process executes
if (session_id()) session_write_close();

/******** background process starts here ********/

Wenn Ihr Webserver die automatische gzip-Komprimierung für die Ausgabe verwendet (z. B. Apache mit mod_deflate), funktioniert dies nicht, da die tatsächliche Größe der Ausgabe geändert wird und die Inhaltslänge nicht mehr genau ist. Deaktivieren Sie die gzip-Komprimierung des jeweiligen Skripts.

Weitere Informationen finden Sie unter http://www.zulius.com/how-to/close-browser-connection-continue-execution

Timbo Weiß
quelle
16
Wenn Ihr Server die Ausgabe komprimiert, können Sie sie mit deaktivieren. Auf diese header("Content-Encoding: none\r\n");Weise wird sie von Apache nicht komprimiert.
GDmac
1
@ GDmac danke! Ich konnte dies für eine Weile nicht zum Laufen bringen, aber das Deaktivieren der Komprimierung hat den Trick getan.
Reactgular
Das ob_flush()ist nicht nötig und verursacht tatsächlich einen Hinweis failed to flush buffer. Ich habe es herausgenommen und das hat super funktioniert.
Levi
2
Ich fand , dass die ob_flush()Linie war notwendig.
Deebster
21

Sie können Fast-CGI mit PHP-FPM verwenden, um die fastcgi_end_request()Funktion zu verwenden . Auf diese Weise können Sie die Verarbeitung fortsetzen, während die Antwort bereits an den Client gesendet wurde.

Sie finden dies im PHP-Handbuch hier: FastCGI Process Manager (FPM) ; Diese Funktion ist jedoch im Handbuch nicht weiter dokumentiert. Hier der Auszug aus dem PHP-FPM: PHP FastCGI Process Manager Wiki :


fastcgi_finish_request ()

Geltungsbereich: PHP-Funktion

Kategorie: Optimierung

Mit dieser Funktion können Sie die Implementierung einiger PHP-Abfragen beschleunigen. Eine Beschleunigung ist möglich, wenn während der Skriptausführung Aktionen ausgeführt werden, die sich nicht auf die Serverantwort auswirken. Das Speichern der Sitzung in Memcached kann beispielsweise erfolgen, nachdem die Seite erstellt und an einen Webserver übergeben wurde. fastcgi_finish_request()ist eine PHP-Funktion, die die Antwortausgabe stoppt. Der Webserver beginnt sofort, die Antwort "langsam und traurig" an den Client zu übertragen, und gleichzeitig kann PHP im Kontext einer Abfrage viele nützliche Dinge tun, z. B. das Speichern der Sitzung, das Konvertieren des heruntergeladenen Videos und das Behandeln aller Arten von Statistiken usw.

fastcgi_finish_request() kann die Ausführung der Abschaltfunktion aufrufen.


Hinweis: fastcgi_finish_request() hat eine Marotte , wo Anrufe flush, printoder echowird das Skript vorzeitig beenden.

Um dieses Problem zu vermeiden, können Sie ignore_user_abort(true)direkt vor oder nach dem fastcgi_finish_requestAnruf anrufen:

ignore_user_abort(true);
fastcgi_finish_request();
Jorrit Schippers
quelle
3
DAS IST TATSÄCHLICHE ANTWORT!
Kirill Titov
2
Wenn Sie PHP-Fpm verwenden - verwenden Sie einfach diese Funktion - vergessen Sie die Header und alles andere. Hat mir so viel Zeit gespart!
Ross
17

Vollversion:

ignore_user_abort(true);//avoid apache to kill the php running
ob_start();//start buffer output

echo "show something to user";
session_write_close();//close session file on server side to avoid blocking other requests

header("Content-Encoding: none");//send header to avoid the browser side to take content as gzip format
header("Content-Length: ".ob_get_length());//send length header
header("Connection: close");//or redirect to some url: header('Location: http://www.google.com');
ob_end_flush();flush();//really send content, can't change the order:1.ob buffer to normal buffer, 2.normal buffer to output

//continue do something on server side
ob_start();
sleep(5);//the user won't wait for the 5 seconds
echo 'for diyism';//user can't see this
file_put_contents('/tmp/process.log', ob_get_contents());
ob_end_clean();
DIYismus
quelle
vollständig in welchem ​​Sinne? Bei welchem ​​Problem mussten Sie das Skript für akzeptierte Antworten ausfüllen (welches?) Und welche Ihrer Konfigurationsunterschiede machten dies erforderlich?
hakre
4
diese Zeile: header ("Content-Encoding: none"); -> sehr wichtig.
Bobby Tables
2
Vielen Dank, dies ist die einzige funktionierende Lösung auf dieser Seite. Dies sollte als Antwort genehmigt werden.
6

Eine bessere Lösung besteht darin, einen Hintergrundprozess zu verzweigen. Unter Unix / Linux ist es ziemlich einfach:

<?php
echo "We'll email you as soon as this is done.";
system("php somestuff.php [email protected] >/dev/null &");
?>

Sie sollten sich diese Frage für bessere Beispiele ansehen:

PHP führt einen Hintergrundprozess aus

Salman A.
quelle
4

Angenommen, Sie haben einen Linux-Server und Root-Zugriff, versuchen Sie dies. Es ist die einfachste Lösung, die ich gefunden habe.

Erstellen Sie ein neues Verzeichnis für die folgenden Dateien und erteilen Sie ihm die vollständigen Berechtigungen. (Wir können es später sicherer machen.)

mkdir test
chmod -R 777 test
cd test

Fügen Sie dies in eine Datei mit dem Namen ein bgping.

echo starting bgping
ping -c 15 www.google.com > dump.txt &
echo ending bgping

Beachten Sie die &. Der Ping-Befehl wird im Hintergrund ausgeführt, während der aktuelle Prozess zum Echo-Befehl übergeht. Es wird 15 Mal ein Ping an www.google.com gesendet, was ungefähr 15 Sekunden dauert.

Machen Sie es ausführbar.

chmod 777 bgping

Fügen Sie dies in eine Datei mit dem Namen ein bgtest.php.

<?php

echo "start bgtest.php\n";
exec('./bgping', $output, $result)."\n";
echo "output:".print_r($output,true)."\n";
echo "result:".print_r($result,true)."\n";
echo "end bgtest.php\n";

?>

Wenn Sie bgtest.php in Ihrem Browser anfordern, sollten Sie schnell die folgende Antwort erhalten, ohne etwa 15 Sekunden auf den Abschluss des Ping-Befehls warten zu müssen.

start bgtest.php
output:Array
(
    [0] => starting bgping
    [1] => ending bgping
)

result:0
end bgtest.php

Der Ping-Befehl sollte jetzt auf dem Server ausgeführt werden. Anstelle des Befehls ping können Sie auch ein PHP-Skript ausführen:

php -n -f largejob.php > dump.txt &

Hoffe das hilft!

Liam
quelle
4

Hier ist eine Modifikation von Timbos Code, die mit der gzip-Komprimierung funktioniert.

// buffer all upcoming output
if(!ob_start("ob_gzhandler")){
    define('NO_GZ_BUFFER', true);
    ob_start();
}
echo "We'll email you as soon as this is done.";

//Flush here before getting content length if ob_gzhandler was used.
if(!defined('NO_GZ_BUFFER')){
    ob_end_flush();
}

// get the size of the output
$size = ob_get_length();

// send headers to tell the browser to close the connection
header("Content-Length: $size");
header('Connection: close');

// flush all output
ob_end_flush();
ob_flush();
flush();

// if you're using sessions, this prevents subsequent requests
// from hanging while the background process executes
if (session_id()) session_write_close();

/******** background process starts here ********/
Andrew Winter
quelle
Du bist ein Gott. Ich habe 2 Tage lang gearbeitet, um das herauszufinden. Es funktionierte auf meinem lokalen Entwickler, aber nicht auf dem Host. Ich wurde abgespritzt. DU HAST MICH GERETTET. DANKE!!!!
Chad Caldwell
3

Ich bin auf einem gemeinsam genutzten Host und bin so eingerichtet fastcgi_finish_request, dass Skripte vollständig beendet werden. Ich mag die connection: closeLösung auch nicht. Durch die Verwendung wird eine separate Verbindung für nachfolgende Anforderungen erzwungen, was zusätzliche Serverressourcen kostet. Ich habe den Transfer-Encoding: cunked Wikipedia-Artikel gelesen und erfahren, dass 0\r\n\r\neine Antwort beendet wird. Ich habe dies nicht gründlich auf allen Browserversionen und Geräten getestet, aber es funktioniert auf allen 4 meiner aktuellen Browser.

// Disable automatic compression
// @ini_set('zlib.output_compression', 'Off');
// @ini_set('output_buffering', 'Off');
// @ini_set('output_handler', '');
// @apache_setenv('no-gzip', 1);

// Chunked Transfer-Encoding & Gzip Content-Encoding
function ob_chunked_gzhandler($buffer, $phase) {
    if (!headers_sent()) header('Transfer-Encoding: chunked');
    $buffer = ob_gzhandler($buffer, $phase);
    return dechex(strlen($buffer))."\r\n$buffer\r\n";
}

ob_start('ob_chunked_gzhandler');

// First Chunk
echo "Hello World";
ob_flush();

// Second Chunk
echo ", Grand World";
ob_flush();

ob_end_clean();

// Terminating Chunk
echo "\x30\r\n\r\n";
ob_flush();
flush();

// Post Processing should not be displayed
for($i=0; $i<10; $i++) {
    print("Post-Processing");
    sleep(1);
}
Skibulk
quelle
Dank Ihrer guten Antwort wurde mir klar, wie dumm (und unnötig) es ist, eine Verbindung zu verwenden: schließen. Ich denke, einige kennen die Schrauben und Muttern ihres Servers nicht.
Justin
@ Justin Ich habe das vor langer Zeit geschrieben. Wenn ich es mir noch einmal anschaue, sollte ich beachten, dass es möglicherweise notwendig ist, die Chunks auf 4 KB aufzufüllen. Ich scheine mich zu erinnern, dass einige Server erst nach Erreichen dieses Minimums geleert werden.
Skibulk
2

Sie könnten versuchen, Multithreading durchzuführen.

Sie könnten ein Skript erstellen , das einen Systemaufruf ausführt (mithilfe von shell_exec ), der die PHP-Binärdatei mit dem Skript aufruft, um Ihre Arbeit als Parameter auszuführen . Aber ich denke nicht, dass dies der sicherste Weg ist. Vielleicht können Sie Dinge aufhellen, indem Sie den PHP-Prozess und andere Dinge chrooten

Alternativ gibt es eine Klasse bei phpclasses, die dies tut http://www.phpclasses.org/browse/package/3953.html . Aber ich kenne die Einzelheiten der Implementierung nicht

paan
quelle
Wenn Sie nicht auf den Abschluss des Prozesses warten möchten, verwenden Sie das &Zeichen, um den Prozess im Hintergrund auszuführen.
Liam
2

TL; DR Antwort:

ignore_user_abort(true); //Safety measure so that the user doesn't stop the script too early.

$content = 'Hello World!'; //The content that will be sent to the browser.

header('Content-Length: ' . strlen($content)); //The browser will close the connection when the size of the content reaches "Content-Length", in this case, immediately.

ob_start(); //Content past this point...

echo $content;

//...will be sent to the browser (the output buffer gets flushed) when this code executes.
ob_end_flush();
ob_flush();
flush();

if(session_id())
{
    session_write_close(); //Closes writing to the output buffer.
}

//Anything past this point will be ran without involving the browser.

Funktionsantwort:

ignore_user_abort(true);

function sendAndAbort($content)
{
    header('Content-Length: ' . strlen($content));

    ob_start();

    echo $content;

    ob_end_flush();
    ob_flush();
    flush();
}

sendAndAbort('Hello World!');

//Anything past this point will be ran without involving the browser.
FluorescentGreen5
quelle
1

Ihr Problem kann durch parallele Programmierung in PHP gelöst werden. Ich habe vor einigen Wochen hier eine Frage dazu gestellt: Wie kann man Multithreading in PHP-Anwendungen verwenden?

Und bekam tolle Antworten. Besonders gut hat mir einer gefallen. Der Autor hat auf das Tutorial Easy Parallel Processing in PHP (September 2008; von Johnlim) verwiesen, das Ihr Problem tatsächlich sehr gut lösen kann, da ich es bereits verwendet habe, um ein ähnliches Problem zu lösen, das vor einigen Tagen aufgetreten ist.

Steve Obbayi
quelle
1

Die Antwort von Joeri Sebrechts ist knapp, zerstört jedoch alle vorhandenen Inhalte, die möglicherweise gepuffert werden, bevor Sie die Verbindung trennen möchten. Es wird nicht ignore_user_abortrichtig aufgerufen , sodass das Skript vorzeitig beendet werden kann. Die Antwort des DIYismus ist gut, aber nicht allgemein anwendbar. Beispielsweise kann eine Person mehr oder weniger Ausgabepuffer haben, die diese Antwort nicht verarbeitet, sodass sie in Ihrer Situation möglicherweise einfach nicht funktioniert und Sie nicht wissen, warum.

Mit dieser Funktion können Sie die Verbindung jederzeit trennen (solange noch keine Header gesendet wurden) und den bisher generierten Inhalt beibehalten. Die zusätzliche Bearbeitungszeit ist standardmäßig unbegrenzt.

function disconnect_continue_processing($time_limit = null) {
    ignore_user_abort(true);
    session_write_close();
    set_time_limit((int) $time_limit);//defaults to no limit
    while (ob_get_level() > 1) {//only keep the last buffer if nested
        ob_end_flush();
    }
    $last_buffer = ob_get_level();
    $length = $last_buffer ? ob_get_length() : 0;
    header("Content-Length: $length");
    header('Connection: close');
    if ($last_buffer) {
        ob_end_flush();
    }
    flush();
}

Wenn Sie auch zusätzlichen Speicher benötigen, weisen Sie ihn zu, bevor Sie diese Funktion aufrufen.

Walf
quelle
1

Hinweis für mod_fcgid-Benutzer (bitte auf eigenes Risiko verwenden).

Schnelle Lösung

Die akzeptierte Antwort von Joeri Sebrechts ist in der Tat funktional. Wenn Sie jedoch mod_fcgid verwenden, stellen Sie möglicherweise fest, dass diese Lösung nicht alleine funktioniert. Mit anderen Worten, wenn die Flush- Funktion aufgerufen wird, wird die Verbindung zum Client nicht geschlossen.

Der FcgidOutputBufferSizeKonfigurationsparameter von mod_fcgid kann schuld sein. Ich habe diesen Tipp gefunden in:

  1. diese Antwort von Travers Carter und
  2. Dieser Blog-Beitrag von Seumas Mackinnon .

Nachdem Sie das Obige gelesen haben, können Sie zu dem Schluss kommen, dass eine schnelle Lösung darin besteht, die Zeile hinzuzufügen (siehe "Beispiel für einen virtuellen Host" am Ende):

FcgidOutputBufferSize 0

entweder in Ihrer Apache-Konfigurationsdatei (z. B. httpd.conf), Ihrer FCGI-Konfigurationsdatei (z. B. fcgid.conf) oder in Ihrer virtuellen Hosts-Datei (z. B. httpd-vhosts.conf).

In (1) oben wird eine Variable mit dem Namen "OutputBufferSize" erwähnt. Dies ist der alte Name des FcgidOutputBufferSizein (2) genannten (siehe die Upgrade-Hinweise auf der Apache-Webseite für mod_fcgid ).

Details & eine zweite Lösung

Die obige Lösung deaktiviert die von mod_fcgid durchgeführte Pufferung entweder für den gesamten Server oder für einen bestimmten virtuellen Host. Dies kann zu einer Leistungsminderung für Ihre Website führen. Auf der anderen Seite ist dies möglicherweise nicht der Fall, da PHP die Pufferung selbst durchführt.

Falls Sie die Pufferung von mod_fcgid nicht deaktivieren möchten , gibt es eine andere Lösung ... Sie können diesen Puffer zum Leeren zwingen .

Der folgende Code macht genau das, indem er auf der von Joeri Sebrechts vorgeschlagenen Lösung aufbaut:

<?php
    ob_end_clean();
    header("Connection: close");
    ignore_user_abort(true); // just to be safe
    ob_start();
    echo('Text the user will see');

    echo(str_repeat(' ', 65537)); // [+] Line added: Fill up mod_fcgi's buffer.

    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush(); // Strange behaviour, will not work
    flush(); // Unless both are called !
    // Do processing here 
    sleep(30);
    echo('Text user will never see');
?>

Die hinzugefügte Codezeile füllt im Wesentlichen den Puffer von mod_fcgi und zwingt ihn zum Leeren . Die Nummer "65537" wurde gewählt, da der Standardwert der FcgidOutputBufferSizeVariablen "65536" ist, wie auf der Apache-Webseite für die entsprechende Anweisung angegeben . Daher müssen Sie diesen Wert möglicherweise entsprechend anpassen, wenn in Ihrer Umgebung ein anderer Wert festgelegt ist.

Meine Umgebung

  • WampServer 2.5
  • Apache 2.4.9
  • PHP 5.5.19 VC11, x86, nicht threadsicher
  • mod_fcgid / 2.3.9
  • Windows 7 Professional x64

Beispiel für einen virtuellen Host

<VirtualHost *:80>
    DocumentRoot "d:/wamp/www/example"
    ServerName example.local

    FcgidOutputBufferSize 0

    <Directory "d:/wamp/www/example">
        Require all granted
    </Directory>
</VirtualHost>
Tasos
quelle
Ich habe viele Lösungen ausprobiert. Und dies ist die einzige Lösung, die für mich mit mod_fcgid funktioniert.
Tsounabe
1

das hat bei mir funktioniert

//avoid apache to kill the php running
ignore_user_abort(true);
//start buffer output
ob_start();

echo "show something to user1";
//close session file on server side to avoid blocking other requests
session_write_close();

//send length header
header("Content-Length: ".ob_get_length());
header("Connection: close");
//really send content, can't change the order:
//1.ob buffer to normal buffer,
//2.normal buffer to output
ob_end_flush();
flush();
//continue do something on server side
ob_start();
//replace it with the background task
sleep(20);
Williem
quelle
0

Ok, im Grunde genommen funktioniert jQuery die XHR-Anforderung nicht, selbst die ob_flush-Methode funktioniert nicht, da Sie nicht bei jedem onreadystatechange eine Funktion ausführen können. jQuery überprüft den Status und wählt dann die richtigen Aktionen aus (abgeschlossen, Fehler, Erfolg, Zeitüberschreitung). Und obwohl ich keine Referenz finden konnte, erinnere ich mich, dass dies nicht bei allen XHR-Implementierungen funktioniert. Eine Methode, von der ich glaube, dass sie für Sie funktionieren sollte, ist eine Kreuzung zwischen ob_flush und Forever-Frame-Polling.

<?php
 function wrap($str)
 {
  return "<script>{$str}</script>";
 };

 ob_start(); // begin buffering output
 echo wrap("console.log('test1');");
 ob_flush(); // push current buffer
 flush(); // this flush actually pushed to the browser
 $t = time();
 while($t > (time() - 3)) {} // wait 3 seconds
 echo wrap("console.log('test2');");
?>

<html>
 <body>
  <iframe src="ob.php"></iframe>
 </body>
</html>

Und weil die Skripte inline ausgeführt werden, während die Puffer geleert werden, erhalten Sie die Ausführung. Um dies nützlich zu machen, ändern Sie die Datei console.log in eine Rückrufmethode, die in Ihrem Hauptskript-Setup definiert ist, um Daten zu empfangen und darauf zu reagieren. Hoffe das hilft. Prost, Morgan.

Morgan ARR Allen
quelle
0

Eine alternative Lösung besteht darin, den Job einer Warteschlange hinzuzufügen und ein Cron-Skript zu erstellen, das nach neuen Jobs sucht und diese ausführt.

Ich musste es kürzlich so machen, um die von einem gemeinsam genutzten Host auferlegten Grenzwerte zu umgehen - exec () et al. War für PHP, das vom Webserver ausgeführt wurde, deaktiviert, konnte aber in einem Shell-Skript ausgeführt werden.

Ole Helgesen
quelle
0

Wenn die flush()Funktion nicht funktioniert. Sie müssen die nächsten Optionen in der php.ini wie folgt festlegen :

output_buffering = Off  
zlib.output_compression = Off  
Nir O.
quelle
0

Neueste Arbeitslösung

    // client can see outputs if any
    ignore_user_abort(true);
    ob_start();
    echo "success";
    $buffer_size = ob_get_length();
    session_write_close();
    header("Content-Encoding: none");
    header("Content-Length: $buffer_size");
    header("Connection: close");
    ob_end_flush();
    ob_flush();
    flush();

    sleep(2);
    ob_start();
    // client cannot see the result of code below
Sudharshana SL Srihari
quelle
0

Nachdem ich viele verschiedene Lösungen aus diesem Thread ausprobiert habe (nachdem keine für mich funktioniert hat), habe ich auf der offiziellen PHP.net-Seite eine Lösung gefunden:

function sendResponse($response) {
    ob_end_clean();
    header("Connection: close\r\n");
    header("Content-Encoding: none\r\n");
    ignore_user_abort(true);
    ob_start();

    echo $response; // Actual response that will be sent to the user

    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush();
    flush();
    if (ob_get_contents()) {
        ob_end_clean();
    }
}
Weißer Engel
quelle