4 번째 수정본 소스 보기 : Perl/System
마지막으로 [b]
-- Loading page list... --
내용출력
로그인[l]
Diary
[f]
최근변경내역
[r]
페이지목록[i]
횡설수설[2]
게시판[3]
링크
수정할 수 없습니다: Perl/System 는 읽기 전용 페이지입니다.
== # 번역: 펄의 system() 함수 사용하기 ( Using the Perl system() function ) == (원문: [http://gssg-www.stanford.edu/public/systemfunction.html Using the Perl system() function]) 여러 매뉴얼들에서 펄의 system() 함수를 조금씩 다르게 설명하며, 중요한 부분을 빼먹곤 한다. 이 글은 내가 직접 펄 system() 함수를 문서화하고 추가로 몇 가지 용례와 잘못된 사용 예를 추가하려고 만들었다. === # system() 기초 === system() 함수는 자식 프로세스를 생성하고(fork) 운영 체제 명령문을 실행한 후, 자식 프로세스가 완료될 때까지 대기하고, 일종의 자식 프로세스 종료 상태값을 반환하여 여러분이 검사할 수 있도록 한다. system() 함수의 인자는 세 가지 형태로 주어질 수 있다 (괄호는 생략 가능하다): {{{ 1. system($STRING); 2. system($PROGRAM, @ARGUMENT_LIST); 3. system { $PROGRAM } $FAUX_PROGRAM, @ARGUMENT_LIST; }}} 첫 번째 형태가 가장 흔히 사용된다. 여러분이 어느 형태를 쓸지(또는 펄이 진짜로 사용할지)는 실행하려는 명령문에 셸 '''메타캐릭터'''가 들어있는지에 따라 결정된다. 셸 메타캐릭터는 다음과 같은 파이프, 리다이렉트, 구문 구분자 등을 포함한다:
( ps -aux | column 1 > pids ); date
정확히는 다음 문자들이다: {{{ & ; ` ' \ " | * ? ~ < > ^ ( ) [ ] { } $ \n \r }}} 만일 여러분이 실행하려는 명령문에 저 문자들 중 일부가 포함되어 있다면, 첫 번째 형태를 사용하여야 한다. 예를 들면: {{{ system("$tace < $tcmd > $tout"); }}} 이 경우 하나의 문자열 인자가 커맨드 셸에 전달된다. 여기서 기억해야 할 중요한 점 하나는, 일단 system() 함수를 사용했다면 여러분이 만든 스크립트는 더 이상 이식성이 있지(portable) 않을 것이라는 점이다. 윈도우와 유닉스 시스템을 오가며 사용하려면 적당히 고쳐야 할 것이다. ==== 그런데 어떤 셸을 쓰는가? ==== 유닉스 같은 운영체제에는 여러 가지 커맨드 셸이 있다: sh, csh, tcsh, bash, zsh 등등. 이 중 어느 것이 사용되는가? /etc/passwd 파일에 정의되어 있는, '''이 펄 스크립트를 실행한 사용자의 기본 셸'''이 사용된다. 여기서 문제의 소지가 있는데, 만일 여러분이 한 명의 사용자로서 스크립트를 개발하였고 이 스크립트를 다른 사용자에게 넘겨주거나, 'root' 등 다른 사용자의 자격으로 시스템 cron 작업으로 등록했다면, system() 함수가 여러분이 사용했던 셸이 아닌 다른 셸에서 실행될 수 있다는 점이다. 셸 내장 명령어의 종류나 $PATH 변수에 등록된 명령어들의 순서가 여러분이 스크립트를 만들 때와 다를 수 있다는 것이다. 여러분이 원하는 셸을 사용하도록 추가적인 셸 실행 계층을 넣어서 이런 문제의 소지를 최소화할 수 있다. {{{ system("/bin/tcsh -c 'diff file file.old > file.diff 2>&1 /dev/null'"); }}} 하지만 더 나은 접근법은 이런 것이다: 1. 가능하면 모든 유닉스 셸에 공통적으로 사용되는 셸 연산자들만 사용한다(단순한 리다이렉션, 파이프 등). 2. 언제나 실행하려는 운영체제 명령어의 전체 경로명을 적는다. (이러면 다른 유닉스 시스템으로의 이식성이 떨어지지만, 이것은 보안과 관련하여 양보해야 할 중요한 문제이다.) '''다음과 같이 하지 말라:''' {{{ system("chown $user.sgd newdata.txt"); }}} '''다음과 같이 하라:''' {{{ system("/usr/bin/chown $user:sgd newdata.txt"); system("/usr/ucb/chown $user.sgd newdata.txt"); }}} === # system() 함수의 두 번째 형태 === system() 함수의 두 번째 형태에서는: {{{ system($PROGRAM, @ARGUMENT_LIST); }}} 셸 메타캐릭터 체크가 이루어지지 않는다. 여러분은 단순히 명령어에 인자 목록을 주어 실행하여야 한다: {{{ system('/usr/bin/cp', $from, $to); }}} 이것은 범용적인 문자열 인자 형태의 system()과 비교했을 때 두 가지 측면에서 효율적일 수 있다. 첫째로, 이 형태는 명령어를 실행하기 위해 셸을 띄우지 않고, 유닉스의 '''execvp''' 시스템 콜을 써서 직접 실행한다. 따라서 런타임에 프로세스 오버헤드가 줄어든다. 둘째로, 컴파일타임과 런타임에 인자들을 하나의 문자열로 만들기 위해 문자열 결합을 할 필요가 없다. ==== 펄은 더 빠른 쪽을 선택한다 ==== 만일 첫 번째 형태를 사용하였는데 인자에 셸 메타캐릭터가 전혀 들어있지 않다면, 펄은 여러분이 인자로 준 문자열을 공백 문자를 기준으로 분리한 후 두 번째 형태로 바꾸어 실행한다. 이렇게 함으로써 추가로 셸을 띄우지 않도록 한다. {{{ system('mv /etc/group_comb /etc/group') => system('mv', '/etc/group_comb', '/etc/group') }}} 따라서 여러분은 두 번째 형태를 쓰려고 고민할 필요가 없다. 펄이 알아서 하게 두라. === # system() 함수의 세 번째 형태 === === # system() 함수는 정확히 무엇을 반환하는가? === === # 특별히 주의해야 할 점 === === # 개인적인 스타일 취향 === === # system() 테마의 변주 === == # 기타 & comments ==
---- [[컴퓨터분류]]
Perl/System
페이지로 돌아가기 |
다른 수정본 보기