Uzun süre çalışan php script yönetmek için en iyi yolu?

12 Cevap php

Ben tamamlamak için uzun bir süre (5-30 dakika) sürer bir PHP komut dosyası var. Sadece konularda durumda, komut başka bir sunucudan veri kazımak için Curl kullanıyor. Bu o kadar uzun sürüyor nedeni; onu işleme ve sonraki geçmeden önce yüklemek için her sayfa için beklemek zorunda.

Ben senaryoyu başlatmak ve bir veritabanı tablosundaki bir bayrak, hangi bitti kadar izin edebilmek için istiyorum.

Sorun bu kadar uzun sürüyor bir istek gibi değil bir iPhone app, gelen init çağrı yapıyorum olmasıdır. Ben ilk istek çabuk bitmiş olması istiyorum.

Yani özetle, ne bilmeniz gereken komut çalıştıran bitmeden http isteği sonuna edebilmek için nasıl. Ayrıca, bir php script bunu yapmanın en iyi yolu nedir? (Benim sunucu, Ruby on Rails, Python, Perl destekleyen Curl bu atıfta ne <-emin) Ben diğer dillerde herhangi bir deneyimi yok rağmen.

12 Cevap

Sen exec kullanabilir veya system bir arka plan işini başlatmak için, ve o içinde işi yapmak.

Ayrıca, tek kullandığınız web kazıma daha iyi yaklaşımlar vardır. Bir eventloop (anda birden fazla sayfaları yapmanın bir iş parçacığı) kullanarak dişli bir yaklaşım (bir defada bir sayfa yapıyor birden çok iş parçacığı), ya da birini kullanabilirsiniz. Perl kullanarak benim kişisel bir yaklaşım kullanarak AnyEvent::HTTP. Olacaktır

ETA: symcbean düzgün arka plan işlemi ayırmak için nasıl açıklanabilir here.

Kesinlikle PHP ile yapılabilir, ancak bir arka plan görevi olarak bunu olmaMAlıdır - yeni işlem başlatıldığı süreç grubundan dissocated gerekir.

Insanlar bu SSS aynı yanlış cevabı vermeye devam yana, ben burada dolgun bir cevap yazdım:

http://symcbean.blogspot.com/2010/02/php-and-long-running-processes.html

C.

Hızlı ve kirli bir şekilde php ignore_user_abort fonksiyonunu kullanmak olacaktır. Bu temelde diyor ki: tamamlanıncaya kadar çalışacak, kullanıcının ne bu senaryoyu Umurumda değil. Bir kamu bakan site ise (o bunu 20 kez başlatılan ise aynı anda çalışan script 20 + + versiyonlarını sahip sona ki, mümkün çünkü) bu biraz tehlikelidir.

"Temiz" bir şekilde (en azından IMHO) bir süreci başlatmak ve (veya) bir cronjob her saat çalıştırmak bayrak ayarlanmış olup olmadığını kontrol etmek istediğiniz zaman (örneğin db) bir bayrak için. Ayarlı ise, uzun süren script ayarlı DEĞİL ise, hiçbirşey olmuyor başlar.

PHP ya da en iyi araç olmayabilir, ama bunu nasıl kullanılacağını bilmek ve uygulamanın geri kalanı kullanarak yazılır. PHP yerine Perl, Ruby veya Python, bunu kullanmak için oldukça güçlü bir durumda yapmak "yeterince iyi" olduğu gerçeği ile birlikte bu iki nitelikleri,.

Amacınız başka bir dil öğrenmek için ise, o zaman birini seçmek ve kullanmak. Eğer belirtilen herhangi bir dil, hiçbir sorun iş yapacak. Perl gibi olur, ama ne gibi farklı olabilir.

Symcbean onun bağdaki arka plan süreçlerini yönetmek konusunda bazı tavsiyeleri vardır.

Kısacası, uzun bit işlemek için bir PHP CLI senaryo yazmak. O bir şekilde durumunu bildirir emin olun. AJAX veya geleneksel yöntemlerle ya, durum güncellemeleri işlemek için bir php sayfası yapmak. Sizin başlama komut kendi oturumunda çalışan işlemini başlatmak ve süreç gidiyor onay dönecektir.

İyi şanslar.

Ben bu bir arka plan işlemi çalıştırmak gerektiğini söylüyorlar cevapları ile katılıyorum. Ama bunu kullanıcı çalışma yapılıyor biliyor durumuyla ilgili rapor olması da önemlidir.

