유닉스 쉘 프로그래밍 1

Posted by 잿빛푸우 greypoooh@daum.net
2008.10.22 10:00 리눅스의 모든것
쉘은 매우 강력하면서도 유연한 기능을 부여하며 생각하는 것보다 훨씬 빠르고 쉽게 시스템을 사용할 수 있게 해 준다.

쉘 프로그래밍의 개념은 MS-DOS의 배치(batch) 프로그램과 비슷하지만, 그보다 훨씬 완벽하고 강력한 기능을 보유하고 있다. 

쉘이란 유닉스 시스템과 사용자 사이에 대화할 수 있도록 해주며, 사용자가 입력한 문장을 읽어 그 문장이 요구하는 시스템 기능을 수행하도록 해주는 명령 해석기(command interpreter)이다.  

다음 명령을 보자.

/home/users > ls -l vi.doc 

쉘은 "ls"를 명령어로 인식하고 나머지는 모두 매개변수(parameter)로 인식한다. 쉘은 이들을 해석하여 유닉스의 핵심 부분인 커널(kernel)에 명령어 실행을 지시한다. 커널은 하드디스크로 부터 "ls"을 읽어 들여 그것을 단말기로 보낸다. 명령어는 이런 순으로 실행된다.  

쉘의 종류는 본쉘(sh), C쉘(csh), 콘쉘(ksh) 등이 있는데 이들을 간단히 살펴보자. 본쉘(Bourn Shell)은 AT&T가 발표한 최초의 표준 쉘이다. AT&T 벨 연구소의 스티븐 본이라는 사람이 만들었다.    

C쉘(C Shell)은 버클리의 캘리포니아 대학에서 개발된 쉘이다.  

콘쉘(Korn SHell)은 본쉘을 개량한 쉘로, C쉘의 많은 기능을 추가 하였으며, 콘쉘 만의 독특한 기능들도 가지고 있다. 이 쉘은 AT&T 벨 연구소의 데이비드 콘에 의해 만들어졌다.   

이들 쉘은 각각의 특징을 가지고 있으며 어떤 명령어들은 특정 쉘에서만 실행된다. 

여러분이 login하면 하나의 쉘이 기동되는데, 무슨 쉘인지는 알아야한다. 쉘을 알아야 해당 쉘에 맞는 환경을 지정할 수 있기 때문이다.

다음과 같이 치면 여러분이 사용하는 쉘이 어떤 쉘인지 알 수 있다.

/home/users > ps 

PID    TTY  TIME CMD    
45243  pts/1  0:00 -ksh    
48188  pts/1  0:00 ps

위의 예는 콘쉘을 사용하는 것이다.(개인적으로 나는 콘쉘을 사용한다). 이 쉘에서 다른 쉘로 변경하려면 "csh", "sh"를 치면 된다. 쉘에 따라 prompt도 바뀐다."$" prompt는 콘쉘과 본쉘의 일반 사용자 prompt이고, "%"는 C쉘의 일반 사용자 prompt이다.  

아래의 예는 test2라는 사용자가 로긴한 후 쉘의 변경 과정을 설명한 것이다. 

$ csh     --> 콘쉘에서 C 쉘로 바꿈           

% sh      --> C 쉘에서 본쉘로 바꿈 

$ ps -ef | grep test2                          
   test2 34366 42319   0 15:03:51  pts/4  0:00 -sh     ->(C 쉘)    
   test2 40769 45119   0 15:04:08  pts/4  0:00 grep pts/4  
   test2 42319 45646   0 14:04:41  pts/4  0:00 -ksh    -> (콘쉘)    
   test2 45119 34366   1 15:03:54  pts/4  0:00 sh     ->  (본쉘)    
   test2 47682 40769   5 15:04:08  pts/4  0:00 ps -ef    
$ exit    --> 본쉘을 빠져나옴
% exit    --> C 쉘을 빠져나옴 

