Мне нужно выполнить копирование каталогов после некоторого действия пользователя, но каталоги довольно большие, поэтому я хотел бы иметь возможность выполнить эту операцию, не зная, сколько времени потребуется для завершения копирования. Как решить данную задачу?
Ответ 1
Предполагая, что вы работаете в среде Linux, можно поступить следующим образом:
exec(sprintf("%s > %s 2>&1 & echo $! >> %s", $cmd, $outputfile, $pidfile));
Команда $cmd перенаправляет вывод команды $outputfile и записывает идентификатор процесса в $pidfile.
Это позволяет вам легко отслеживать, что делает процесс и работает ли он.
function isRunning($pid){
try{
$result = shell_exec(sprintf("ps %d", $pid));
if( count(preg_split("/\n/", $result)) > 2){
return true;
}
}catch(Exception $e){}
return false;
}
Ответ 2
Можно попробовать эту команду:
>/dev/null 2>/dev/null &
Например, так:
shell_exec('service named reload >/dev/null 2>/dev/null &');
Ответ 3
Простой пример для этой функции в Windows:
Создайте следующие два файла и сохраните их в веб-каталоге:
foreground.php:
<?php
ini_set("display_errors",1);
error_reporting(E_ALL);
echo "<pre>загрузка страницы</pre>";
function run_background_process() {
file_put_contents("testprocesses.php","время запуска1 = " . time() . "\n");
echo "<pre> время запуска1 = ".time()."</pre>";
// вывод команды должен быть перенаправлен в файл или другой поток вывода
// http://ca.php.net/manual/en/function.exec.php
exec("php background.php > testoutput.php 2>&1 & echo $!", $output);
echo "<pre>время завершения1 = " . time() . "</pre>";
file_put_contents("testprocesses.php","время завершения1 = ".time()."\n", FILE_APPEND);
return $output;
}
echo "<pre>вызов фонового процесса</pre>";
$output = run_background_process();
echo "<pre>output = "; print_r($output); echo "</pre>";
echo "<pre>end of page</pre>";
?>
background.php:
<?
file_put_contents("testprocesses.php","время запуска2 = " . time() . "\n", FILE_APPEND);
sleep(10);
file_put_contents("testprocesses.php","время завершения2 = " . time() . "\n", FILE_APPEND);
?>
Дайте IUSR разрешение на запись в каталог, в котором вы создали указанные выше файлы.
Выполните следующую последовательность команд:
loading page
calling run_background_process
время запуска1 = 1266003600
время заврешения1 = 1266003600
output = Array (
[0] => 15010
)
end of page
Вы должны получить testoutput.php в том же каталоге, в котором были сохранены указанные выше файлы, и он должен быть пустым.
Вывод будет подобным такому:
Время запуска1 = 1266003600
Время завершения1 = 1266003600
Время запуска2 = 1266003600
Время завершения2 = 1266003610
Ответ 4
Если вам нужно просто сделать что-то в фоновом режиме, не дожидаясь завершения PHP операции, вы можете использовать фоновый PHP-скрипт, который "вызывается" командой wget. Этот фоновый сценарий PHP будет выполняться с привилегиями, конечно же, как и любой другой сценарий PHP в вашей системе.
Вот пример использования wget в Windows из пакетов gnuwin32.
Фоновый код (файл test-proc-bg.php) в качестве примера:
sleep(5); // задержка
file_put_contents('test.txt', date('Y-m-d/H:i:s.u')); // запись в файл
Скрипт, вызывающий фоновый процесс:
$proc_command = "wget.exe http://localhost/test-proc-bg.php -q -O - -b";
$proc = popen($proc_command, "r");
pclose($proc);
Необходимо использовать popen/pclose, чтобы это работало правильно.
Параметры wget:
-q - активный режим.
-O - вывод в stdout.
-b - фоновый режим.
Web