여러분이 쉘 스크립트를 실행시키게 되면 다른 명령어 프로세스의 인스턴스를 띄웁니다. 여러분이 실행시킨 명령어가 명령어 줄 프롬프트에서 해석될 때, 스크립트 파일에 들어 있는 명령어 목록도 한 번에 같이 처리하게 됩니다. 이 때 실행되는 각각의 쉘 스크립트는 사실, 콘솔이나 한텀에서 여러분에게 프롬프트를 보여주던 부모 쉘의 서브 프로세스입니다.
쉘 스크립트 자신도 서브 프로세스를 띄울 수 있습니다. 이 서브쉘 덕분에 스크립트가 병렬로 처리되고 결국 동시에 다중 작업을 하는 것과 동일한 결과를 가져옵니다.
참고: 서브쉘의 변수들은 서브쉘이 속해 있는 코드 블럭 밖으로 보이지 않습니다. 이 변수들은 부모 프로세스나 그 서브쉘을 띄운 쉘에서 접근할 수 없기 때문에 실제로는 지역 변수가 됩니다.
예 20-1. 서브쉘에서 변수의 통용 범위(variable scope)
#!/bin/bash # subshell.sh echo outer_variable=Outer ( inner_variable=Inner echo "서브쉘의 \"inner_variable\" = $inner_variable" echo "서브쉘의 \"outer\" = $outer_variable" ) echo if [ -z "$inner_variable" ] then echo "inner_variable 은 쉘의 메인에서 정의되지 않았습니다." else echo "inner_variable 은 쉘의 메인에서 정의되었습니다." fi echo "쉘 메인의 \"inner_variable\" = $inner_variable" # $inner_variable 은 초기화되지 않은 것처럼 보이는데, # 서브쉘에서 정의된 변수는 그 서브쉘의 "지역 변수"이기 때문입니다. echo exit 0 |
예 32-1 참고.
+
서브쉘에서 작업 디렉토리가 변경돼도, 부모 쉘에게 영향을 미치지 않습니다.
예 20-2. 사용자 프로파일 보기
#!/bin/bash # allprofs.sh: 모든 사용자의 프로파일 출력 # 이 스크립트는 Heiner Steven 이 작성하고, 이 문서의 저자가 수정했습니다. FILE=.bashrc # 사용자 프로파일을 담고 있는 파일. #+ 원래 스크립트에서는 ".profile" 이었습니다. for home in `awk -F: '{print $6}' /etc/passwd` do [ -d "$home" ] || continue # 홈 디렉토리가 없는 사용자라면 다음으로 넘어감. [ -r "$home" ] || continue # 읽을수 없는 홈디렉토리라면 역시 그냥 넘어감. (cd $home; [ -e $FILE ] && less $FILE) done # 'cd $home' 이 서브쉘에서 돌기 때문에, #+ 스크립트가 끝난 다음, 'cd'를 써서 원래 디렉토리로 다시 돌아갈 필요가 없습니다. exit 0 |
서브쉘은 특정 명령어 그룹에 그들만의 "전용 환경"(dedicated environment)을 설정해 줄 수 있습니다.
COMMAND1 COMMAND2 COMMAND3 ( IFS=: PATH=/bin unset TERMINFO set -C shift 5 COMMAND4 COMMAND5 exit 3 # 서브쉘만 종료시킴. ) # 부모 쉘의 환경은 영향을 받지 않고 그대로 남아 있습니다. COMMAND6 COMMAND7 |
if (set -u; : $variable) 2> /dev/null then echo "변수가 세트되어 있습니다." fi # 이렇게도 할 수 있죠. [[ ${variable-x} != x || ${variable-y} != y ]] # 혹은 [[ ${variable-x} != x$variable ]] # 역시 [[ ${variable+x} = x ]]) |
if (set -C; : > lock_file) 2> /dev/null then echo "다른 사용자가 이미 실행중입니다." exit 65 fi # Thanks, S.C. |
프로세스를 다른 서브쉘에서 병렬로 실행시킬 수도 있습니다. 이렇게 하면 복잡한 작업을 여러개로 나누어서 동시에 처리할 수 있습니다.
예 20-3. 프로세스를 서브쉘에서 병렬로 돌리기
(cat list1 list2 list3 | sort | uniq > list123) & (cat list4 list5 list6 | sort | uniq > list456) & # 동시에 두 종류의 파일들을 합치고 정렬. # 백그라운드로 돌려서 병렬로 확실히 수행되도록 함. # # 다음과 같은 결과. # cat list1 list2 list3 | sort | uniq > list123 & # cat list4 list5 list6 | sort | uniq > list456 & wait # 서브쉘이 끝나기 전에 다음 명령어를 실행하지 않게 함. diff list123 list456 |
서브쉘로 I/O 재지향을 하려면 ls -al | (command) 처럼 파이프 연산자인 "|"를 씁니다.
참고: 중괄호속의 명령어 블럭은 서브쉘을 띄우지 않습니다.
{ command1; command2; command3; ... }