다른 프로그램을 실행시켜 출력내용 읽기

전종필

다른 프로그램을 실행시키고 그 출력 내용을 읽는 방법은 여러가지가 있습니다.
많은 분들이 알고 계시지만, 몇몇 모르시는 분들을 위해 여기 그 방법들을 소개합니다.

Backtick

역따옴표(`...`)는 그 안에 들어있는 내용을 shell을 통해 실행하고, 표준출력(STDOUT)으로 출력되는 내용을 반환합니다. 따라서,


$content = `cat /etc/passwd`;
는 passwd 파일을 간단히 읽어들입니다.
물론, 단순한 파일을 읽는데는 직접 open을 해서 읽어들이는 것이 좋습니다. 역따옴표를 사용하게 되면, 그 내부의 프로그램을 실행하기 위해서 별도의 프로세스가 생성되어야 하기 때문에 그만큼 시스템의 자원을 소모하게됩니다.

open 함수를 이용하는 방법

open 함수에서 파일이름분에 > 대신 | (파이프)기호를 뒤에 붙이면 해당 파일이름을 실행시키고 그 출력내용을 읽을 수 있습니다.


#!/usr/bin/perl
# prog.pl
print "$$\n";
warn "Exiting\n";


#!/usr/bin/perl
# opener.pl
$p = open(RUN, "./prog.pl |") || die $!; # ./prog.pl 뒤에 | 표시.
@out = <RUN>;
close RUN; # 반드시 하십시오.

print "opener: $p\n";
print map { "opener: $_" } @out;
opener.pl에서 prog.pl을 "./prog.pl |"와 같이 하여 열었습니다.(open)
그 후 일반 파일 읽기에서 하는 것처럼 <RUN>를 이용하여 출력내용을 읽습니다.
참고로, open 함수가 반환하는 것은, 프로그램이 제대로 실행되었을 때, 새로운 프로세스의 프로세스 아이디입니다.
만일 이 프로그램이 오랜시간동안 살아 있는 것(웹서버처럼)이라면 close를 하지 않을 경우 문제가 될 수 있습니다. 예를 들어, open은 계속해야 하는데, close를 해 주지 않는다면, 해당 프로세스가 죽지않고 계속 남아서 시스템자원을 차지하고 있어서 결국 시스템이 멈추는 상황이 발생할 수도 있게됩니다.
따라서 반드시 close를 해 주어야 합니다.

만일 표준에러(STDERR)까지 같이 읽어야 한다면


#!/usr/bin/perl
# prog.pl
print "$$\n";
warn "Exiting\n";


#!/usr/bin/perl
# opener.pl
$p = open(RUN, "./prog.pl 2>&1 |") || die $!; # ./prog.pl 뒤에 | 표시.
@out = <RUN>;
close RUN; # 반드시 하십시오.

print "opener: $p\n";
print map { "opener: $_" } @out;
와 같이 2>&1를 추가합니다. 
Comments