위의 예에서 "ps -ef |grep test2" 라는 명령어를 쳤다. 그 이유는 임의의 쉘에서 다른 쉘로 바꿀 때 기존의 쉘이 남아있다는 것을 보여주기 위해서 이다. 이는 서브 쉘을 불렀기 때문이다. 이 서브 쉘에서 빠질려면 "exit"를 치면 된다. 

서브 쉘을 부르지 않고 다른 쉘로 바꾸기 위해서는 "exec"을 사용한다.

/home/users > ps
48235  pts/3  0:00 ps     
49758  pts/3  0:00 -ksh  
/home/users > exec csh
% ps
48221  pts/3  0:00 ps  
49741  pts/3  0:00 -sh  

쉘에 대해 이야기 할 때 쉘 스크립트란 말을 많이 쓴다. 쉘 스크립트(Shell script)란 일련의 쉘 명령을 포함하고 있는 파일로, 쉘에 대한 입력으로 사용되거나 실행 가능한 파일로 선언될 수 있는 스크립트를 말한다. 스크립트란 일반 프로그래밍 언어(c, cobol등)가 아닌 언어로 작성된 짧은 프로그램이다.  

간단한 쉘 스크립트를 작성해서 실행시켜 보자.

/home/users/shell > cat > shell1
ls -l
who
^D 
/home/users/shell > ls -l  shell1
-rw-r--r--   1 root     test           10 May 29 10:51 shell1
/home/users/shell > ksh shell1
total 4                                              
-rw-r--r--   1 root     test           10 May 29 10:51 shell1
root        pts/1       May 31 13:42          (mjj)          
root        pts/2       May 27 09:24          (sun)
test2       pts/3       May 31 13:38          (moon)
root        pts/6       May 29 09:58          (sun)  

위의 스크립트 결과는 "ls -l" 실행 후 "who" 명령을 실행한 것과 같은 결과를 출력한다. 이번에는 "ksh"를 빼고 실행 시켜보자. 

/home/users/shell > chmod 755 shell1      (실행 모드로 바꿈)
/home/users/shell > shell1 

같은 결과가 화면에 출력될 것이다. 

프로그램을 작성했을 때 주석(comment)을 달지 않는 프로그래머는 없다. 설사 그런 프로그래머가 있다고 하더라고 진정한 프로그래머라고 난 말하지 않는다.  쉘 스크립트에서도 "#" 기호를 사용하여 comment를 쓸 수 있다. 주석의 범위는 "#" 기호가 쓰여진 곳에서 부터 행의 끝까지고, 주석이 길어 다음 라인으로 넘어가면 "#" 기호를 다시 사용해야 한다.  

사용 예를 보자.

/home/users/shell > cat shell2
# 주석 사용 예.              
  ls -l          # 디렉토리 리스트 보기.
  who            # 누가 login 했나?      

이번에는 쉘 변수에 대해서 알아보자. 변수명은 문자, 숫자, 밑줄(underscore)로 구성되고, 반드시 문자나 밑줄로 시작해야 한다. 변수의 종류는 다음과 같이 세 가지가 있다.  

사용자 정의 변수 : 사용자가 임의로 사용하는 변수
쉘 변수(환경변수):쉘에 특별한 의미를 갖는 변수로 사용자에 의해 읽기와 쓰기가  허용되는 특수한 변(예, $HOME, $PATH, $PS1 등)
특수 변수(기호변수): 쉘이 자동적으로 지정하는 변수로 읽기만 허용되는 변수 

먼저 사용자 정의 변수에 대해서 살펴보자. 사용자 정의 변수는 다음과 같이 사용한다. "변수명=문자열". "=" 양측에 공백이 있으면 안 된다는 것에 주의해야 겠다.
변수에 값을 할당하고 변수의 내용을 확인해 보자. 확인 방법은 "set", "echo"명령을 사용된다. 

/home/users/shell > JJ=전조
/home/users/shell > echo $JJ
전조 

