set_time_limit PHP-CLI etkileyen değil

6 Cevap php

Bu herhangi bir çözüm?

#!/usr/bin/php -q 
<?php
set_time_limit(2);
sleep(5); // actually, exec() call that takes > 2 seconds
echo "it didn't work again";

6 Cevap

Burada çözüm kullanmak için pcntl_fork(). Ben sadece POSIX korkuyorum. PHP --enable-pcntl olup --disable-posix ile derlenmiş olması gerekir. Kodunuzu aşağıdaki gibi görünmelidir:

<?php

function done($signo)
{
    // You can do any on-success clean-up here.
    die('Success!');
}

$pid = pcntl_fork();
if (-1 == $pid) {
    die('Failed! Unable to fork.');
} elseif ($pid > 0) {
    pcntl_signal(SIGALRM, 'done');
    sleep($timeout);
    posix_kill($pid, SIGKILL);
    // You can do any on-failure clean-up here.
    die('Failed! Process timed out and was killed.');
} else {
    // You can perform whatever time-limited operation you want here.
    exec($cmd);
    posix_kill(posix_getppid(), SIGALRM);
}

?>

Temelde ne yapar çatal else { ... } bloğu çalışan yeni bir süreçtir. Bunun (başarılı) bir sonuca biz elseif ($pid > 0) { ... } bloğunu çalıştıran ana süreç, geri bir alarm gönderecektir. Bu blok başarıyla sonlandırır alarm sinyali (done() callback) için tescilli sinyal işleyicisi var. Bu alınana kadar, ana süreç uyur. Zaman aşımı sleep() tamamlandığında, bu (muhtemelen askıda) alt işlemi için SIGKILL gönderir.

Ne set_time_limit takımları, sayım harcanmaktadır (at least, on Linux) Zaman olan max_execution_time sınırı PHP süreci, çalışırken.

Manuel sayfasını alıntı set_time_limit():

Note: The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself.
Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running.
This is not true on Windows where the measured time is real.

Eğer sleep() kullanırken, PHP komut dosyası çalışma değil: sadece bekliyor ... Peki bekliyor 5 saniye max_execution_time limiti tarafından dikkate alınmakta değildir.

Exec üzerinden php çalıştırmayı deneyin ve "zaman aşımı" komutunu kullanabilir miyim? (Http://packages.ubuntu.com/lucid/timeout)

kullanımı: zaman aşımı [sinyal] time komutu.

Ben komut bir döngü somewhoere durduğunu ssuming ediyorum. Neden sadece $STARTUP_TIME=time() komut başlangıç ​​yapmak ve komut çıkmak için neeeds eğer döngü içinde kontrol tutmak değil?

Ben cli betikleri çok kullanmak beri çok hackish, ama, ben shamefully geçmişte benzer bir hack kadar tokatladı sahip itiraf. Gerekli 2 komut.

İlk cron komut (asılı bir) düz bir dosya onun StartTime ve ProcessID günlükleri -> fonksiyon getmypid için bu arkadaşınız olacak. Her (x) dakika cron çalıştırmak ikinci bir komut, Flatfile denetler projelendirilmiştir yürütme zamanı geçti ne öldürür, isterseniz başka bir dosyaya Flatfile ve hatta günlüklerini temizler.

İyi şanslar ;)

UPDATE:

Bu soruyu hatırladı ve bu yazı için geri geldi. Sebastian Bergmann en github hesabı aracılığıyla karıştırmak ederken php-invoker üzerine tökezledi. Yazarın sözleriyle:

Bir zaman aşımı ile PHP callables çağırmak için yardımcı sınıf.

Geçerli cevap linux tabanlı olmayan portatif kullanım için çok iyi olmasına rağmen çapraz platform çözümü gerekiyorsa, bu çözüm, Windows'un çalışan bu kötü ruhlar için, windows uyumlu olmalıdır. Sayın Bergmann bir PHP tanrı olmak, tamamen script kalitesi için kefil.

EDIT 1

Ben PHP kılavuzunda bu yorum fark ettim:

Please note that, under Linux, sleeping time is ignored, but under Windows, it counts as execution time.

Bildiğim kadarıyla anladığım gibi, uyku bir sistem çağrısı olarak uygulanır ve bu nedenle PHP tarafından göz ardı as described in the manual.

EDIT 2

there is an exec() running instead of sleep() there. and some exec() stuff hangs indefinitely. i am also searching for killing it from within exec (on linux shell), like exec(kill_after15secs myscript.sh), but i can't seem to find that either

Ben şimdi gerçek soruya bakın. Eğer birçok Linux / Unix ortamında çalışıyoruz olduğunu varsayarsak, bu çizgi etrafında bir çözüm bulmak için:

<?php $pid = system( 'sh test.sh >test-out.txt 2>&1 & echo $!' ); ?>

Bu başlamak sürecin süreç kimliği yakalanan ne, sanırım. Sen damgası ile birlikte bir veritabanı veya metin dosyasına giriş yapabilirsiniz. , Diyelim ki, her 5 dakikada bir çalışan başka bir cron komut olarak, 5 dakika önce oluşturulan ve hala yayınlanmadığını kontrol edilen tüm işlem kimlikleri almak:

<?php $status = system( 'ps ' . $pid ); ?>

: Süreç hala çalışıyorsa, siz çıktı iki satır olsun

 PID TTY STAT TIME COMMAND
2044 ?   S    0:29 sh test.sh

Eğer öyleyse, bu gibi feshedebilir:

<?php system( 'kill ' . $pid ); ?>

I creating background processes in PHP (ve daha sonra onları avlamak) hakkında bir makale yazdı. Bütün örnekler oradan kopyalandı.

EDIT 3

Bütün noktalar birbirine bağlanabilir:

<?php
    $pid = system( 'sh test.sh >test-out.txt 2>&1 & echo $!' );
    $timer = 300;
    while( --$timer ) {
        sleep(1);
        $status = system( 'ps ' . $pid );
        $status = explode( "\n", $status, 2 ); // I am not sure, please experiment a bit here
        if ( count( $status ) == 1 || trim( $status[ 1 ] ) == '' ) {
            die( 'spawned process ended successfully' );
        }
    }
    system( 'kill ' . $pid );
    die( 'spawned process was terminated' );
?>