Erlang

Erlang 외부 프로세스 실행

메롱씨티 배드맨 2012. 4. 20. 18:38

Web Server는 기존 HTML 파일과 같은 이미 Fixed 된 파일을 열어 전달하는 역할도 하지만,

PHP, JSP, ASP와 같은 서버사이드 스크립트를 실행하여 그 결과물을 전달하는 기능도 필수적으로 있어야 한다.


일단은 PHP, JSP, ASP와 같은 별도의 모듈을 설치해야 하는 부분은 제외하고 CGI로 구동되는 기능만을 개발하기로 한다.






1. Web Server의 요청중 .cgi 로의 요청은 외부 프로세스 실행 루틴을 타도록 한다.

2. 외부 프로세스 실행시 실행 Path + filename을 넘기고, Request Method와 Query String을 넘긴다.

    ( 이외에 더 많은 서버 상수들이 있겠지만, 일단 이렇게만 넘기기로 한다. )

3. 프로세스 실행 파이프 라인 모듈은 Pork 를 통해 프로세스를 실행시키고 pipe라인을 통해 출력값을 캡춰한다.

4. 캡춰된 출력값은 다시 파이프 라인 모듈을 통해 Web Server로 Write 한다.

5. 수신 받은 내용을 Web Server 는 Response 로 Client에게 전달한다.


여기서는 크게 세부분의 소스 코드가 등장한다.


첫째, Web server에서 외부 프로세스를 실행하고 결과값을 받기 위한 부분

둘째, Web server로 부터 실행 요청을 수신하고 외부 프로세스를 실행하고 결과값을 다시 전달하는 부분 ( C code로 작성한다. )

세째, 실제 실행된 외부 CGI (이 부분은 실제 구현에서는 필요없는 부분이지만, 테스트를 위해 작성했다 ( Perl 로 작성한다. ))



Web Server에서 외부 프로세스를 실행할 모듈의 소스 코드이다.





지난번 리스트 형 변수의 소스코드와 전체적인 모습은 비슷한다.

외부 프로세스를 실제 수행할 파이프 라인 모듈(C Code로 작성된.) 의 이름은 exec3 이다. 

이 프로세스를 등록하고 open_port를 통해 프로세스를 실행한다.

os:cmd() 함수가 외부 프로세스를 실행하는 가장 간단한 방법이지만, 이 함수는 실행 후 결과값을 리턴 받을수가 없었다.


start 하면 exec3 를 실행하여 이 프로세스와 연결을 유지한 상태가 된다.

loop함수에는 외부 프로세스의 리턴값을 감시할 수 있도록 무한 루프 상태가 된다.


execCall 함수는 외부 프로세스에게 무엇을 실행할지를 알려주는 메세지를 전달할 외부 I/F 함수이다.

execCall함수를 통해 실제 구동시킬 외부 프로세스 정보를 exec3에게 전달한다.



다음은 외부 프로세스 모듈을 실제로 수행할 프로세스 코드이다 ( C source )





while 루프에서 표준출력 0 번에서 계속 read하고 있다.

read 한 데이터는 exeCmd 함수를 통해 외부 프로세스를 실행하게 되고, retStr 에 결과값을 받아오게 한다.

전달받은 retStr 데이터는 write_cmd 함수를 통해 웹서버 모듈에 다시 전달한다.


다음은 실제로 외부 프로세스를 실행할 exeCmd 함수 코드이다.



exeCmd 함수는 실행할 외부 프로세스 정보를 cmd 로 받는다 (cmd는 const char 이다.)

cmd에는 스페이스로 구분되어 정보를 받게 되는데, 첫번째 정보는 filepath, 두번째 정보는 request method, 세번째 정보는 query string 이다.

strtok_r 함수를 통해 데이터를 parsing 하여 filename과 arg, env 에 각각 정보를 저장한다.





이후 프로세스를 pork 하여 띄운후 새로 띄운 프로세스를 pipe로 연결한 후 execve 함수에 이전에 만들었던 정보와 함게 외부 프로세스를 실행한다.

이후 프로세스 실행이 끝난후 이 프로세스의 출력값을 read로 통해 읽어들인다.

읽은 데이터는 retStr에 복사하여 전달한다.


다음은 테스트용으로 만든 외부 실행 프로세스이다 ( Perl code )



이 Perl CGI는 REQUEST_METHOD와 QUERY_STRING을 받아서 처리한다.

우리는 앞서 프로세스에서 filename 과 REQUEST_METHOD, QUERY_STRING을 넘기도록 했다.

이렇게 전달받은 Parameter를 HTML코드에 넣어 반환한다.


다음은 실제 실행 화면이다.





exec1:start() 로 모듈을 시작한다. ( 이 부분은 차후 웹서버 자체에 내장하도록 한다. )

exec1:execCall("./test1.cgi GET name=iks&family=jin"). 로 프로세스를 실행한다.

execCall 함수의 파라미터에 filename REQUEST_METHOD QUERY_STRING을 스페이스를 기준으로 한 문자으로 넣었다.


다음은 외부 프로세스에서 실행시 로그 화면이다.




맨 첫 라인이 받은 파라미터이며,

두번째 라인 이후의 arg, env 가 외부 프로세스에 넘길 환경정보이다.

read buf 이후는 외부 프로세스의 리턴값이다.