[php] PHP에서의 외부 프로그램 실행과 개념
주로 사용되는 함수
system, exec
passthru외부 프로그램을 실행하기위해 3개의 함수가 준비되어 있습니다.
세 함수의 서로 다른 점은 리턴되는 값입니다. system 함수는 프로그램
실행결과를 문자열로 되돌려 줍니다. exec는 프로그램을 실행결과를
마지막 한줄로 마찬가지로 문자열로 되돌려줍니다. passthru는 프로그램
실행 결과를 있는 그대로의 바이너리 데이터로 되돌려줍니다.
다시 말해서 실행결과가 필요한 경우는 exec, 텍스트를 출력하는 프로그램
실행 결과가 모두 필요한 경우에는 system, 바이너리를 출력할 실향결과가
필요한 경우에는 passthru를 사용하면 됩니다.
또 backtick연산자라는 기강이 준비되어 있는데 거의 system과 동등한
기강입니다(system에서는 프로그램 종료 스테이터스를 얻을 수가 있지만
backtick 연산자에서는그럴 수가 없습니다.). 백쿼터(`)로 둘러싼 내용을
쉘에 넘겨 실행시키고 출력 결과를 되돌려줍니다.
backtick 연산자 사용예
1: $str = `/bin/ls -l /tmp`;
이라는 형식으로 ls 결과값이 $str에 들어갑니다.
####주의점(시쿠린놈관련)####
system등의 외부 프로그램관수를 사용하는 스크립을 작성할때 주의
하지 않으면 안되는 점이 있습니다. 예를 들어 폼에서 받아 들인 값의
일부가 system등에 외부 프로그램의 인수의 일부로 건네줄 경우 간단히
임의의 명령 (rm 이나 cat /etc/passwd 등의 위험한 코맨드)를 발행하여
실행 시킬 수가 있습니다.
예를 들어 $fFilename 라는 변수의 폼에서 건네준 값이라고 하고
1: $str = system(“/bin/ls /tmp/$fFilename”);
라는 스크립이 실행 되었을 경우 $fFilename 에 [; /bin/rm -rf /] 라고
기술하면 쉘에 대하여 [/bin/ls /tmp/; /bin/rm -rf /]라는 명령을 건네
줍니다. [;]는 코맨드 구분자로 인식이 되어 ls 도 rm 도 실행이 되는
것입니다.
이런 문제점을 방지하기위해 escapeshellcmd 라는 함수가 준비 되어
있습니다. [;]를 포함한 쉘에 대하여 특별한 의미를 가진 문자를
에스케이프해서 출력 해줍니다.
이함수를 사용하여
1: $fFilename = escapeshellcmd($fFilename);
2: $str = system(“/bin/ls /tmp/$fFilename”);
와같이 해주면 먼저 프로그램은 (다소) 안전해집니다.
시간이 걸리는 프로그램을 백그라운드에서 실행
시간이 걸리는 처리(대량 메일 송신이나 데이터 베이스 전체 삭제등)를
브라우저에서 실향하고 싶을 때나 필요성이 있을 겁니다. 그럴 경우에
일반적인 방법으로 처리하면 이 처리가 종료될 때까지 유저가 브라우저를
사용할 수 없게 됩니다(IE 의 지구마크가 계속 돌아가는 상태).
이 때에는 유저가 브라우저에 대하여 어떤 조작을 하였을 경우의 작동에
대해서 보장이 되지 않습니다. 또, 일정한 시간이 경과하면 접속(런)
타임아웃이 되는 경우가 있습니다.
이러한 상태를 피하기 위해 브라우저를 바로 풀어주고 시간이 걸리는
처리는 백그라운드에서 처리(뒷구멍에서 호박씨까기 상태)해주는 방법이
필요하게 됩니다. 주로 대량 메일을 송신하는 경우에 많이 사용되리라고
생각됩니다.
Perl 에서는 fork 함수를 사용해서 같은 프로그램안에 백그라운드에서
처리할 부분을 기술할 수 있지만 PHP 의 경우에는 fork 함수가 없으므로
백그라운드처리하게 할때 먼저 별도의 프로그램을 만들어 놓고, system
함수 혹은 exec 함수를 불러내는 형식이 됩니다. 당연한 이야기 이지만
백그라운드에서 처리된 결과를 얻는 것은 불가능합니다(메인 처리는
백그라운드 처리 전에 먼저 종료 되었기 때문에). 그래서 결과적으로
exec 를 사용해도 system 을 사용해도 똑 같은 결과가 됩니다.
system 함수나 exec 함수의 리퍼런스를 보면 다음과 같은 내용이 있습니다.
(이 함수를 사용하여 프로그램실행을 해서 백그라운드에서 실행한 상태로
두고 싶을 때에는 프로그램의 출력을 파일 혹은 다른 출력 스트림에
리다이렉트해줄 필요가 있는 점에도 추의해야 됩니다. 그렇지 않으면
PHP는 그 프로그램의 실행이 종료될 때까지 풀어주지 않고 붙들고 있을
것입니다(Hang).)
이 문장의 의미는 다음과 같이 기술하라는 의미입니다.
system(“/home/your/bgprog $arg1 $arg2 > /dev/null &”);
여기에서 bgprog 은 백그라운드에서 실행하고자 하는 프로그램입니다.
어떤 언어로 기술되어도 상관이 없습니다. 혹은 위의 예와 같이 메인
처리에서 인수를 건네 주고 싶은 경우에는 bgprog 쪽에서 정확하게 받아
처리할 수 있도록 해주지 않으면 안됩니다.
[> /dev/null] 가 [리다이렉트] 에 해당하는 기술입니다. /dev/null
라고 하는 것은 [쓰레기통] 으로 생각하면 됩니다. 모든 출력결과를
버립니다. 마지막의 & 는 백그라운드에서 실행을 하라는 의미입니다.
이 주변의 자세한 내용은 UNIX 쉘 관련 참고서를 보면 있습니다.
[PHP는 그 프로그램이 종료 될때까지 Hang됩니다] 라는 의미는 IE 의
지구 마크가 게속 돌고 있는 상태를 의미합니다.
그럼 실험을 해보겠습니다. 브라우저의 상태에 주의해서 봅시다.
bgprog 에 해당하는 프로그램을 다음과 같은 내용으로 만들어 보겠습니다.
간단히 수면제 멱여서 10 초동안 잠재우는 프로그램입니다.
여기에서는 쉘스크립으로 만들겠습니다.
sleep.sh
sleep 10
다음은 위의 프로그램을 불러낼 PHP 스크립을 만들겠습니다.
<?
system(“/bin/sh /home/your/sleep.sh > /dev/null &”);
echo “OK.”;
?>
위의 페이지를 출력하면 순간적으로 OK 가 출력이 됩니다.
10초 이내에 ps 코맨드를 확인하면 OK가 출력이 된후에도
sleep.sh 가 실행이 되고 있는 상태가 됩니다.
그럼 아래와 같이 일반적인 방법으로 변경하면 어떻게 될까요?
<?
system(“/bin/sh /home/your/sleep.sh &”);
echo “OK.”;
?>
10초가 지난 후에 OK가 출력이 될 것입니다.
그 동안에 브라우저는 목빠지게 처리 결과를 기다리고 있는
상태로 있다는 것을 확인 할 수 있을 겁니다.
4 Responses
3predicted
3absolution
… [Trackback]
[…] Information on that Topic: nblog.syszone.co.kr/archives/2609 […]
… [Trackback]
[…] Here you will find 8429 additional Info to that Topic: nblog.syszone.co.kr/archives/2609 […]