Dönüş için bekleyen OLMADAN Perl arka planda işi Koşu

5 Cevap php

The Disclaimer

Her şeyden önce, ben bu soru (ya da yakın varyasyonlar) bin kere soruldu biliyorum. Ben gerçekten açık ve çok da belirgin olmayan yerlerde arayan birkaç saat geçirdim, ama ben özlüyorum küçük bir şey olabilir.

The Context

Daha açık sorunu tanımlamak edelim: Ben gerçek gönderme işlemi uyumsuz olmak istediğiniz bir bülten app yazıyorum. Olduğu gibi, kullanıcı "gönder" tıklamaları, isteği hemen döner ve daha sonra (örneğin, AJAX) Belirli bir sayfa ilerlemeyi kontrol edebilirsiniz. Sizin geleneksel lamba yığını içinde yazılı.

Özellikle ev sahibi olarak ben, kullanarak PHP'nin exec () ve sistem () güvenlik nedenleriyle devre dışı, ama Perl sistem fonksiyonları (exec, sistem ve backticks) değildir değilim. Yani benim workaround çözüm PHP CLI üzerinden gerçek gönderen çağırır ve ilerleme sayfaya yönlendirir Perl bir "tetikleyici" komut dosyası oluşturmak için oldu.

Where I'm Stuck

Çok şimdi, gönderenin çağrıları hat:

system("php -q sender.php &");

Sorun, olmak hemen dönen değil, ama komut bitirmek için bekliyor. Ben arka planda çalıştırmak istediğiniz ve sistem çağrı kendisi hemen iade var. Ben de Linux terminalde benzer bir komut dosyası çalıştırmayı denedim, ve aslında istemi gerçekten arka planda çalışıyor gösteren, benim test çıkışı çalışmaz bile, script bittikten sonra kadar görünmüyor.

What I already tried

  • Perl exec () fonksiyonu - sisteminin (aynı sonuç).
  • Için komut değiştirme: |) "php-q sender.php şimdi de" umuduyla cini dönecekti "at" ve PHP sürecinin kendisi Perl bağlı değil ki.
  • 'Dolaylı' komutu yürütülüyor: "/ bin / sh-c 'php-q sender.php &'" - sender.php gönderiyor bitene kadar hala bekler.
  • fork () 'sürecini ing ve çocuk (umarım müstakil işlem) sistem çağrısını - aynı sonucu olarak yukarıdaki

My test environment

Sadece belirgin bir şey eksik değilim emin olmak için, ben sadece çıkmadan önce beş saniye uyumayan bir sleeper.php komut dosyası oluşturulur. Ve aynen böyle bir test.cgi komut olduğunu:

#!/usr/local/bin/perl
system("php sleeper.php &");
print "Content-type: text/html\n\ndone";

What should I try now?

5 Cevap

Sorunu çözmek için başardı. Görünüşe göre ne dönen onu tutmak oldu gönderenin bu şekilde çağırıyor stdout'unu bağlantısını vermedi oldu. Peki, çözüm basitçe sistem çağrısı değişiyordu:

system("php sender.php > /dev/null &");

Teşekkürler yardım için herkes. Ben stdout kesmek için bir fikrim var bir süreç "Daemonizing" hakkında bütün hikayeyi okurken, aslında öyleydi.

Bir çocuk kapalı çatal ve üst güvenle çocuğu etkilemeden sonlandırabilirsiniz böylece sonra tamamen üst ayırın - Esasen 'Artalanda' bir süreç gerekiyor.

Sen CPAN modülü ile kolayca yapabilirsiniz Proc::Daemon:

use Proc::Daemon;
# do everything you need to do before forking the child...

# make into daemon; closes all open fds
Proc::Daemon::Init();

Bazen STDERR ve STDOUT de hem almak için, (Ben kullanmak çoğu kabuk ortamlarda (bash, csh, vb) için ...) kullanmak ... sistemini kilitleyebilirsiniz:

system("php sender.php > /dev/null 2>&1 &");

Kullan fork() ve ardından alt süreçte system diyoruz.

my $pid = fork();
if (defined $pid && $pid == 0) {
    # child
    system($command);    # or exec($command)
    exit 0;
}
# parent
# ... continue ...

Başka bir seçenek e-posta gönderme yapmak bir gearman sunucusu ve bir işçi işlemi (veya süreçleri) kurmak olacaktır. Eğer çok e-posta gönderme, aynı anda oluyor nasıl kontrol bu şekilde, ve hiçbir çatallaşma gereklidir. İstemci (program) (istenirse bir sonucu beklemeden arka planda) Gearman sunucuya bir görev ekleyebilir ve sunucunun kullanılabilir bir işçinin işi geçene kadar işleri sıraya alınır. Orada Gearman için perl ve php API'leri vardır, bu yüzden çok uygun.