Sürecini başlatmak için PHP istek alırken, bir veritabanında benzersiz bir tanımlayıcı ile görevin bir temsilini depolayabilir. Sonra, o benzersiz bir tanımlayıcı geçen, ekran kazıma işlemini başlatın. Görev başladı ve son durumunu almak için, yeni görev kimliğini içeren, belirtilen bir URL kontrol gerektiğini edildiğini geri iPhone app Raporu. IPhone uygulaması artık ("uzun anket" ve hatta) bu URL yoklamak. Bir tamamlanma yüzdesi, mevcut aşamada, ya da başka hangi statü göstergeleri İstediğiniz ile çalıştı arada, arka plan işlemi görevin veritabanı temsil güncelleştirmek. Bu bittikten zaman, bu tamamlanmış bir bayrak açardı.

Hayır, PHP en iyi çözüm değildir.

Ruby veya Perl hakkında emin değilim, ama Python ile sizin sayfa kazıyıcı çok dişli olması yazabilirsiniz ve muhtemelen daha hızlı en az 20x çalışır. Multi-threaded uygulamalar yazma biraz bir meydan okuma olabilir, ama ben yazdım ilk Python uygulaması mutlti dişli sayfa sıyırıcı oldu olabilir. Ve sadece kabuk yürütme işlevlerinden birini kullanarak PHP sayfası içinde Python komut diyebiliriz.

Ben bu oldukça eski bir soru olduğunu fark ama denemek istiyorum. Bu script hızla bitirmek ve küçük parçalar halinde ağır yükü devirmek için çağrı off ilk tekme hem hitap etmeye çalışır. Ben bu çözüm test değil.

<?php
/**
 * crawler.php located at http://mysite.com/crawler.php
 */

// Make sure this script will keep on runing after we close the connection with
// it.
ignore_user_abort(TRUE);


function get_remote_sources_to_crawl() {
  // Do a database or a log file query here.

  $query_result = array (
    1 => 'http://exemple.com',
    2 => 'http://exemple1.com',
    3 => 'http://exemple2.com',
    4 => 'http://exemple3.com',
    // ... and so on.
  );

  // Returns the first one on the list.
  foreach ($query_result as $id => $url) {
    return $url;
  }
  return FALSE;
}

function update_remote_sources_to_crawl($id) {
  // Update my database or log file list so the $id record wont show up
  // on my next call to get_remote_sources_to_crawl()
}

$crawling_source = get_remote_sources_to_crawl();

if ($crawling_source) {


  // Run your scraping code on $crawling_source here.


  if ($your_scraping_has_finished) {
    // Update you database or log file.
    update_remote_sources_to_crawl($id);

    $ctx = stream_context_create(array(
      'http' => array(
        // I am not quite sure but I reckon the timeout set here actually
        // starts rolling after the connection to the remote server is made
        // limiting only how long the downloading of the remote content should take.
        // So as we are only interested to trigger this script again, 5 seconds 
        // should be plenty of time.
        'timeout' => 5,
      )
    ));

    // Open a new connection to this script and close it after 5 seconds in.
    file_get_contents('http://' . $_SERVER['HTTP_HOST'] . '/crawler.php', FALSE, $ctx);

    print 'The cronjob kick off has been initiated.';
  }
}
else {
  print 'Yay! The whole thing is done.';
}

Ben, Perl ile benzer şeyler yaptım çift çatalı () ve üst sürecinden ayırarak var. Iş getiriliyor Tüm http çatallı sürecinde yapılmalıdır.

Bir XHR (Ajax) istek olarak gönderebilirsiniz. Müşteriler genellikle normal HTTP isteklerinin aksine, XHR'ler için herhangi bir zaman aşımı yok.

Ben uzun süre için çalıştırmak için gereken PHP komut dosyalarını çalıştırmak için kullanılabilecek bir c + + hizmeti oluşturmak var.

Bkz http://jose.ydra.org/projects/PhpRunner

Isteği temsilci bir proxy kullanın.

(Linux farklı tatlar farklı çıkış / bazı programlar çıktı işleme konusunda farklı kurallar var çünkü) ne zaman kullanıma bu çeşitlerinden biridir:

Variant I @exec('./myscript.php \1>/dev/null \2>/dev/null &');

Variant II @exec('php -f myscript.php \1>/dev/null \2>/dev/null &');

Variant III @exec('nohup myscript.php \1>/dev/null \2>/dev/null &');

Siz "nohup" install havet olabilir. Ben FFMPEG Video converstions otomatize Ama ne zaman, örneğin, çıkış arayüzü şekilde çıktı akımları 1 & yönlendirerek tarafından ele% 100 değildi 2, bu yüzden nohup kullanılan VE çıktı yönlendirilir.