2013-08-07 4 views
6

Я полностью не нашел ответа на этот вопрос. Надеюсь, кто-то здесь может помочь.Не запускайте скрипт, если он уже запущен

У меня есть PHP-скрипт (конкретный шаблон WordPress), который автоматически импортирует и обрабатывает изображения, когда пользователь нажимает на него. Проблема в том, что обработка изображений занимает много памяти, особенно если несколько пользователей одновременно обращаются к шаблону и начинают обработку изображения. Из-за этого мой сервер разбился несколько раз.

Моим решением было не выполнять функцию обработки изображений, если она уже запущена. Перед запуском функции я проверил бы запись базы данных с именем image_import_running, чтобы узнать, установлено ли значение false. Если бы это было так, функция затем выполнялась. Самое первое, что сделала функция, было установлено как image_import_running в true. Затем, после того, как все было закончено, я вернул его в false.

Он отлично работал - теоретически. С тех пор сайт не разбился, я могу вам это сказать. Но есть две основные проблемы, связанные с ней:

  1. Если пользователь закрывает страницу, пока она загружается, скрипт никогда не заканчивает обработку изображения, и поэтому никогда не устанавливает image_import_running назад к ложным. Шаблон никогда не будет обрабатывать изображения снова, пока он не будет вручную установлен на false.

  2. Если сценарий не работает во время обработки изображений - и это сильная возможность, если в очереди много изображений - у вас по существу та же проблема, что и № 1: сценарий никогда не доходит до точки, где он возвращает image_import_running значение false.

Для обработки № 1 (первый из двух проблем, я понял), я добавил ignore_user_abort(true) в сценарий. Это сработало? Я не знаю, потому что № 2 по-прежнему остается проблемой. Вот где я в тупике.

Если бы я мог попросить сервер был запущен ли скрипт или нет, я мог бы сделать что-то вроде этого:

if($import_running && $script_not_running) { 
    $import_running = false; 
} 

Но как я установил, что $script_not_running переменных? Ударь меня.

Я рассказал вам всю эту историю на всякий случай, если у вас есть другое блестящее решение.

+1

Не делайте этого на странице просмотра. Сделайте это заранее или используйте работу cron. – GolezTrol

+2

Исправить заболевание не является симптомом –

+1

Как и другие, было бы лучше перенести обработку изображения из самого запроса. В качестве промежуточного «исправления» храните временную метку рядом с «image_import_running», когда начинается задание обработки (например, 'image_import_commenced'). Это очень грубый механизм, но если вы знаете максимальное время выполнения задания до тайм-аута, скрипт может проверить, прошел ли этот период времени (например, если «image_import_running» по-прежнему истинно, но текущее время больше, чем Через 10 минут после 'image_import_commenced' запустите обработку в любом случае). – plasmid87

ответ

1

Попытайтесь использовать ignore_user_abort(true);, он будет продолжать работать, даже если человек уходит и закрывает браузер.

вы также можете поставить номер вместо True False в записи БД и установить максимальное число процессов, которые могут работать вместе

+1

Это хорошая идея, но это зависит от того, какой интерфейс CGI используется веб-сервером. Многие реализации имеют «жесткий тайм-аут», который нельзя переопределить с помощью 'ignore_user_abort (true)'; этот процесс будет принудительно убит после истечения периода ожидания. – plasmid87

1

Как и другие предложили, было бы лучше, чтобы переместить обработку изображения из самого запроса.

В качестве промежуточного «исправления» храните временную метку рядом с image_import_running, когда начинается работа по обработке (например, image_import_commenced). Это очень грубый механизм, но если вы знаете максимальное время выполнения задания до истечения времени ожидания, скрипт может проверить, прошел ли этот период времени.

например, если image_import_running по-прежнему является истинным, но текущее время более 10 минут с image_import_commenced, выполните обработку в любом случае.

1

Для меня я использую только эту простую идею с текстовым документом. например run.txt файл
в использовании верхнего сценария:

if((file_get_contents('run.txt') != 'run'){ // here the script will work 
$file = fopen('run.txt', 'w+'); 
fwrite($file, 'run'); 
fclose('run.txt'); 
}else{ 
exit(); // if it find 'run' in run.txt the script will stop 
} 

и добавить в конец файла сценария

$file = fopen('run.txt', 'w+'); 
fwrite($file, ''); //will delete run word for the next try ;) 
fclose('run.txt'); 

Это будет проверять, если скрипт уже работает, проверив runt.txt содержимое
если пробег слово существует в run.txt он не будет работать

1

Запуск cron будет окончательно быть лучшим решением. Идея хранить URL-адрес в таблице - хорошая.

Чтобы ответить на исходный вопрос, вы можете запустить команду ps auxwww с помощью exec (Проверить эту страницу: How to get list of running php scripts using PHP exec()?) и переместить вашу функцию в отдельный файл php.

exec("ps auxwww|grep myfunction.php|grep -v grep", $output); 
1

Что касается установки переходного процесса с истечением срока годности, который будет дросселировать операцию?

if(!get_transient('import_running')) { 
    set_transient('import_running', true, 30); // set a 30 second transient on the import. 
    run_the_import_function(); 
} 
1

Я предпочел бы сохранить работу в базу данных слабеющей ее в ожидании и установите хроны для выполнения обработки одного задания одновременно.

0

Просто добавьте следующий текст в начало вашего скрипта.

<?php 
    // Ensures single instance of script run at a time. 
    $fileName = basename(__FILE__); 
    $output = shell_exec("ps -ef | grep -v grep | grep $fileName | wc -l"); 
    //echo $output; 
    if ($output > 2) 
    { 
     echo "Already running - $fileName\n"; 
     exit; 
    } 

    // Your php script code. 
?> 
Смежные вопросы