Shell 이란?
User와 UNIX(Linux) 사이의 인터페이스로 작동하는 프로그램이다. 사용자는 shell을 통하여 OS가 실행할 명령을 입력한다. Windows(command 환경) 의 명령 프로프트와 비슷하다. 많은 쉘들이 존재한다. 대부분의 shell들은 Bourne shell 로부터 파생되었다. bash, csh, sh(Bourne) shell etc.등이 있다. Shell은 명령어 처리기와 고급 프로그래밍 언어의 두가지 역할을 한다.
[실습1] 현재 사용중인 bash 쉘의 버전을 확인해보자.
[ue20@zeus ~]$ /bin/bash –version
Redirection & Pipes
File Descriptor:
프로세스가 파일이나 디바이스를 access 하기 위해 사용한다. Standard file descriptor로는 표준 입력(예, 키보드)으로 사용되는 stdin(0), 표준 출력(예, 모니터)으로 사용되는 stdout(1)과 표준 에러 출력(예, 에러 메시지)으로 사용되는 stderr(2)가 있다.
Redirection:
>,>>: 명령어의 출력내용을 파일로 저장한다. ‘>’는 파일을 새로이 생성해서 출력내용을 저장한다. 파일이 존재하면 초기화후에 내용을 저정한다. 한다. ‘>>’는 기존 파일의 뒷부분에 추가한다.
<: 명령어에의 입력을 파일로부터 받아들인다.
Pipe ( | ):
하나의 Process에서 발생한 출력내용을 다른 프로세서의 입력으로 전달한다.
[실습2] 출력/입력 redirection을 실행해보자
Step1. 준비작업
[ue20@zeus ~]$ mkdir ch2
[ue20@zeus ~]$ cd ch2
[ue20@zeus ch2]$ pwd
/home/ue20/ch2
mkdir [name]: [name]을 가진 디렉토리를 만드는 명령어이다.
cd [name or path]: [name or path]로 이동하는 명령어이다.
pwd: 현재 위치한 전체 경로를 알려준다.
Step2. 현재 위치에서 다음과 같이 명령어 입력해보자.
[ue20@zeus ch2]$ ls -al > lsoutput.txt
[ue20@zeus ch2]$ more lsoutput.txt
⇒ more 또는 cat 명령어를 통해 lsoutput.txt 내용을 확인
[ue20@zeus ch2]$ more < lsoutput.txt
[ue20@zeus ch2]$ ps >> lsoutput.txt
[ue20@zeus ch2]$ more lsoutput.txt
vim lsoutput.txt 내용
more(cat) lsoutput.txt 내용
[실습3] pipe 사용
[ue20@zeus ch2]$ ps > psout.txt
[ue20@zeus ch2]$ sort psout.txt > pssort.out
[ue20@zeus ch2]$ more pssort.out
[ue20@zeus ch2]$ ps | sort > pssort.out
[ue20@zeus ch2]$ more pssort.out
※ 위의 보기에서 파이프를 이용했을 경우 psout.txt에 저장 없이 pssort.out를 얻을 수 있다.
※ 파이프는 명령들의 집합이 생성됨과 동시에 출력 파일 생성 또는 작성을 한다.
※ 명령들의 집합에 동일한 파일이 있을 경우는 원하는 결과를 얻을 수 없다.
Shell Programming
Shell Programming에는 두가지 방법이 있다. 첫째는 명령어들을 차례로 입력하고, shell이 명령어들을 대화형으로 실행하는 방법이다. 둘째는 명령어들을 파일에 기록하는 방법이다. 파일을 실행하면 명령어들이 실행된다. 이를 스크립트라한다. 스크립트 작성과 실행의 순서는 (1) Script 작성, (2) 실행 파일로 만들기, (3) 스크립트 실행 이다.
[예시] Line command
[ue20@zeus ch2]$ for file in *
> do
> if grep -l ps $file
> then
> more $file
> fi
> done
[예시2] Script를 사용해보자
[ue20@zeus ch2]$ vi first
# !/bin/sh
for file in *
do
if grep -l ps $file
then
echo $file
fi
done
exit 0
Shell 문법
Shell에서 사용할 수 있는 변수로는 문자열, 숫자, 환경, 매개변수가 있고, 쉘 부울(boolean)이 있다. 또한 프로그램 제어문에는 ‘if’, ‘elif’, ‘for’, ‘while’, ‘until’, ‘case’가 있다. Shell에서는 리스트와 함수를 사용할 수 있고, 쉘에 내장된 명령을 사용하고 명령의 결과를 가져올 수 있다.
Shell에서 변수는 사용할 때 선언한다. 즉 변수에 초기 값을 대입할 때 변수를 만들게 된다. 모든 변수는 문자열로 간주한다. 변수가 숫자 값을 가지는 경우에도 문자열로 간주된다. 또한 변수는 대소문자를 구분한다. 이 것은 리눅스 시스템의 특성이다. 변수에 값이 부여될 때를 제외하고, 변수를 사용할 경우 변수 앞에 ‘$’ 표시를 붙여야 한다. 변수에 부여된 값은 echo 명령을 통해 확인이 가능하다. 변수에 저장될 문자열 값 중 빈 칸을 포함하고 있다면 ” “을 이용하여 값을 부여한다.
쉘 변수 실습
[실습4] 명령줄(command line)에 변수에 값을 설정하고 each로 확인해보자
[ue20@zeus ch2]$ VAR=Hello ⇐ 값을 설정할 때 띄워 쓰면 에러가 발생한다.
[ue20@zeus ch2]$ echo $VAR
Hello
[ue20@zeus ch2]$ VAR=”Hello Hanyang Univ.”
[ue20@zeus ch2]$ echo $VAR
Hello Hanyang Univ.
[실습5] 스크립트를 작성해서 다양한 출력형태 확인해보자
[ue20@zeus ch2]$ vi var_example.sh
myvar=”Hi Hanyang Univ.”
echo $myvar
echo “$myvar”
echo ‘$myvar’
echo \$myvar
echo Enter some text
read myvar
echo ‘$myvar’ now equals $myvar
exit 0
Shell 환경변수
Shell Script가 시작 될 때 일부의 변수는 환경의 값을 통해 초기화 되는데, 이를 환경변수라 한다. 환경 변수는 사용자 정의 (쉘)변수와 구분하기 위해 보통 대문자로 선언된다. 환경변수는 각 사용자 환경에 따라 값이 다르다.
Shell 환경변수 실습
[실습6] 환경변수를 이해해보자
[ue20@zeus ch2]$ echo $PATH
/usr/kerberos/bin:/usr/local/bin:/bin/:/usr/bin:/usr/X11R6/bin:/home/ue20/bin
[ue20@zeus ch2]$ echo $HOME
/home/ue20
[ue20@zeus ch2]$ cat /home/ue20/ .bash_profile
# .bash_profile
#Get the aliases and functions
If [ -f ~/.bashrc ]; then
.~/.bashrc
fi
#User specific environment and startup programs
PATH=$PATH:$HOME/bin
Export PATH
Unset USERNAME
[ue20@zeus ch2]$
Shell 파라미터 변수
Script가 파라미터를 통해 호출된다면 몇 가지 추가적인 변수가 생성되는데 이를 파라미터 변수라 한다.
파라미터 변수 실습
Shell 상태에서 다음과 같이 명령을 실행한다.
$IFS=h #환경변수 IFS를 h로 초기화 한다.
$set foo bar bam #파라미터 설정.
$echo $@
$echo “$@”
$echo $*
$echo “$*”
$unset IFS
$echo $@
$echo $*
$echo “$@”
$echo “$*”
Shell 파라미터 변수 실습
[실습7] 매개 변수와 환경 변수를 사용해보자
[ue20@zeus ch2]$ vim vitry_var.sh
salutation=“Hello”
echo $salutation
echo “The Program $0 is now running”
echo “The Second parameter was $2”
echo “The First parameter was $1”
echo “The user’s home directory is $HOME”
echo “Please enter a new greeting”
read salutation
echo $salutation
echo “The script is now complete”
exit 0
[실습7] 매개 변수와 환경 변수 결과를 확인해보자
※ 사용자 작성 스크립트 chmod 명령을 통해 권한 변경 후 수행 가능하게 만들어보자
[ue20@zeus ch2]$ ls -l
[ue20@zeus ch2]$ chmod +x vitry_var.sh
[ue20@zeus ch2]$ ls –l
[ue20@zeus ch2]$ ./vitry_var.sh Hanyang Univ.
Shell 조건문
Shell Bool형 확인 기능으로 [], test가 있다. test, []는 어떤 표현식이나 파일에 대해 산술비교 스트링 비교, 파일조건 등을 확인하고 그에 대해 참 또는 거짓의 값을 리턴한다.
예) 파일의 존재 유무를 확인하는 test 명령
사용법: test –f <filename>
방법1. 기본형
if test –f fred.c
then
…
fi
방법2. 축약형
if [ -f fred.c]
then
…
fi
조건형식에는 문자열 비교, 산술 비교, 파일 조건이 있다.
Shell 제어 구조
‘If’는 명령의 결과를 테스트하고 조건부로 구문의 그룹을 실행한다. If 구문은 아래와 같다.
if condition
then
statements
else
statements
fi
If 조건문 실습
[실습8] 간단한 if 조건문을 사용해보자
[ue20@zeus ch2]$ vim ch2_if.sh
#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
if [ $timeofday = “yes” ]; then
echo “Good morning”
else
echo “Good afternoon”
fi
exit 0
Shell 제어 구조
‘Elif’는 스크립트가 yes가 아닌 모든 대답을 no로 받아들이는 것을 방지하기 위한 구조이다. If의 else부분이 실행될 때 검사할 두번째 조건을 추가하여 사용한다.
elif 조건문 실습
[실습9] elif를 사용하여 더 많은 검사를 수행해보자
[ue20@zeus ch2]$ vim ch2_ex_if.sh
#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
if [ $timeofday = “yes” ];then
echo “Good morning”
elif [ $timeofday=“no” ];then
echo “Good afternoon”
else
echo “Sorry, $timeofday not recognized. Enter yes or no”
exit 1
fi
Shell 제어 구조
‘For’는 값의 범위에 대한 반복문을 수행한다. 값의 범위는 문자열의 집합도 가능하다. ‘For’ 구문은 아래와 같다.
for variable in values
do
statements
done
for 반복문 실습
[실습10] 고정된 문자열을 사용하는 for 반복문을 사용해보자
[ue20@zeus ch2]$ vim ch2_for.sh
#!/bin/sh
for foo in bar fud 43
do
echo $foo
done
exit 0
[ue20@zeus ch2]$ vim ch2_for1.sh
#!/bin/sh
for foo in “bar fud 43”
do
echo $foo
done
exit 0
※ 변수 foo를 만들고 for 반복문이 매번 실행할 때마다 다른 값이 대입된다. 따라서 위의 두 예제 결과가 다름을 알 수 있을 것이다.
[실습11] 와일드카드(*) 확장을 사용하는 for 반복문을 사용해보자
[ue20@zeus ch2]$ vim ch2_wfor.sh
for file in $(ls c*.sh)
do
echo $file
done
exit 0
※ values 값으로 $(command)을 이용하여, 변수명(여기서는 file)은 $(ls c*.sh)에 포함된 명령의 출력값을 이용한다. 즉, 현재 디렉토리 내의 c로 시작하고 확장자가 sh로 끝나는(c*.sh) 모든 파일을 입력으로 해서 echo $file 출력을 한다.
모든 shell 변수가 기본적으로 문자열로 인식하기 때문에, for 반복문은 문자열 집합에 대해 반복문을 수행하기에 편리하다. 하지만, 정해진 횟수만큼 명령을 실행할 수 없다.
# !/bin/shfor foo in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
do
echo “here we go again”
done
exit 0
‘while’ 구문은 아래와 같다.
while condition do
statements
done
While 문 실습
[실습12] while 문을 이용한 간단한 password 확인 프로그램 작성해보자
[ue20@zeus ch2]$ vim ch2_pass_while.sh
#!/bin/sh
echo “Enter password”
read pass
while [ “$pass” !=kokoro” ]; do
echo “Sorry, try again..”
read pass
done
exit -0
[실습13] 정해진 횟수만큼 실행해보자
[ue20@zeus ch2]$ vim ch2_count_while.sh
#!/bin/sh
foo=1
while [ “$foo” –le 5 ]
do
echo “Here we go again”
foo=$(($foo+1))
done
exit 0
※ [ Expression1 –le Expression2 ] exp1이 exp2 보다 작거나 같을 때까지 반복한다
‘until’ 구문은 아래와 같다
until condition
do
statements
done
[ue20@zeus ch2]$ vim until2.sh
#!/bin/sh
until who | grep “$1” > /dev/null
do
sleep 10
done
echo –e \\a
echo “$1 has just logged in”
exit 0
‘Case’ 구문은 아래와 같다.
case variable in
pattern [ | pattern ] …) statements;;
pattern [ | pattern ] …) statements;;
…
esac
#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
case “$timeofday” in
yes | y | Yes | YES ) echo “Good Morning”;;
[nN]* ) echo “Good Afternoon”;;
* ) echo “Sorry”
exit 1;;
esac
[ue20@zeus ch2]$
Shell 리스트
‘AND list’는 “구문1 && 구문2 && 구문3 && …”로 표현한다. 그리고 ‘OR list’는 “구문1 || 구문2 || 구문3 …”와 같이 표현한다.
[ue20@zeus ch2]$ vim AndOr.sh
#!/bin/sh
touch file_one
rm –f file_two
if echo “True1” && [ -f file_one ] && echo “True3”
then
echo –e “And list”
rm –f file_one
else
echo –e “And list fail”
fi
touch file_two
if [ -f file_one ] || echo “False1” || [ -f file_two ] || echo “False2”
then
echo –e “Or list”
else
echo –e “or list fail”
Shell 함수
Shell 함수는 아래와 같이 사용한다.
function_name () {
statements
}
[ue20@zeus ch2]$ vim function.sh
#!/bin/sh
yes_or_no(){
echo “Is Your Name $1?”
while true
do
echo –n “Enter yes or no: ”
read X
case “$X” in
y|Y|yes|Yes|YES) return 0;;
n|N|no|No|NO) return 1;;
*) echo “Answer yes or no”
esac
done
}
echo “Original parameters are $*”
if yes_or_no “$1”
then
echo “Hi $1”
else
echo “Oh! Sorry”
fi
exit 0
Shell에 내장된 명령
Shell script 내에 2가지 명령 형태가 존재한다. 첫번째는 명령 프롬프트로부터 실행 가능한 명령이 있고, 두번째는 Shell script 내에 정의된 내장 명령이 있다. Shell에 내장된 명령어 중 ‘Break’는 반복문을 빠져나올 수 있다.
[ue20@zeus ch2]$ vim break.sh
#!/bin/sh
for var in 1 2 3 4 5 6 7 8 9 10
do
echo “var is $var.”
if [ “$var” = “5” ]
then
break;
fi
done
echo “Break!”
exit 0
~
[ue20@zeus ch2]$
‘: (콜론명령)’은 널 명령, true에 대한 별칭으로 조건에 대한 논리를 지정한다. ‘Continue’는 반복문에서 다음 반복에서부터 실행을 계속 한다. ‘Echo’는 문자열과 줄 바꿈 문자를 출력하며, ‘Eval’는 인자를 연산한다. ‘Exit n’는 숫자 ‘n’으로 지정된 종료 원인을 리턴하며 종료하는 명령이다. ‘n’ 값이 0이면 성공, 1~125이면 스크립트에서 사용 가능한 에러코드이다. 이 이상의 숫자는 예약된 코드이며 예를 들어 126은 “파일이 실행 가능하지 않았다”, 127은 “명령이 발견되지 않았다”, 128 이상은 “Signal 발생”을 의미한다.
‘Export’는 매개변수로 받은 이름의 변수를 하위 쉘에서 사용 가능하도록 만들어 준다.
[ue20@zeus ch2]$ vim export1.sh
#!/bin/sh
foo=“20”
export bar=“Valid 30”
./export2.sh
[ue20@zeus ch2]$ vim export2.sh
#!/bin/sh
echo –n “foo:”
echo “$foo”
echo –n “bar:”
echo “$bar”
[ue20@zeus ch2]$ ./export1.sh
foo:
bar: Valid 30
[ue20@zeus ch2]$
‘Expr’ 명령은 인수를 수식으로 평가할 수 있다.
‘Printf’는 [printf “형식 문자열” 매개변수1 매개변수2 …] 와 같이 사용할 수 있다. ‘Printf’에서의 escape 문자는 아래의 표와 같다.
‘Printf’의 중요한 변환 지정자는 아래의 표와 같다.
‘Return’은 함수를 반환하는 명령으로 하나의 숫자 매개변수를 가진다. ‘Set’ 명령은 쉘을 위한 파라미터 변수를 설정한다. ‘Shift’ 명령은 모든 파라미터 변수를 한 단계 아래로 이동한다.
[ue20@zeus ch2]$ vim shift.sh
#!/bin/sh
while [ “$1” != “” ]
do
echo “$1”
shift
done
exit 0
실습
다음 작업을 하는 shell program 을 작성해보자.
1. Creating 1000 files
~/test/ 디렉토리에 1.txt, 2.txt, …, 1000.txt 파일을 생성한다. touch 명령어를 사용한다.
%touch 1.c //1.c 파일이 생성된다.
2. 파일 내용 채우기
1.c 파일에는 ‘a’를 한번, 2.txt 파일에는 ‘a’를 2번,…, 1000.txt 파일에는 ‘a’를 1000번 쓴다.
3. 파일 복사
파일명이 3의 배수인 파일들을 ~/test_dest/ 디렉토리로 복사한다.
참고자료
KLDP Shell Programming의 기본
http://wiki.kldp.org/wiki.php/DocbookSgml/Shell_Programming-TRANS
초보자용 Shell Programming
http://www.softintegration.com/docs/ch/shell/