PHP에서 실시간 출력으로 프로세스 실행
웹 페이지에서 실시간으로 출력을 반환하는 프로세스를 실행하려고 합니다.예를 들어 'ping' 프로세스를 실행하면 새로운 행이 반환될 때마다 페이지가 갱신됩니다(현재는 exec(명령어, 출력)을 사용할 때 -c 옵션을 사용해야 하며 프로세스가 완료될 때까지 웹 페이지에서 출력을 볼 수 있습니다).이것을 php로 할 수 있습니까?
또한 누군가가 페이지를 떠날 때 이러한 과정을 멈추는 올바른 방법이 무엇인지 궁금합니다.'ping' 프로세스의 경우 시스템 모니터에서 실행 중인 프로세스를 확인할 수 있습니다(무엇이 말이 되는지).
이 방법은 효과가 있었습니다.
$cmd = "ping 127.0.0.1";
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
flush();
$process = proc_open($cmd, $descriptorspec, $pipes, realpath('./'), array());
echo "<pre>";
if (is_resource($process)) {
while ($s = fgets($pipes[1])) {
print $s;
flush();
}
}
echo "</pre>";
셸 명령어의 실시간 출력을 표시하는 좋은 방법은 다음과 같습니다.
<?php
header("Content-type: text/plain");
// tell php to automatically flush after every output
// including lines of output produced by shell commands
disable_ob();
$command = 'rsync -avz /your/directory1 /your/directory2';
system($command);
출력 버퍼링을 방지하려면 다음 기능이 필요합니다.
function disable_ob() {
// Turn off output buffering
ini_set('output_buffering', 'off');
// Turn off PHP output compression
ini_set('zlib.output_compression', false);
// Implicitly flush the buffer(s)
ini_set('implicit_flush', true);
ob_implicit_flush(true);
// Clear, and turn off output buffering
while (ob_get_level() > 0) {
// Get the curent level
$level = ob_get_level();
// End the buffering
ob_end_clean();
// If the current level has not changed, abort
if (ob_get_level() == $level) break;
}
// Disable apache output buffering/compression
if (function_exists('apache_setenv')) {
apache_setenv('no-gzip', '1');
apache_setenv('dont-vary', '1');
}
}
제가 사용해 본 모든 서버에서 동작하는 것은 아니지만, php 설정에서 무엇을 찾아야 하는지 조언하고 싶습니다.이러한 동작이 서버에서 동작하도록 하기 위해 머리를 뽑아야 하는지 판단하기 위해서입니다.또 아는 사람?
다음은 플레인 PHP의 더미 예시입니다.
<?php
header("Content-type: text/plain");
disable_ob();
for($i=0;$i<10;$i++)
{
echo $i . "\n";
usleep(300000);
}
나는 이것이 검색으로 여기까지 온 다른 사람들에게 도움이 되기를 바란다.
모든 답을 확인했지만 아무 것도 작동하지 않았습니다...
솔루션 검색은 이쪽
윈도우에서 동작합니다(저쪽에서 검색하는 사용자에게 도움이 될 것 같습니다).
<?php
$a = popen('ping www.google.com', 'r');
while($b = fgets($a, 2048)) {
echo $b."<br>\n";
ob_flush();flush();
}
pclose($a);
?>
최신 HTML5 Server Side Events를 사용한 이 오래된 문제에 대한 보다 나은 해결책은 다음과 같습니다.
http://www.w3schools.com/html/html5_serversentevents.asp
예:
http://sink.agiletoolkit.org/realtime/console
코드: https://github.com/atk4/sink/blob/master/admin/page/realtime/console.php#L40
(Agile Toolkit 프레임워크의 모듈로 구현)
명령줄 사용:
function execute($cmd) {
$proc = proc_open($cmd, [['pipe','r'],['pipe','w'],['pipe','w']], $pipes);
while(($line = fgets($pipes[1])) !== false) {
fwrite(STDOUT,$line);
}
while(($line = fgets($pipes[2])) !== false) {
fwrite(STDERR,$line);
}
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
return proc_close($proc);
}
파일을 실행하려는 경우 먼저 실행 권한을 부여해야 할 수 있습니다.
chmod('/path/to/script',0755);
이것을 사용해 보세요(Windows 머신과 wamp 서버에서 테스트 완료).
header('Content-Encoding: none;');
set_time_limit(0);
$handle = popen("<<< Your Shell Command >>>", "r");
if (ob_get_level() == 0)
ob_start();
while(!feof($handle)) {
$buffer = fgets($handle);
$buffer = trim(htmlspecialchars($buffer));
echo $buffer . "<br />";
echo str_pad('', 4096);
ob_flush();
flush();
sleep(1);
}
pclose($handle);
ob_end_flush();
Windows에서 다양한 PHP 실행 명령어를 사용해 본 결과, 많은 차이가 있었습니다.
- 하지 않음:
shell_exec
,exec
,passthru
- 종류 : 업업종종 :
proc_open
,popen
「는, 할 수 없기 때문에 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------my.exe --something
와 같이 할 수 있습니다._my_something.bat
를 참조해 주세요.
최적의 (간단한) 접근법은 다음과 같습니다.
- exe가 명령어를 플러시하고 있는지 확인해야 합니다(프린트 플러시 문제 참조).이것이 없으면, 대부분의 경우, 약 4096 바이트의 텍스트 배지를 받게 됩니다.
- 경우, 「」를 사용해 .
header('Content-Type: text/event-stream');
)header('Content-Type: text/plain; charset=...');
일부 브라우저/클라이언트에서는 동작하지 않습니다.스트리밍은 이 기능이 없어도 작동하지만 적어도 첫 번째 행은 브라우저에 의해 버퍼링됩니다. - , 캐시 「」를 디세블로 할 수도 .
header('Cache-Control: no-cache');
. - hpp. "hpp.ini" 중 ).
ini_set('output_buffering', 'off');
이 작업은 Apache/Nginx 또는 앞에서 사용하는 서버에서도 수행해야 합니다. - 전환(hpp "hpp.ini" 중 )
ini_set('zlib.output_compression', false);
이 작업은 Apache/Nginx 또는 앞에서 사용하는 서버에서도 수행해야 합니다.
따라서 C++ 프로그램에서는 다음과 같은 작업을 수행합니다(다른 솔루션에 대해서는 printflush 문제 참조).
Logger::log(...) {
printf (text);
fflush(stdout);
}
PHP에서는 다음과 같은 작업을 수행합니다.
function setupStreaming() {
// Turn off output buffering
ini_set('output_buffering', 'off');
// Turn off PHP output compression
ini_set('zlib.output_compression', false);
// Disable Apache output buffering/compression
if (function_exists('apache_setenv')) {
apache_setenv('no-gzip', '1');
apache_setenv('dont-vary', '1');
}
}
function runStreamingCommand($cmd){
echo "\nrunning $cmd\n";
system($cmd);
}
...
setupStreaming();
runStreamingCommand($cmd);
먼저 flush()가 자신에게 적합한지 확인합니다.정상적으로 동작하고 있는 경우는, 예를 들면 mod_gzip이 유효하게 되어 있는 경우 등, 어떠한 이유로 Web 서버가 버퍼링 되고 있는 것을 의미합니다.
ping 등의 경우 가장 쉬운 방법은 PHP 내에서 루프를 실행하여 "ping -c 1"을 여러 번 실행하고 각 출력 후에 flush()를 호출하는 것입니다.사용자가 HTTP 연결을 닫았을 때 PHP를 중단하도록 설정했다고 가정하면(일반적으로 기본값이거나 확인을 위해 ignore_user_abort(false)를 호출할 수 있습니다), 실행 ping 프로세스에 대해서도 걱정할 필요가 없습니다.
자프로세스를 1회만 실행하여 출력을 연속적으로 표시해야 하는 경우, 백그라운드에서 실행하고 출력을 스트림으로 리다이렉트한 후 일반 flush() 호출을 사용하여 사용자에게 스트림백하는 PHP 에코가 필요할 수 있습니다.
PHP를 통해 시스템 명령을 실행하는 경우 exec 문서를 참조하십시오.
그러나 트래픽량이 많은 사이트에서는 이 작업을 권장하지 않습니다.요청마다 프로세스를 포킹하는 것은 매우 큰 작업입니다.일부 프로그램에서는 프로세스 ID를 파일에 쓰는 옵션을 제공하여 사용자가 원하는 대로 프로세스를 확인하고 종료할 수 있도록 하지만 ping과 같은 명령어는 man 페이지를 확인하십시오.
리모트 호스트상에서 리슨 하고 있는 포토(HTTP 의 경우는 포토 80)의 소켓을 여는 것만으로, 유저랜드나 네트워크상에서 모든 것이 정상적으로 동작하고 있는 것을 알 수 있기 때문에, 보다 나은 서비스를 제공할 수 있습니다.
바이너리 데이터를 출력하려고 하면 php의 헤더 함수를 살펴보고 적절한 content-type과 content-disposition을 설정했는지 확인합니다.출력 버퍼의 사용/비활성화에 대한 자세한 내용은 설명서를 참조하십시오.
php.ini 파일 세트 "output_dispering = Off"를 변경해 보십시오.exec 대신 시스템명령어 사용 페이지에서 실시간 출력을 얻을 수 있습니다.system 명령어는 출력을 플러시합니다.
출력을 로그 파일로 파이핑한 다음 해당 파일을 사용하여 클라이언트에 내용을 반환하는 것이 좋습니다.꽤 실시간은 아니지만 충분히 좋을까?
Symfony Process Components(https://symfony.com/doc/current/components/process.html)를 사용해야만 동일한 문제가 발생하였습니다.
간단한 예:
<?php
use Symfony\Component\Process\Process;
$process = new Process(['ls', '-lsa']);
$process->run(function ($type, $buffer) {
if (Process::ERR === $type) {
echo 'ERR > '.$buffer;
} else {
echo 'OUT > '.$buffer;
}
});
?>
언급URL : https://stackoverflow.com/questions/1281140/run-process-with-realtime-output-in-php
'it-source' 카테고리의 다른 글
완전한 mysql mysqldump 파일에서 단일 테이블을 복원할 수 있습니까? (0) | 2022.10.20 |
---|---|
"198.1994.Out Of Memory Error : 새 네이티브 스레드를 만들 수 없습니다." (0) | 2022.10.20 |
Java 프로젝트의 패키지 구조? (0) | 2022.10.20 |
JavaScript에서의 MD5 구현 속도 향상 (0) | 2022.10.20 |
Java에서 UUID의 최상위 비트를 사용한 충돌 가능성 (0) | 2022.10.20 |