이 예에서 보듯이 "echo"을 이용해서 변수를 확인할 때는 변수명 앞에 "$"를 붙여서 확인했다.  변수를 사용하고자 할 때는 변수가 "="왼쪽에 있을 때는 "$"를 붙이지 않고, 그 이외의 일반적인 경우는 "$"를 붙혀 사용한다. 

"set"은 현재 login한 사용자의 모든 변수를 출력한다.

/home/users/shell > set 

위에서와 같이 변수명에 직접 대입해서 값을 지정할 수도 있지만, 키보드를 통해 입력을 받고 지정할 수도 있다.

/home/users/shell > read JJ
전조
/home/users/shell > echo $JJ
전조 

이렇게 설정된 변수를 삭제할 수 있는데, "unset" 명령어를 이용한다.

/home/users/shell > unset JJ
/home/users/shell > echo $JJ                              
<-- 변수가 지워졌다.
/home/users/shell > 

이제는 쉘 변수에 대해서 살펴보자. 아래에 나열한 변수들은 사용자의 HOME 디렉토리에 있는 .profile에서 설정되며, 그 값을 변경함으로써 사용자 자신에 맞는 환경을 구축할 수도 있다. "echo"라는 명령어로 확인할 수 있다.

HOME : cd 명령의 default 인수로서 홈 디렉토리를 나타낸다.
PATH : 명령어의 검색 경로이다(MS-DOS에서와 똑같은 개념이다)
MAIL : 사용자의 메일이 저장된 파일을 지정한다.
MAILCHECK : 메일의 도착 여부를 검사하는 시간 간격. default는 600초
PS1  : 콘쉘의 프롬프트를 지정.
PS2  : SECONDARY 프롬프트를 지정.
       예) /home/users > echo ' Enter
           > ' Enter        ---> ">"이 PS2의 값이다.
IFS  : 필드 구분 문자이며 보통 공백이다.
SHELL : 현재 참조하고 있는 쉘을 명시한다.
TERM : 사용자의 단말기 유형을 지정한다.
PPID : 해당 쉘의 parents 프로세스 ID.
PWD  : cd 명령어 의해 지정된 현재의 작업 디렉토리.
OLDPWD : cd 명령어 의해 이동된 이전의 디렉토리 

이 외에 자동적으로 지정되는 변수가 있다. 다음 변수들은 쉘이 수행되면 자동으로  어떤 값을 할당한다.  

$ : 명령을 수행하는 프로세스 번호
! : 가장 최근에 수행된 백그라운드 프로세스 번호
* : 인수의 개수
* : 지정된 인수의 모든 이름
? : 가장최근에 수행된 명령의 결과치(0 이면 실행 상태가 정상, 1 이면 비정상) 

다음 예를 보면 쉽게 알 수 있을 것이다.

/home/users/shell > cat shell3
echo $$          
echo $!
echo $#        
echo $*
echo $?            
/home/users/shell > shell3 a b c             (a, b, c 는 인수)
15426                --> shell3이 실행될 때의  프로세스 ID                          
                       --> 최근에 수행된 백그라운드 프로세스 ID. 현재 없슴.
3                      --> 인수의 개수(a, b, c)                   
a b c                 --> 인수 이름                   
0                       --> 최근에 수행된 명령의 결과치. 여기서는 "echo $*"의 결과치. 
                                정상적으로 끝났기 때문에 "0" 

변수에 값을 지정하는 방법을 봤다. 우연히 변수의 값이 바뀌면 어떻게 될까?
원하는 결과치를 얻지 못할 것이다. 이럴 때는 변수를 읽기 전용 변수로 바꿀 수 있다. 예를 보자. 

/home/users/shell > JJ=전조   
/home/users/shell > readonly JJ
/home/users/shell > JJ=전조1
ksh: JJ: This variable is read only.    
/home/users/shell > echo $JJ   
전조
저작자 표시 비영리 동일 조건 변경 허락
신고
이 댓글을 비밀 댓글로