2010-12-07 3 views
6

이전에 서버에 업로드 한 JFFS2 이미지의 파일 이름을 사용하기위한 PHP 스크립트 웹 페이지를 코딩하고 있습니다. 스크립트는 이미지를 사용하여 서버의 파티션을 다시 플래시하고 결과를 출력합니다. 나는 이것을 사용했다 :명령 실행으로 shell_exec 명령의 출력을 얻으십시오.

$tmp = shell_exec("update_flash -v " . $filename . " 4 2>&1"); 
echo '<h3>' . $tmp . '</h3>'; 

echo verifyResults($tmp); 

합니다 (verifyResults 기능이 업데이트 명령이 성공적으로 완료 여부를 사용자에게 표시 일부 HTML을 반환합니다 즉, 업데이트가 성공적으로 완료 될 경우, 표시 버튼을을 다시 시작합니다. 장치 등)

이 문제는 업데이트 명령이 완료되는 데 몇 분이 걸리고 PHP 스크립트가 셸 명령이 완료 될 때까지 차단되어 출력을 반환합니다. 이는 일반적으로 사용자가 HTTP 504 오류 (최악의 경우)를 보거나 페이지가 몇 분 동안로드 될 때까지 기다리는 동안 update 명령이 계속 실행됨을 의미합니다.

나는이 대신 같은 일을 생각했다 :

shell_exec("rm /tmp/output.txt"); 
shell_exec("update_flash -v " . $filename . " 4 2>&1 >> /tmp/output.txt &"); 
echo '<div id="output"></div>'; 
echo '<div id="results"></div>'; 

이 이론적 백그라운드에서 명령을 넣고 /tmp/output.txt 모든 출력을 추가합니다.

그리고 나서 Javascript 함수에서 주기적으로 getOutput.php를 요청합니다. getOutput.php는 단순히 /tmp/output.txt의 내용을 출력하고 "output"div에 저장합니다. 명령이 완전히 완료되면 다른 JavaScript 함수가 출력을 처리하고 "결과"div에 결과를 표시합니다.

하지만 여기서 볼 수있는 문제는 업데이트 대상으로 지정된 파티션에 있기 때문에 장치의 플래시 메모리 업데이트 프로세스 중에 getOutput.php가 결국 액세스 할 수 없게된다는 것입니다. 따라서 504와 같은 영원히로드 된 페이지가 아니더라도 이전과 같은 위치에 나를 남겨 둘 수 있습니다.

장치의 다른 파티션으로 getOutput.php를 이동할 수 있지만 웹 서버 구성에서 웹 서버 구성에 액세스 할 수있는 펑키 물건을 필요로한다고 생각합니다. 다른 파일과 마찬가지로 나중에 다시 플래시하는 동안 덮어 씁니다.)

실행되는 명령의 출력을 표시하는 다른 방법이 있습니까? 아니면 내가 갖고있는 솔루션으로해야합니까?

편집 1 : 현재 몇 가지 해결책을 테스트 중입니다. 나중에 결과로 내 질문을 업데이트하겠습니다.

편집 2 : 내가 원래 생각한 것처럼 파일 시스템이 덮어 쓰이지 않는 것 같습니다. 대신, 시스템은 기존의 파일 시스템을 읽기 전용 모드로 마운트하는 것처럼 보이기 때문에 파일 시스템이 다시 플래시 된 후에도 getOutput.php에 계속 액세스 할 수 있습니다.

내 질문에 설명 된 두 번째 솔루션은 shell_exec 대신 popen (아래 답변에서 언급 한)을 사용하는 것 외에 작동하는 것 같습니다. 페이지가로드되고 Ajax를 통해 output.txt의 내용을 표시 할 수 있습니다.

그러나, 경우 output.txt 그것을 실행에서 업데이트 명령이 리턴 될 때까지 아무 것도 표시하지 않을 것 같다 실시간으로 ..에 재 플래시 명령의 출력을 반영하지 않는 것 같다. 나는 여기서 무슨 일이 일어나는지 더 많은 테스트를해야 할 것입니다.

편집 3 : 나는 액세스로는 신경 쓰지 마,이 파일 처럼 보인다는 전류이다. 커널이 소스 JFFS2 이미지가 저장된 파티션을 사용하여 트리거 된 JFFS2 관련 작업을 수행하는 동안 지연이 발생했습니다. 왜 그런지는 모르겠지만 모든 PHP 스크립트가 끝날 때까지 차단됩니다.

이 문제를 해결하려면 업데이트 명령 호출을 별도의 스크립트에 넣고 Ajax를 통해 요청하십시오. 그런 식으로하면 기술적으로 아직 시스템에서 기다리는 동안 사용자는 최소한 미리 패키지 된 피드백을 받게됩니다. 는 popen에서

답변

3
+0

popen은 PHP가 원하는대로 차단하지 못하는 것 같지만, 내 명령이 내 출력 파일을 즉시 업데이트하지 않습니다. 자세한 내용은 내 질문 2를 참조하십시오. –

+0

괜찮아, popen이 예상대로 작동했다. –

1

재미있는 시나리오.

내 첫 번째 생각은 proc_ * 및 $ _SESSION과 관련하여 뭔가를하는 것이었지만 작동 여부는 확실하지 않았습니다. 시도해 보라. 그렇지 않다면 ...

프로세스 중에 플래시되는 것에 대해 걱정이된다면, 보조 프로세스에서 항상 mysql 데이터베이스를 인스턴스화하고 그것에 쓸 수있다. 데이터베이스는 다른 파티션에 존재할 수 있으며 로컬 IP로 주소 지정할 수 있으며 시스템이 라우팅을 처리합니다.

$_SESSION = array(
    1 => array("pipe", "w"), 
); 

내가 가지 의심 작동하지만 :

편집 내가 세션을 proc_ *을 언급

때, 나는 $의 descriptorspec이 될 것 this 비슷한 의미. 이 프로세스는 첫 번째 스크립트가 종료되면 더 이상 존재하지 않는 $ _SESSION 메모리에 기록을 마칩니다.

편집 2

사실, 그 주에, 당신은 memcache를 설치하고 보조 프로세스는 다음 웹 인터페이스 프로세스에 의해 다시 읽을 수있는 메모리에 직접 쓰도록 할 수있다.

+0

그것은 가벼운 임베디드 리눅스 시스템이기 때문에, 비록 내가 바이너리를 가지고 있더라도, mysql 구현을위한 저장 공간을 가질 여유가 없다고 생각한다 : ( –

1

DocRoot를 지우면이 시간 동안 사용자의 요청에 응답 할 수있는 리소스/스크립트가 없습니다. 따라서 삭제 요청과 동일한 요청으로 사용자에게 업데이트를 보내야합니다. 이를 위해서는 쉘 프로세스를 시작하고 즉시 PHP로 돌아 가야합니다. 이는 pcntl_fork()pcntl_exec()으로 수행 할 수 있습니다. PHP 스크립트는 이제 쉘 스크립트의 출력을 클라이언트에 계속 보내야합니다. 쉘 스크립트가/tmp에있는 파일에 추가되면, 쉘 스크립트가 끝날 때까지 fpassthru() 파일을 지우고 지울 수 있습니다. 에 관한

1

당신의 그러나 :

내 생각 엔 당신이 스트림의 파일을 사용하려고합니다. 어떤 프로덕션 테스트도하지 않았지만 파일이 fclose()의 디스크에만 다시 기록됩니다.

스크립트 # 2에서 계속해서 파일에 쓰는 경우 파일을 닫을 때까지 해당 쓰기가 실제로 메모리로 직접 이동합니다.

다시 말해서 확인할 수는 없지만 테스트하려면 모든 쓰기 작업마다 파일을 다시 열고 닫으십시오.이것은 내 이론을 확인하거나 거절 할 것이므로 그에 따른 접근 방식을 수정할 수 있습니다.

+0

두 번째 스크립트는 파일을 읽고 내용을 출력한다; ("update_flash -v". $ filename. "4 2> & 1 >> /tmp/output.txt") –

+1

아, 죄송합니다. . 어떤 이유로 든 두 개의 PHP 스크립트를 사용하고 있다는 것을 머리 속에 떠 올렸습니다. 파일 잠금과 충돌이 발생할 가능성이 있습니까? – Craige

+0

흠, 그럴 수도 있습니다. PHP의 fopen과 같은 방식으로 동작합니다. –

관련 문제