-read 명령: 빌트인 명령으로써 터미널 또는 파일로부터 입력 문자열을 읽을 때 사용한다.
-let 명령: 빌트인 명령으로 정수형 산술 연산을 수행하고 숫자 표현식을 테스트한다.
# n=`echo "scale=2; 20 / 3" | bc` -> 즉 소수점 아래 2자리(scale)로 지정하고 20을 3으로 나누고 결과값을 bc아규먼트에 전달
※ bc 명령은 대화형으로 문장을 실행하는 무한 정확도의 숫자를 지원하는 언어이다.
----------------------------------------------------------------------------------
echo $0 을 호출하였음.
----------------------------------------------------------------------------------
-종료상태: 명령어 수행 후에 echo $?을 입력하여 0이 나오면 정상 종료, 1이 나오면 비정상 종료(명령어 수행X)이다.
※ 브라켓을 사용할 때에는 반드시 시작 브라켓 다음에는 공백이 있어야 한다.
echo "파일 사이즈 범위가 20블록보다 작습니다. (20블록 이상)"
----------------------------------------------------------------------------------
$2 변수값의 크기(block)를 의미한다. +$2이므로 $2의 값 이상인 파일을 검색한다는 의미이며 exit 1,2,3은 종료 상태의 값을 나타낸다.
# ./nullcheck.sh -> 첫 번째 아규먼트의 값을 입력하지 않았다. (null)
# ./nullcheck.sh pride -> 첫 번째 아규먼트 값은 pride 이다.
----------------------------------------------------------------------------------
#!/bin/bash
# 스크립트명 : ifelse.sh
if [[ $1 == " " ]]
then
echo 사용법 : ./ifelse.sh 아이디
exit 1
fi
if grep :$1: /etc/passwd >& /dev/null
then
echo $1 아디를 찾았습니다.
else
echo "$1 아이디를 찾지 못했습니다."
exit 2
fi
----------------------------------------------------------------------------------
# chmod -x ifelse.sh
# ./ifelse.sh
# ./ifelse.sh root
vi rootcheck.sh
----------------------------------------------------------------------------------
#!/bin/bash
# 스크립트명: rootcheck.sh
# 수퍼유저의 유저아이디 번호는 0버이다.
id=`id | awk -F'[=(]' '{print $2}' ` # 유저아이디 얻기
echo 유저아이디 번호 : $id
if (( id == 0 )) # [ $id -eq 0 ]
then
echo "당신은 수퍼유저입니다. "
else
echo "당신은 수퍼유저가 아닙니다."
fi
----------------------------------------------------------------------------------
# chmod +x rootcheck.sh
# ./rootcheck.sh
-> awk 이용하여 필드 구분자를 =또는 ( 기호를 사용한다. 그래서 1번 필드는 uid 문자열이 되고, 2번 필드는 0, 3번 필드는
root)gid 문자열이 된다.
-if/then/elif/then/else 명령
<형식>
if 명령
then
명령
elif 명령
then
명령
else
명령
fi
# vi qa.sh
----------------------------------------------------------------------------------
#!/bin/bash
# 스크립트명 : qa.sh
echo -n "몇 점이세요? (0-100) : "
read num
if [ $num -lt 0 -o $num -gt 100 ]
then
echo "0 이상 100 이하의 수를 입력하세요."
exit 1
fi
if [ $num -le 69 ]
then
echo "70점 이하네요. "
elif [ $num -ge 70 -a $num -le 79 ]
then
echo "70점대군요."
elif [ $num -ge 80 -a $num -le 89 ]
then
echo "80점대군요."
elif [ $num -ge 90 -a $num -le 99 ]
then
echo "90점대군요"
elif [ $num -eq 100 ]
then
echo "만점이시네요. 축하합니다. "
else
echo "숫자를 입력해 주세요.(1-100)"
fi
----------------------------------------------------------------------------------
# chmod +x
-파일테스트
<파일 테스크 연산자>
파일 테스트 연산자
|
참(true)일 때 의미
|
-b filename
|
파일이 존재하고 블록 특수 파일이면 참
|
-c filename
|
파일이 존재하고 문자 특수 파일이면 참
|
-d filename
|
파일이 존재하고 디렉터리이면 참
|
-e filename
|
파일이 존재하면 참
|
-f filename
|
파일이 존재하고 일반 파일이면 참
|
-G filename
|
파일이 존재하고 유효 그룹 ID의 소유이면 참
|
-g filename
|
파일이 존재하고 set-group-id이면 참
|
-k filename
|
파일에 “스틱키(sticky)” 비트가 설정되어 있으면 참
|
-L filename
|
파일이 존재하고 심볼릭 링크이면 참
|
-p filename
|
파일이 존재하고 명명된(named) 파이프이면 참
|
-L filename
|
파일이 존재하고 심볼릭 링크이면 참
|
-p filename
|
파일이 존재하고 읽을 수 있으면 참
|
-O filename
|
파일이 존재하고 유효(effective) 사용자 ID의 소유이면 참
|
-f filename
|
파일이 존재하고 읽을 수 있으면 참
|
-S filename
|
파일이 존재하고 소켓이면 참
|
-s filename
|
파일이 존재하고 그 크기가 0보다 크면 참
|
-t fd
|
fd(파일 기술자)가 열린 상태이고 터미널이면 참
|
-u filename
|
파일이 존재하고 set-user-id 비트가 설정되어 있으면 참
|
-w filename
|
파일이 존재하고 쓸 수 있으면 참
|
-x filename
|
파일이 존재하고 실행 가능하면 참
|
# vi permitest1.sh
----------------------------------------------------------------------------------
#!/bin/bash
if [[ -z $1 ]]
then
echo 사용법 : ./permtest1.sh 파일명
exit 1
fi
if [[ -d $1 ]]
then
echo "$1은 디렉터리다."
elif [[ -f $1 ]]
then
if [[ -r $1 && -w $1 && -x $1 ]]
then
echo "$1 파일은 읽기, 쓰기, 실행이 가능한 파일이다. "
fi
else
echo "$1은 디렉터리도 파일도 아니다. "
fi
----------------------------------------------------------------------------------
# chmod +x permitest1.sh
# ./permitest.sh
# ./permitest.sh permitest.sh
-null 명령: 빌트인 명령이며, 콜론(:)으로 표시하며 수행시에 아무것도 출력하지 않는다.
# vi nulltest.sh
----------------------------------------------------------------------------------
#!/bin/bash
if grep "$1" testfile > & /dev/null
then
:
else
echo "$1 문자열은 testfile에 없네요."
exit 1
fi
----------------------------------------------------------------------------------
# chmod +x nulltest.sh
# ./nulltest.sh
# ./nulltest.sh 홍길동
-> 입력값이 testfile의 1번째 필드의 아규먼트와 일치하는지 확인하고 있으면 아무것도 출력하지 않고 없으면 메세지를 출력한다.
# vi nulltest1.sh
----------------------------------------------------------------------------------
#!/bin/bash
echo "정수를 입력하세요."
read number
if expr "$number" + 0 >& /dev/null
then
:
else
echo "입력된 값은 정수가 아닙니다."
exit 1
fi
----------------------------------------------------------------------------------
# chmod +x nulltest1.sh
# ./nulltest1.sh
-> 정수를 입력하세요~
1.22 -> "입력된 값은 정수가 아닙니다. "출력
100 -> 변화없음
입력값에 +0을 했을 때 정수이면 출력 없고 정수가 아니면 "입력된 값은 정수가 아닙니다"를 출력한다.
※ expr: 표현식을 평가하는 명령어
-case 명령
<형식>
case 변수 in
value1)
명령
;;
value2)
명령
;;
*)
명령
;;
esac
# vi case_exam.sh
----------------------------------------------------------------------------------
#!/bin/bash
echo -n "색을 표현하는 영어단어를 적으세요. 한글로 번역합니다. : "
read color
case $color in
[Bb]l??)
echo 푸른색입니다.
;;
[Gg]ree*)
echo 녹색입니다.
;;
red | orange) # 버티컬바는 or를 의미한다.
echo 빨간색 또는 오렌지색입니다.
;;
*)
echo "다시 입력해 주세요(blue, green, red, orange). "
;;
esac
echo "Case 명령 실행을 완료했습니다. "
----------------------------------------------------------------------------------
# chmod +x case_exam.sh
# ./case_exam.sh
>> here 다큐먼트와 case 명령을 사용한 메뉴 생성
# vi case_exam2.sh
----------------------------------------------------------------------------------
#!/bin/bash
echo "웹 서버를 시작할지 중지할지 선택하세요.: "
cat <<- ENDIT
1) 웹 서버 시작
2) 웹 서버 중지
3) 웹 서버 재시작
ENDIT
read choice
case "$choice" in
1) STATUS="시작"
/etc/init.d/httpd start
;;
2) STATUS="중지"
/etc/init.d/httpd stop
;;
3) STATUS="재시작"
/etc/init.d/httpd restart
;;
esac
echo "웹 서버가 $STATUS되었습니다. "
----------------------------------------------------------------------------------
# chmod +x case_exam2.sh
# ./case_exam2.sh
-> cat <<- ENDIT 명령은 cat 명령의 종료 마크로 ENDIT 문자열을 사용하는 here 다큐먼트이다. 즉, cat 명령으로 화면에 출력할
문자열은 ENDIT 문자열로 시작하는 라인의 앞부분이다. 선택된 숫자를 choice 변수에 할당하고 변수에 값에 따라 서로 다른 명령어를
지정하였다. 각 case 값에 대해 STATUS 변수값을 할당하고 실행할 명령들을 적어주었다.
루프 명령(for, while, until)
-for 루프 명령
<형식>
for 변수 in 단어목록
do
명령
done
# vi forloop.sh
----------------------------------------------------------------------------------
#!/bin/bash
for loop in 홍길동 장길산 장보고 이순신
do
echo "$loop"
done
echo "루프가 끝났습니다."
----------------------------------------------------------------------------------
# chmod +x forloop.sh
# ./forloop.sh
-> 4개의 이름을 차례로 출력
#vi mail_list
---------------------------------------------------------------------------------
root
centos
---------------------------------------------------------------------------------
# vi mail.txt
---------------------------------------------------------------------------------
안녕하세요.
반갑습니다.
---------------------------------------------------------------------------------
# vi mailing.sh
---------------------------------------------------------------------------------
#!/bin/bash
for person in $(cat mail_list)
do
mail $person < mail.txt
echo $person 발송 완료
done
echo "전체 메일 발송 완료!"
----------------------------------------------------------------------------------
# chmod +x mailing.sh
# ./mailing.sh
-> mail.txt의 내용을 mail_list에 있는 사용자에게 메일로 발송
<백업 스크립트>
# touch file1 file2 file3
# mkdir backup
# vi backup.sh
----------------------------------------------------------------------------------
#!/bin/bash
dir=/script/backup
for file in if*
do
if [ -f $file ]
then
cp $file $dir/$file.bak
echo "$file 파일이 $dir 디렉터리에 백업되었습니다."
fi
done
----------------------------------------------------------------------------------
-> for루프 사용하여 if로 시작하는 모든 파일을 file 변수에 할당하고 "-f $file"을 사용하여 파일인지 판단한 다음,
파일이면 cp명령을 사용하여 파일을 복사하면서 파일 뒤에 .back 문자열을 붙이도록 하였다.
- $*와 $
큰 따움표로 둘러 싸이지 않으면 $*와 $@의 의미는 같다. $* 하나의 문자열을, $@는 분리된 단어의 목록을 평가한다.
# vi hi.sh
----------------------------------------------------------------------------------
#!/bin/bash
for name in $*
do
echo $name 안녕.
done
----------------------------------------------------------------------------------
# chmod +x hi.sh
# ./hi.sh linux centos script
-> linux안녕. centos안녕. script안녕 이 각 행에 출력됨
# vi permx.sh
----------------------------------------------------------------------------------
#!/bin/bash
for file
do
if [[ -f $file && ! -x $file ]]
then
chmod +x $file
echo $file 파일에 실행퍼미션을 추가했습니다.
fi
done
----------------------------------------------------------------------------------
# chmod +x permx.sh
# touch permxtest1 permxtest2 permxtest3
# ls -l permxtest*
# ./ permx.sh permxtest* -> permxtest로 시작하는 파일들에게 실행권한(+x)을 부여함
# ls -l permxtest*
-> for 루프에서 단어 목록 미지정시 스크립트가 실행될 때 위치 파라미터를 분리하여 file 변수에 할당한다. if 명령으로
주어진 파일이 파일인지, 실행퍼미션을 가지고 있지 않은지 판단하고 두 가지 조건을 만족하면 퍼미션을 추가한다.
-while 루프 명령
<형식>
while 명령
do
명령
done
# vi numbers.sh
----------------------------------------------------------------------------------
#!/bin/bash
number=0 #number 변수 초기화
while (( $number < 10 )) # 또는 while [ number -lt 10 ]
do
echo -n "$number"
let number+=1 # number 변수 1증가
done
echo -e "\n루프 종료."
----------------------------------------------------------------------------------
# chmod +x number.sh
# ./number.sh
-> 0부터 9까지의 숫자를 차례대로 출력함
# vi quiz.sh
----------------------------------------------------------------------------------
#!/bin/bash
echo "2007년 12월 19일 제 17대 대한민국 대통령에 당선된 사람의 이름은?"
read answer
while [[ "$answer" != "이명박" ]]
do
echo "정답이 아닙니다. 다시 입력해 주세요!"
read answer
done
echo 정답입니다. :: 이명박
----------------------------------------------------------------------------------
# chmod +x quiz.sh
# ./quiz.sh
-> answer 변수에 값을 저장하고 그 값이 "이병박"이 아니면 반복해서 입력받고, 맞으면 메세지를 출력 후 종료
# vi say.sh
----------------------------------------------------------------------------------
#!/bin/bash
echo q를 입력하면 종료합니다.
go=start
while [[ -n "$go" ]] # 변수에 큰 따옴표를 확인하라.
do
echo -n 종료하려면 q를 입력하세요. :
read word
if [[ $word == [qQ] ]] # 예전 스타일 : [ "$word: = q -o :$word: = Q ]
then
echo "q를 입력하셨네요. 종료합니다!"
go=
fi
done
----------------------------------------------------------------------------------
# chmod +x say.sh
# ./quiz.sh
-> go의 변수의 값이 null이 아니면 루프를 계속 수행한다. 만약 q가 입력되면 then 아래의 명령이 수행되어 go 변수의 값이
null이 되므로 while 루프를 빠져나가게 된다.
-until 루프 명령
<형식>
until 명령
do
명령
done
vi untilcommand.sh
----------------------------------------------------------------------------------
#!/bin/bash
until who | grep multi
do
sleep 5
done
echo multi 유저가 로그인해 있습니다.
----------------------------------------------------------------------------------
# chmod +x untilcommand.sh
# ./untilcommand.sh
-> root유저가 로그인 할때까지 who 명령어를 5초에 한번씩 실행했다. root 유저가 있으면 who명령어 실행 후 종료한다.
# hour.sh
----------------------------------------------------------------------------------
#!/bin/bash
hour=0
until (( hour >= 24 ))
do
case "$hour" in
[0-9]|1[0-1]) echo $hour시 : 오전
;;
12) echo $hour시 : 정오
;;
*) echo $hour시 : 오후
;;
esac
(( hour+=1 )) # hour 변수를 1 증가해야 한다.
done
----------------------------------------------------------------------------------
# chmod +x hour.sh
# ./hours.sh
-> 0부터 23까지의 각 숫자에 해당하는 case 명령의 echo 명령 결과를 출력(0~11시 : 오전, 12시 : 정오, 13~23시 : 오후로 출력)
-select 명령과 메뉴: PS3 프로픔트는 입력을 위해 사용하는데, 디폴트로 PS3은 #?이다. PS 프롬프트가 출력된 다음, 쉘은 사용자의
입력을 위해 기다리게 된다. 이때 입력값은 메뉴 목록의 숫자 중에 하나가 되어야 한다. case 명령은 메뉴와 선택, 명령, 실행으로부터
유저가 선택하도록 하는 select 명령과 함께 사용된다. (루프를 빠져나가기 위해서는 break, 스크립트를 종료하기 위해서는 exit 사용)
<형식>
select 변수명 in 단어목록
do
명령
done
# vi run.sh
----------------------------------------------------------------------------------
#!/bin/bash
PS3="실행할 프로그램을 선택하세요. : "
select program in 'ls -F' pwd date exit
do
$program
done
----------------------------------------------------------------------------------
# chmod +x run.sh
# ./run.sh
-> 1을 입력하면 'ls -F', 2를 입력하면 pwd, 3을 입력하면 date, 4를 입력하면 exit를 실행한다.
# vi choice.sh
----------------------------------------------------------------------------------
#!/bin/bash
PS3="번호를 입력하면 웹사이트 주소를 볼 수 있습니다.. : "
select choice in 구글 네이버 네이버닷컴 다음 종료
do
case "$choice" in
구글)
continue;;
네이버 | 네이버닷컴)
continue;;
다음)
continue;;
종료)
echo "종료하였습니다."
break;;
*)
echo "$REPLY은(는) 없습니다. 1에서 4사이의 수를 입력하세요." 1>&2
echo "다시 선택."
;;
esac
done
----------------------------------------------------------------------------------
# chmod +x choice.sh
# ./choice.sh
-> 검색사이트들의 이름에 해당하는 번호를 선택하면 웹사이트의 주소를 출력해 주는 스크립트이다. select 명령어에서 변수로
choice를 사용했으며, 이 변수에 할당된 값은 총 5가지로 구성하였다. 선택한 번호가 존재하지 않을 경우 REPLY 빌트인 변수를
사용하여 echo 메시지를 출력하도록 하였으며 5번을 선택하면 break;; 명령을 실행하여 do~done을 빠져나온다.
값 입력 후에 continue를 수행함으로써 반복적인 입력을 수행 할 수 있다.
루프 관리 명령
-shift 명령: shit 명령은 지정한 수만큼 좌측으로 파라미터 목록을 이동한다. 가장 좌측에 있는 파라미터는 영구적으로 삭제된다.
<형식>
shitf n
# vi shift_using.sh
----------------------------------------------------------------------------------
#!/bin/bash
set 사과 배 포도 복숭아
shift
echo $*
set $(date)
echo $*
shift 3
echo $*
shift
echo $*
----------------------------------------------------------------------------------
# chmod +x shift_using.sh
./shift_using.sh
-> 결과값은 "배 포도 사과", date 출력값, date의 4번째 파라미터부터, date의 5번째 파라미터부터 출력($*은 모든 파라미터 출력)
# vi shift_while.sh
----------------------------------------------------------------------------------
#!/bin/bash
while (( $# > 0 ))
do
echo $*
shift
done
----------------------------------------------------------------------------------
# chmod +x shift_while.sh
# ./shift_while.sh 사과 배 복숭아
-> 파라미터의 수가 0보다 크면 do~done 명령을 수행한다. 즉, 입력받은 파라미터의 수가 0이 될때까지 shift하여 출력한다.
# vi shift_date.sh
----------------------------------------------------------------------------------
#!/bin/bash
set $(date)
while (( $# > 0 ))
do
echo $1
shift
done
----------------------------------------------------------------------------------
# chmod +x shift_date.sh
# ./shift_date.sh
-> 파라미터의 수가 0보다 같거나 작을 때 까지 shft를 수행하면서 1번째 파라미터를 출력한다.
-break 명령: break 명령은 루프를 빠져나가기 위해 사용한다. 바깥쪽 루프부터 안쪽 루프까지 3,2,1이 된다.
<형식>
break n
# vi loop_break.sh
----------------------------------------------------------------------------------
#!/bin/bash
while true
do
echo "리눅스를 사용해 보신 적이 있나요[y/n]? : "
read answer
if [[ "$answer" == [Y|y] ]]
then
break
else
echo "리눅스를 사용해 보신 경험이 없군요. "
fi
done
echo "리눅스 사용자이시군요."
----------------------------------------------------------------------------------
# chmod +x loop_break.sh
# ./loop_break.sh
-> 입력값이 Y또는 y가 될때까지 무한루프를 수행한다.
-continue 명령: 상태값이 true가 되면 continue 아래의 모든 명령들은 무시되고 루프의 최상위로 리턴하는 명령이다.
만약에 3개의 중첩루프가 있다면 가장 바깥쪽 루프는 3, 그 안쪽은 3, 가장 안쪽은 1로 정의된다. 가장 바깥쪽 루프의 상위로
가려면 continue 3을 실행하면 된다.
<형식>
continue n
# vi mail_list
----------------------------------------------------------------------------------
apache2
root
----------------------------------------------------------------------------------
# vi mail_content.txt
----------------------------------------------------------------------------------
안녕하세요
메일 테스트입니다.
----------------------------------------------------------------------------------
# vi continue_mail.sh
----------------------------------------------------------------------------------
#!/bin/bash
for name in $(cat mail_list)
do
if [[ $name == apache2 ]]
then
continue
else
mail $name < mail_content.txt
fi
done
----------------------------------------------------------------------------------
# chmod +x continue_mail.sh
# ./continue_mail.sh
# mail
-> mail_list애 입력되어 있는 유저 아이디를 가져와서 name 변수에 할당하는데, 이때 name 변수의 값이 apache2라면 coninue
명령을 실행하여 루프 최상단으로 가기 때문에 apache2 유저에게는 메일을 발송하지 않고 root 유저에게만 메일을 발송한다.
-중첩 루프와 루프 관리: 중첩 루프를 사용할 때 break 명령과 continue 명령에 숫자(정수형 아규먼트)를 부여할 수 있다.
<형식>
continue n : n번째 루프의 시작으로 이동
n : 가장 안쪽 루프가 1
그 다음 바깥쪽 루프가 2
그 다음 바깥쪽 루프가 3 ...
# vi loop_continue2.sh
----------------------------------------------------------------------------------
#!/bin/bash
# "continue n" 명령, n번 레벨의 루프에서 계속하기(continue).
for outer in A B C D E # 바깥쪽 2번 루프
do
echo; echo -n "Group $outer: "
for inner in 1 2 3 4 5 6 7 8 9 10 # 안쪽 1번 루프
do
if [ "$inner" -eq 6 ]
then
continue 2 # "바깥쪽 루프"인 2번 루프에서 계속 진행한다..
# 윗줄을 "continue"라고 하면 안쪽 1번 루프를 순회한다.
fi
echo -n "$inner" # 5 7 8 9 10은 출력되지 않는다.
done
done
echo; echo
exit 0
----------------------------------------------------------------------------------
# chmod +x loop_continue2.sh
# ./loop_continue2.sh
-> 안쪽 루프의 inner 변수의 값이 1부터 5까지 출력된 다음, 6이 되면 continue2 로 진행하여 반복적으로 수행하기 때문에
6부터 10까지의 수는 출력되지 않는다.
리다이렉션과 서브쉘
-루프의 결과를 파일로 리다이렉트하기
# vfi file.txt
----------------------------------------------------------------------------------
홍길동: 100
장길산: 200
정약용: 300
----------------------------------------------------------------------------------
# vi redirectfile.sh
----------------------------------------------------------------------------------
#!/bin/bash
if (( $# < 2 ))
then
echo "Usage: $0 [입력 파일명] [출력 파일명]" >&2
exit 1
fi
count=1
cat $1 | while read line
do
((count == 1 )) && echo "Processing file $1..." > /dev/tty
echo -e "$count\t$line"
let count+=1
done > tmp$$
mv tmp$$ $2
----------------------------------------------------------------------------------
# chmod +x redirectfile.sh
# ./redirectfile.sh
# ./redirectfile.sh file.txt file2.txt
# cat file2.txt
-> 라인별로 앞쪽에 라인 번호가 입력되고 탭이 들어간 다음 원래의 문자열이 출력된다.
-루프의 결과를 명령어와 파이프하기
# vi loop_command.sh
----------------------------------------------------------------------------------
#!/bin/bash
for i in 9 4 2 6 7 3
do
ecgi $i
done | sort -n
----------------------------------------------------------------------------------
# chmod +x loop_command.sh
# ./loop_command.sh
-> sort -n 명령을 사용하여 숫자를 정렬하여 출력
-백그라운드에서 루프 사용하기
----------------------------------------------------------------------------------
#!/bin/bash
for person in root multi linux centos
do
mail $ person < mail.txt
done &
----------------------------------------------------------------------------------
-> &를 사용하면 for 루프를 백그라운드로 실행할 수 있다.
-IFS와 루프: 쉘의 내부 필드 분리자(IFS)는 공백, 탭, newline 문자를 평가하며, read, set, for와 같은 단어 목록을 분석하는
명령을 위해 단어 분리자로 사용된다. (분리자 재설정 가능)
# vi use_IFS.sh
----------------------------------------------------------------------------------
#!/bin/bash
names=홍길동:김길동:이길동:박길동
oldifs="$IFS"
IFS=":"
for persons in $names
do
echo $persons님 안녕하세요.
done
echo "====="
IFS="$oldifs"
set 박정희 김대중 노무현 이명박
for president in $*
do
echo $president님 안녕하세요
done
----------------------------------------------------------------------------------
# chmod +x user_IFS.sh
# ./user_IFS.sh
-> names 변수에 값을 할당하면서 콜론:) 문자를 분리자로 사용하여 4개의 이름을 할당하였다. 그리고 IFS변수를 나중에
사용하기 위해 oldifs 변수에 할당해 주었으며, IFS 변수에는 콜론(:)을 재할당하였다. 그리고 for루프에서 names 변수
에서 방금 할당한 IFS 변수의 값인 콜론(:)을 사용하여 persons 변수에 분리된 문자열을 할당한다. 이번에는 앞서 만들
어둔 oldifs 변수의 값을 다시 IFS 변수에 재할당한 다음, set 명령을 사용하여 위치 파라미터들을 지정하고 $1 $2 $3 $4,
for 루프에서 $* 전체 위치 파라미터들을 president 변수에 각각 할당하면 공백을 기준으로 파라미터들이 분리되어 출력된다.
함수: 함수는 명령 또는 명령 그룹의 명칭이다. 함수는 현재 쉘의 컨텍스트에서 실행되며 자식프로세스를 생성하지
않는다.
<함수 작성 규칙>
1. 쉘은 디스크에서 검색되는 엘리아스, 함수, 빌트인 명령, 실행 프로그램(스크립트)들을 사용할지 결정한다.
2. 함수를 사용하기 위해서는 가장 먼저 함수를 정의해 두어야 한다.
3. 함수는 현재 환경에서 실행된다. 함수를 호출하는 스크립트 내에서 변수를 공유하여 위치 파라미터로 할당된 아규먼트들을
전달한다. 로컬 변수는 local 함수를 사용하여 함수 내에서 생성할 수 있다.
4. 만약 함수에서 exit 명령을 사용하면 스크립트의 실행을 중지하고 빠져나간다.
5. 함수에서 return 문장은 함수 또는 주어진 아규먼트의 값으로 마지막 실행된 명령의 종료상태를 리턴한다.
6. 함수는 export -f 빌트인 명령을 사용하여 서브쉘로 전달(전역화)할 수 있다.
7. 함수 목록과 정의를 출력하기 위해서는 declare -f 명령을 사용하고 함수 이름 목록을 출력하기 위해서는 decalre -F 명령을
사용한다.
8. 변수와 같이 트랩은 함수 안에서 전역이다. 스크립트와 스크립트에서 호출되는 함수에 의해 공유된다. 만약 트랩이 함수에서
정의되었다면 스크립트에 의해 공유된다. 원하지 않는 효과를 가져올 수 있다.
9. 만약 함수가 다른 파일에 저장되어 있으면 source 명령을 사용하여 현재 스크립트에서 사용할 수 있다.
10. 함수는 재귀호출이 가능하다. 즉, 자신을 호출할 수 있으며 재귀호출 횟수는 제한이 없다.
<형식>
function 함수명 { 명령 ; 명령 ; }
# function dir { echo "Directories: ";ls -l | awk '/^D/ {print $NF}' ; }
# dir
-함수 설정 제거하기
<형식>
unset -f 함수명
# function kty { echo "KIM TAE YONG" ; }
# kty
# unset -f
# kty
-함수 export: 함수를 서브쉘로 export하여 서브쉘에서 함수를 사용할 수 있다.
<형식>
export -f 함수명
-함수 아규먼트와 리턴값
>> 아규먼트: 아규먼트는 위치 파라미터를 사용하여 함수로 전달 할 수 있다
>> 빌트인 local 함수: 로컬 변수는 함수 내에서만 사용하는 변수이며, local 함수를 사용하여 로컬 변수를 정의한다. 함수가 종료
되면 로컬 변수도 제거된다.
>> 빌트인 return 함수
return 명령은 함수를 종료하기 위해 호출되는 함수의 위치에서 프로그램 관리를 리턴하는데 사용할 수 있다. (스크립트나 함수
에서 exit 명령을 사용하면 스크립트를 종료함). return 명령을 사용하여 아규먼트를 지정하지 않으면 함수의 리턴값은 스크립트
에 사용된 마지막 명령의 종료상태값이 된다. 만약 return 명령에 의해 할당된 값이 있다면 그 값은 ? 변수에 저장되고 0~256
사이의 정수값을 가질 수 있다.
# vi rwcheck.sh
----------------------------------------------------------------------------------
#!/bin/bash
function Usage { echo "에러 : $*" 2>&1; exit 1; }
if (( $# != 2 ))
then
Usage "$0: 두 개의 아규먼트가 필요합니다. "
fi
if [[ ! ( -r $1 && -w $1) ]]
then
Usage "$1: 파일은 읽고 쓸 수 없습니다. "
fi
echo 아규먼트 : $*
----------------------------------------------------------------------------------
# chmod +x rwcheck.sh
# touch f1.txt f2.txt
# ls -l f1.txt f2.txt
# ./rwcheck.sh
# ./rwcheck.sh f1.txt f2.txt
-> 에러가 발생했을 때 아규먼트를 사용하여 메세지를 출력하는 함수이다. 만약 아규먼트의 수가 2개가 아니라면 then 이하의
Usage 함수 호출을 실행하여 에러 메시지를 출력할 것이며, if 명령어에서 일고 쓰기가 불가능하다면 then 이하의 Usage 함수를
호출할 것이다. [결과 -> 아규먼트 : f1.txt f2.txt]
# vi increase.sh
----------------------------------------------------------------------------------
#!/bin/bash
increase () {
local sum;
let "sum=$1 + 1 "
return $sum
}
echo -n "합계는 "
increase 7
echo $? # increase 함수의 리턴값을 출력함
echo $sum # 아무런 값도 출력하지 않음
----------------------------------------------------------------------------------
# chmod +x increase.sh
# ./increase.sh
-> 아규먼트가 7인 increase 함수를 호출하여 7+1의 결과값을 리턴해준다. (결과 -> 합계는 8)
# square.sh
----------------------------------------------------------------------------------
#!/bin/bash
function square {
local sq
let "sq=$1 * $1"
echo "가로와 세로 길이 : $1"
echo "정사각형 넓이 : $sq "
}
echo "정사각형의 가로는? "
read number
value_returned=$(square $number)
echo "$value_returned"
----------------------------------------------------------------------------------
# chmod +x square.sh
# ./square.sh
-> sq를 지역변수로 선언하여 첫번째 입력값의 곱을 할당하고 입력 된 값을 read 명령을 사용하여 number 변수에 할당하였다.
square 함수에서 이 값을 아규먼트로 사용하여 호출한 결과값을 value_returend 변수에 할당하고 이 변수값을 출력하였다
-함수와 source 명령: 함수가 필요할 때 source 명령을 사용하여 함수가 정의된 파일에서 호출하여 사용할 수 있다.
# vi myfunction
----------------------------------------------------------------------------------
function os () {
echo "리눅스"
}
----------------------------------------------------------------------------------
# function use() { echo $1님은 $(os)를 사용해 보셨나요?; }
# source myfunction
# os
# use root
-> 쉘에서 source 명령을 사용하여 myfunction 파일을 읽어들일 수 있고, use 함수에도 함께 적용하여 사용할 수 있다.
# vi function
----------------------------------------------------------------------------------
function A() {
echo "function A"
}
function B() {
echo "function B"
}
function C() {
echo "function C"
}
----------------------------------------------------------------------------------
# vi function_script.sh
----------------------------------------------------------------------------------
#!/bin/bash
source ./function
A # 함수 A 실행
B # 함수 B 실행
C # 함수 C 실행
----------------------------------------------------------------------------------
# chmod +x function_script.sh
# ./function_script.sh
# A
-> 쉘 스크립트 내부에서 사용한 함수는 스크립트가 종료되면 모두 제거되기 때문에 실행 완료 후에는 사용할 수 없다.
트래핑 시그널
-trap 명령은 시그널이 도착했을 때 프로그램이 어떤 반응을 할지 관리하도록 하는 명령이다.
kill -l 명령 또는 trap -l 명령을 사용하면 모든 시그널 목록을 볼 수 있다.
※ 가장 많이 사용하는 시그널
1) SIGHUP (hangup), 2) SIGINT (interrupt), 3) SIGQUIT(quit), 9) SIGKILL (kill) 15) SIGTERM(exit), 20) SIGTSTP (stop)
<형식>
trap '명령; 명령' 시그널번호
trap '명령; 명령' 시그널이름
# trap 'rm tmp*; exit 1' 1 2 15
-> 1, 2, 15 시그널이 도착했을 때 tmp로 시작하는 모든 파일을 삭제하고 종료하도록 한 것이다. 스크립트가 실행되는 동안 인터
럽트가 발생하면 tarp 명령은 시그널을 인터럽트하게 된다.
# trap 'rm tmp*; exit 1' HUP INT TERM
-> bash쉘에서는 SIG 문자열을 제외한 시그널 심볼릭 이름을 사용 할 수 있으며, 시그널의 숫자값도 사용할 수 있다.
-시그널 재설정
시그널을 디폴트로 설정하기 위해서 TRAP 명령 다음에 시그널 이름 또는 시그널 번호를 적는다.
(함수의 trap 설정은 함수가 호출 될 때 함수를 호출한 쉘에 한 번만 적용된다)
trap INT 또는 trap 2
-> 시그널 2를 위한 디폴트 액션을 리셋하였다. 이 디폴트 액션은 <Ctrl-C> 키를 두 번 눌러서 인터럽트할 때 프로세스를 제거
하기 위한 것이다.
trao 'trap 2' 2
-> 실행할 명령어를 (' ')로 감싸주었기 때문에 프로그램을 종료하기 위해서는 <Ctrl-C>키를 두 번 눌러야 한다. 먼저 첫 번째
trap은 시그널을 가로채고, 두 번째 trap 재설정은 시그널의 디폴트 액션으로 설정하여 프로세스를 제거하는 것이다.
-시그널 무시하기
trap 명령 다음 따옴표 안에 아무 내용이 없으면 시그널 목록들은 프로세스에 의해 무시된다.
trap 명령 " " 1 2 또는 trap "" HUP INT
-> 시그널 1과 2는 쉘 프로세스에 의해 무시된다.
-trap 목록
# vi trap_exam.sh
----------------------------------------------------------------------------------
#!/bin/bash
trap 'echo "Ctrrl-C 종료하지 않음 $0."' INT
trap 'echo "Ctrl-\\ 종료하지 않음 $0."' QUIT
trap 'echo "Ctrl-Z 종료하지 않음 $0."' TSTP
echo "프롬프트에 아무 문자열이나 입력하세요.
종료를 하려면\"stop\" 을 입력하세요."
while true
do
echo -n "GOGO...> "
read
if [[ $REPLY == [Ss]top ]]
then
break
fi
done
----------------------------------------------------------------------------------
# chmod +x trap_exam.sh
# ./trap_exam.sh
GOGO...> Ctrl-C, Ctrl-\, Ctrl-Z, stop을 차례로 입력
-> Ctrl-C, Ctrl-\, Ctrl-Z 키에 echo를 설정하여 시그널을 수행하지 않고 메세지를 출력하게 함(stop 입력시 종료)
-trap과 함수: trap을 사용한 함수가 한번 호출되고 나면 스크립트 전체에 영향을 미친다.
# vi trap_func.sh
----------------------------------------------------------------------------------
#!/bin/bash
function trapper () {
echo "trapper 안"
trap 'echo "trap이 가로챔!"' INT
# trap이 한번 설정되면 trap은 스크립트 전체에 영향을 준다.
# ^c를 입력하더라도 스크립트는 무시한다.
}
while :
do
echo "메인 스크립트 안에서"
trapper
echo "아직 메인 스크립트"
echo "프로세스 아이디(ID) : $$"
sleep 5
done
----------------------------------------------------------------------------------
# chmod +x trap_func.sh
# ./trap_func.sh
<Ctrl-c> 입력
<Ctrl-z> 입력
# jobs
# ps ax | grep trap_func.sh | grep -v grep
# kill -9 [PID]
# ps ax | grep trap_func.sh | grep -v grep
-> trapper 함수를 정의하여, 시그널 INT(^C)가 발생하면 "trap이 가로챔"이라는 문자열을 출력하도록 하였고 메인 스크립트에서
while 무한루프 상태에서 trapper 함수를 호출하고 현재 프로세스 아이디를 출력하도록 하였다. 프로세스를 종료시키기 위해
서는 <Ctrl-C>키를 사용하여 프로세스를 백그라운드에서 실행되도록 한 다음 kill -9 명령을 입력하여야 한다.
bash 스크립트 디버깅
<bash 스크립트 디버깅 옵션>
스크립트 디버깅 옵션
|
옵션명
|
설명
|
bash –x 스크립트명
|
에코 옵션
|
변수 치환 후 그리고 실행 이전에 스크립트 각 라인을 출력한다.
|
bash –v 스크립트명
|
다양한 옵션
|
실행 이전에 스크립트의 각 라인을 출력한다.
|
bash –n 스크립트명
|
비실행 옵션
|
해석은 하지만 실행하지는 않는다.
|
set –x
|
에코 활성화
|
스크립트에서 실행을 추적한다.
|
set +x
|
에고 비활성화
|
스크립트에서 실행을 추적하지 않는다.
|
※ 다양한 옵션을 사용하거나 -v 옵션(bash -v 스크립트명)과 함께 쉘을 호출하면 스크립트의 각 라인은 스크립트에 타이핑한
것처럼 출력하고 실행 할 수 있다.
# debug_exam.sh
----------------------------------------------------------------------------------
#!/bin/bash
name="linux"
if [[ $name == "centos" ]]
then
printf "Hello $name\n"
fi
declare -i num=1
while(( num < 5 ))
do
let num+=1
done
printf "Total : %d\n" $num
----------------------------------------------------------------------------------
# bash -x debug_exam.sh -> 변수 치환 후 실행 이전에 스크립트의 각 라인을 출력
# chmod +x debug_exam.sh
# ./debug_exam.sh
명령라인
-getopts를 사용한 명령라인 프로세싱: -옵션을 사용 할때 여러개의 아규먼트를 한번에 처리 할 수 있다.(ls -liF)
# vi opt1.sh
----------------------------------------------------------------------------------
while getopts xy options
do
case $options in
x ) echo "-x 옵션을 사용하셨네요.";;
y ) echo "-y 옵션을 사용하셨네요.";;
esac
done
----------------------------------------------------------------------------------
# chmod +x opt1.sh
# ./opt1.sh -x
# ./opt1.sh -xy
# ./opt1.sh -a
# ./opt1.sh a
-> getopts 명령은 x와 y의 옵션을 체크하기 위해 getopts xy 형태로 사용한다. -x와 -y는 있는 옵션이기 때문에 입력시에
정상적으로 출력되지만 -a는 옵션으로 인식하지 않기 때문에 잘못된 메세지를 출력,-가 없으면 아무값도 출력하지 않는다.
-툭수한 getopts 변수들: getopts 함수는 아규먼트들의 존재를 유지시키기 위해 두 개의 변수(OPTIND,OPTARG)를 제공한다.
OPTIND 변수는 1로 초기화되며, getopts가 명령라인 아규먼트를 한번 씩 프로세싱 할 때마다 증가되는 특수변수이다.
OPTARG 변수는 아규먼트의 값을 가진다.
# vi opt3.sh
----------------------------------------------------------------------------------
#!/bin/bash
while getopts ab: options
do
case $options in
a) echo "-a 옵션을 사용하셨네요.";;
b) echo "-b 옵션의 아규먼는 $OPTARG";;
c) echo "사용법 : opt3 -ab 파일명" 1>&2;;
esac
done
----------------------------------------------------------------------------------
# chmod +x opt3.sh
# ./opt3.sh -a
# ./opt3.sh -b linux
-> -a 옵션을 입력하면 지정된 메세지를 출력하고 -b 옵션과 파라미터를 입력하면 OPTARG에 저장하여 출력한다.
-eval 명령과 명령라인 파싱: eval 명령은 명령라인을 평가하는데, 모든 쉘 치환을 수행한 다음 명령라인을 실행한다.
# set a b c d e -> 파라미터 5개 설정
# echo The Last Argument is \$$#. -> "\$"는 $문자를 그대로 출력, $#의 값은 파라미터 개수를 출력 (출력값: $5)
# eval echo The Last Argument is \###. -> eval 명령을 사용하면 변수를 먼저 값으로 치환한 다음에 echo 명령을 수행
vi eval_exam.sh
----------------------------------------------------------------------------------
#!/bin/bash
eval `id | sed 's/[^a-z0-9=].*//'`
if [ "${uid:=0}" -ne 0 ]
then
echo $0: only root can run $0
exit 2
else
echo "root user : superuser"
fi
----------------------------------------------------------------------------------
# chmod +x eval.exam.sh
# ./eval_exam.sh
# su fedora
# ./eval_exam.sh
# exit
-> sed 명령어를 사용하여 정규표현식은 문자열로 시작되고 = 기호가 있는 곳까지 검색한다. 그리고 괄호가 나타나는 곳부터
문장의 끝까지 모든 것을 삭제한다. 그래서 남은 문자열은 uid 형태를 가지게 되며, eval 명령은 명령라인을 평가하면서 root
유저라면 uid=0을 실행하여 uid 로컬 변수에 0을 할당한다. 그리고 명령 변경자를 사용하여 uid 변수의 값이 0인지 테스트하고,
아니면 then 이하의 echo 명령에서 첫 번째 위치 파라미터 $0의 값을 출력하게 되며, 0이면 else 다음의 echo 명령을 실행한다.
bash 옵션들
-쉘 호출 옵션: 싱글 캐릭터 옵션은 대시(-) 다음에 단일 문자가 오며, 멀티 캐릭터 옵션은 두 개의 대시(--) 다음에 여러 개의
문자가 온다. 멀티 캐릭터 옵션은 싱글 캐릭터 옵션에 위치해야 한다. 일반적으로 인터렉티브한 로그인 쉘은 -i 옵션(인터렉티브
쉘 시작), -s(표준 입력으로부터 읽기), -m(잡 컨트롤 가능) 옵션을 가지고 시작된다.
<쉘 호출 옵션>
옵션
|
의미
|
-C sring
|
-c 플래그가 있으면 문자열로부터 명령을 읽어들인다. 문자열 뒤에 전달인수가 있으면 그 전달인수는 $0부터 시작하여 위치 매개변수로 지정된다.
|
-D
|
$로 시작되고, 큰 따옴표로 인용된 문자열들의 목록은 표준 출력으로 출력된다. 현재 로케일이 C 또는 POSIX가 아닐 때 이 문자열들은 언어 번역을 위한 제목이다.
|
-i
|
-I 플래그가 있으면 쉘은 대화형(interactive) 모드로 동작한다.
|
-s
|
-s 플래그가 있을 때 또는 옵션 처리 후에 남은 인수가 없을 때에는 표준 입력으로부터 명령을 읽어들인다. 이 옵션을 사용하여 대화형 쉘을 실행시킬 때 위치 매개변수를 설정 할 수 있다.
|
-r
|
제한된 쉘을 시작한다.
|
-
--
|
옵션의 마지막 시그널이며 옵션 프로세싱을 더 이상 할 수 없다.
--또는 –옵션 이후의 아규먼트들은 파일명과 아규먼트로 취급한다.
|
--dump-strings
|
-D 옵션과 같다.
|
--help
|
빌트인 명령을 위한 사용법 메시지를 출력하고 종료한다.
|
--login
|
bash가 마치 로그인 쉘로 시작된 것처럼 행동하게 한다.
|
--noediting
|
bash가 대화형 모드로 실행 중일 때 readline 라이브러리를 사용하지 않는다.
|
--noprofile
|
시스템 전역 시동 파일인 /etc/profile 또는 ~/.bash_profile, ~/.bash_login, ~/.profile 파일과 같은 모든 개인 초기화 파일을 읽지 않도록 한다. bash가 로그인 쉘로 실행될 때에는 기본적으로 이 모든 파일을 읽는다.
|
--norc
|
쉘이 대화형 모드일 때 유저 개인의 초기화 파일인 ~/.bashrc 파일을 실행하지 않도록 한다. 쉘을 실행할 때 bash9sh)라는 이름으로 실행하면 기본적으로 이 옵션이 켜진다.
|
--posix
|
기본적으로 POSIX 1003.2 표준과 다른 BASH 행동 방식을 바꾸어 표준에 부합되도록 지시한다.
|
--quiet
|
쉘을 시작할 때 상세한 정보를 보여주지 않는다. 즉, 쉘 버전과 기타 정보를 표시하지 않는다. 기본값이다.
|
--rcfile file
|
쉘이 대화형 모드일 때 표준적인 개인 초기화 파일인 ~/.bashrc 대신 파일의 명령을 실행한다.
|
--restricted
|
제한된 쉘을 시작한다. –r 옵션과 같다.
|
--vervose
|
vervose 옵션을 켠다. –v 옵션과 같다.
|
--version
|
bash 쉘에 대한버전 정보를 표시하고 종료한다.
|
- set 명령과 옵션들: set -기호를 사용하여 옵션을 on하고 set +기호를 사용하여 off옵션을 설정 할 수 있다.
# set -f
# echo ??????
?????? -> 입력한 값을 그대로 출력
# set +f
# echo ??????
f1.txt, f2.txt .... -> .을 포함한 6자리의 파일명을 출력
<set 명령 옵션>
set 명령 옵션
|
짧은 옵션
|
의미
|
allexport
|
-a
|
설정을 해제할 때까지 뒤이어서 나올 명령의 환경으로 export하기 위해 수정 또는 생성할 변수를 자동으로 표기한다.
|
breacexpand
|
-B
|
브레이스 확장이 가능하며 기본값으로 설정되어 있다.
|
emacs
|
|
이맥스 스타일의 명령행 편집 이터페이스를 사용하며, 기본값으로 설정되어 있다.
|
errexit
|
-e
|
명령이 0 아닌 상태값을 갖고 종료하면 즉시 종료한다. 만약 실패한 명령이 until 또는 while 루프의 일부, if 문의 일부, &&의 일부, || 목록의 일부이거나 또는 명령의 반환값이 !로 반전되면 종료하지 않는다.
|
histexpand
|
-H
|
! 스타일의 히스토리 치환을 사용한다. 쉘이 대화형 모드이면 기본으로 켜지는 플래그이다.
|
ignoreeof
|
|
쉘을 빠져나오기 위해 <Ctrl-d>를 눌러 EOF하지 못하도록 한다. 이때에는 exit 명령을 사용해야 한다. 쉘 명령 ‘IGNOREEOF=10’을 실행한 것과 같은 효과를 발휘한다.
|
keyword
|
-k
|
명령을 위한 환경에서 키워드 아규먼트를 배치한다.
|
interactive-comments
|
|
인터렉티브 쉘에서 이 옵션을 사용하지 않으면 # 주석을 사용할 수 없다. 기본값으로 설정되어 있다.
|
monitor
|
-m
|
잡 컨트롤을 허용한다.
|
noclobber
|
-C
|
리다이렉션이 사용될 때 덮어쓰기로부터 파일을 보호한다.
|
noexec
|
-n
|
명령을 읽지만 실행하지 않으며, 스크립트의 문법을 체크하기 위해 사용된다. 인터렉티브로 실행했을 때에는 이 옵션이 적용되지 않는다.
|
noglob
|
-d
|
경로명 확장을 할 수 없다. 와일드카드가 적용되지 않는다.
|
notify
|
-b
|
백그라운드 잡이 종료되었을 때 유저에게 알려준다.
|
nounset
|
-u
|
변수 확장이 설정되지 않았을 때 에러를 출력해 준다.
|
onecmd
|
-t
|
하나의 명령을 읽고, 실행한 다음 종료한다.
|
physical
|
-P
|
이 옵션이 설정되면 cd 또는 pwd를 입력했을 때 심볼릭 링크는 가져오지 못한다. 물리적인 디렉터리만 보여준다.
|
posix
|
|
기본 연산이 POSIX 표준과 매칭되지 않으면 쉘의 행동이 변경된다.
|
privileged
|
-p
|
이 옵션이 설정되었을 때 쉘은 .profile 또는 ENV 파일을 읽지 않으며, 쉘 함수는 환경으로부터 상속되지 않는다.
|
verbose
|
-v
|
쉘에서 행 입력을 받을 때마다 그 입력행을 출력한다.
|
vi
|
|
명령라인 에디터로 vi 에디터를 사용한다.
|
xtrace
|
-x
|
각각의 간단한 명령을 확장한 다음, bash PS4의 확장값을 표시하고 명령과 확장된 인수를 표시한다.
|
bash 스크립트를 이용하여 Text GUI 만들기
-dialog 유틸리티 설치하기
# rpm -qa|grep dialog -> 확인
# yum install dialog -y -> 설치
-dialog 사용법 확인
# dialog --help # man dialog
-메세지 박스
# dialog --title "메세지 박스" --backtitle "쉘 스크립트 프로그래밍" --msgbox "리눅스 쉘 스크립트" 15 30
-> 타이틀과 백타이틀 설정, msgbox 높이는 15 너비는 30
-yes/no 박스
# vi ynbox.sh
----------------------------------------------------------------------------------
#!/bin/bash
dialog --title "경고 : 파일 삭제" --backtitle \
"리눅스 프로그래밍" --yesno \
"\n삭제하시겠습니까? '/home/multi/testdel.sh' file" 7 60
sel=$?
case $sel in
0) echo "삭제를 선택했습니다.";;
1) echo "삭제를 선택하지 않았습니다.";;
255) echo "<Esc>키를 눌러 취소하였습니다.";;
esac
----------------------------------------------------------------------------------
# chmod +x ynbox.sh
# ./ynbox.sh
-> --yesno 옵션을 사용하여 yes/no 박스를 보여주고 sel 변수에 $? 값을 할당하여 선택 결과에 따라 다른 메세지를 출력
-입력 박스
# vi inputbox.sh
----------------------------------------------------------------------------------
#!/bin/bash
dialog --title "입력 박스" --backtitle "쉘 스크립트 프로그래밍" --inputbox "이름을 입력하세요." 8 60 2>/tmp/input.$$
sel=$?
name=`cat /tmp/input.$$`
case $sel in
0) echo "$name님 안녕하세요." ;;
1) echo "취소를 누르셨네요." ;;
255) echo "<Esc>키를 누르셨네요." ;;
esac
rm -f /tmp/input.$$
----------------------------------------------------------------------------------
# chmod +x inputbox.sh
# ./inputbox.sh
-> --inputbox은 유저로부터 문자열을 입력받기 위해 사용하는 옵션이며, 3>/tmp/input.$$와 같이 입력한 값을 파일로 저장한다.
여기서 $$는 현재 실행중인 쉘의 PID를 의미하며 sel 변수에 이전 명령의 종료 상태값($?)을 할당하였고, name 변수에 cat/tmp/
/input.$$ 명령을 저장해두었으며, <Esc>키가 눌러지면 255) 항목의 명령을 실행하도록 하였다. 마지막으로 수행이 끝나면
이전에 사용했던 파일은 rm -f를 이용하여 삭제하였다.
-라디오 리스트
# dialog --backtitle "라디오 리스트" --radiolist " 선택하세요" 15 25 3 1 "one" "off" 2 "two" "on" 3 "three" "off"
-> --radiolist를 사용하여 체크 박스를 1, 2, 3번의 체크 리스트를 만들고 2번의 on 상태를 기본으로 유지
-dialog 예제 만들어 보기
# touch dialogbox.sh
# chmod +x dialogbox.sh
# vi dialogbox.sh
----------------------------------------------------------------------------------
#!/bin/bash
dialog --title "vsftpd 서버 관리" --backtitle "vsftpd 서버 관리" \
--msgbox "vsftpd 서버를 관리합니다. " 15 35
dialog --title "vsftpd 시작/중지/재시작" --backtitle "vsftpd 시작/중지/재시작" \
--menu "선택하세요." 15 35 4 start "시작하기" stop "중지하기" \ # 높이15 너비35, 메뉴높이4
restart "재시작하기" exit "종료" 2>/tmp/vsftpd_menu.$$ # restart를 /tmp 디렉터리 아래 vsftpd_menu.[PID]형태로 리다이렉션
menuitem=`cat /tmp/vsftpd_menu.$$`
case "$menuitem" in
start)
/etc/rc.d/init.d/vsftpd start
dialog --backtitle "결과" --infobox "vsftpd 서버를 시작하였습니다. " 10 25
;;
stop)
/etc/rc.d/init.d/vsftpd stop
dialog --backtitle "결과" --infobox "vsftpd 서버를 중지하였습니다. " 10 25
;;
restart)
/etc/rc.d/init.d/vsftpd restart
dialog --backtitle "결과" --infobox "vsftpd 서버를 재시작하였습니다." 10 25
;;
exit)
exit 0
;;
esac
rm -f /tmp/vsftpd_menu.$$
----------------------------------------------------------------------------------
# vi vsftpd_menu.sh
----------------------------------------------------------------------------------
#!/bin/bash
while :
do
#clear
echo "---------------------------------"
echo "vsftpd 시작/중지/재시작"
echo "---------------------------------"
echo "[1] vsftpd 시작하기"
echo "[2] vsftpd 중지하기"
echo "[3] vsftpd 재시작하기"
echo "[4] 프로그램 종료하기"
echo "===================="
echo -n "메뉴에서 번호를 선택하세요. [1-4] : "
read choice
case $choice in
1) /etc/rc.d/init.d/vsftpd start \
&& ps ax|grep /usr/sbin/vsftpd|grep -v grep;;
2) /etc/rc.d/init.d/vsftpd stop;;
3) /etc/rc.d/init.d/vsftpd restart \
4) exit 0;;
*) echo "1에서 4번 중 선택하세요.";;
esac
done
----------------------------------------------------------------------------------
# chmod +x vsftpd_menu.sh
# ./vsftpd_menu.sh
유용한 유틸리티
<실습 설정>
# vi sname(공백은 tab으로 구분)
----------------------------------------------------------------------------------
11 사과
12 배
13 복숭아
14 참외
15 수박
----------------------------------------------------------------------------------
# vi sprice(공백은 tab으로 구분)
----------------------------------------------------------------------------------
11 300
12 500
13 200
14 150
15 5000
----------------------------------------------------------------------------------
-cut 명령: 파일에서 지정한 각 라인의 필드를 자르는 명령
<형식>
cut -f[필드번호] [파일명]
# cut -f2 sname
-> 2열만 잘라서 출력
# cut -f1 sname
-> 1열만 잘라서 출력
-paste 명령: 텍스트 정보를 합치는 명령
<형식>
paste [파일1] [파일2]
# paste sname sprice
-join 명령: 두 파일에서 같은 값을 가지는 필드는 합치고 나머지 필드는 더하는 명령
<형식>
join [파일1] [파일2]
# join sname sprice
-tr 명령: 표준 입력으로부터 문자들을 변경하거나 삭제하고 표준 출력으로 출력
<형식>
tr [패턴1] [패턴2]
# tr "12" "xy" < sname
-> 1 문자를 x로, 2 문자를 y로 변경하는 명령
# tr "[a-z]" "[A-Z]"
-> 소문자를 대문자로 변경
-uniq 명령: 인접한 라인의 같은 문자열을 검색하여 되풀이 되는 라인은 한 개의 문자열만 제외하고 모두 삭제
<형식>
uniq [파일명]
# vi pname
----------------------------------------------------------------------------------
리눅스 좋아하세요?
CentOS
CentOS
환영합니다.
리눅스의 세계로 오신 것을 환영합니다.
리눅스를 좋아하세요?
페도라
페도라
----------------------------------------------------------------------------------
# uniq pname
-> 중복된 CentOS와 페도라는 한 개만 남기고 모두 삭제
# sort pname | uniq
-> sort 명령을 활용하면 인접해 있지 않은 같은 내용에 대해서도 삭제할 수 있다.
-split 명령: 용량이 큰 텍스트 파일을 크기 단위 또는 라인 단위로 잘라낼 수 있다.
# split --help -> 옵션 확인...(unix와 옵션이 다름)
# split -l [라인수] [파일명] [저장할 파일명(안써도됨)] -> 라인 수로 데이터 나누기(나누었을 때 알파벳(aa..ab)을 기준으로 분류)
# split -b [바이트 수] -d [파일명] [저장할 파일명(안써도됨)] -> 데이터의 크기로 데이터 나누기(-d 옵션을 사용하여 숫자로 채움)
-col 명령: "\n\r" 문자를 "\n" 문자로, 공백문자를 탭문자로, 백스페이스 삭제 문자로 변경하는 필터이다.
# man col -> 옵션 확인
col 옵션
|
의미
|
-b
|
어떠한 백스페이스 문자도 출력하지 않는다. 백스페이스 문자와 연결되는 마지막 문자만 출력한다.
|
-f
|
밑줄 속성을 가진 문자열을(Forward half line feed) 변환하지 않는다. 일반적으로 밑줄 속성을 가진 문자열들은 다음 라인에서 밑줄이 나타난다.
|
-h
|
여러 공백문자를 탭문자로 바꾼다.
|
-x
|
여러 공백문자들을 그대로 둔다.
|
-l[num]
|
메모리에 한 번에 둘 수 있는 최대 라인수를 num 라인수로 한다.
초기값은 128라인이다.
|
-xargs 명령 :입력된 데이터를 라인 단위로 읽어서 아규먼트화하는 명령이다.
# xarg --help -> 옵션 확인
# which bash | xargs ls -l
-> which bash 명령의 결과값을 변수로 하여 ls -l 실행. 즉 ls -l 'which bash' 와 같음.
-find 명령: 디렉터리 계층에서 파일과 디렉터리를 검색한다.
<find 옵션>
find옵션
|
의미
|
-name 파일명
|
파일명으로 검색한다.
|
-user 유저명
|
유저명 또는 UID로 검색한다.
|
-group 그룹명
|
그룹명으로 검색한다.
|
-perm nnn
|
퍼미션이 nnn인 파일을 검색한다.(예 –perm 755)
# find. –perm -100 –print
실행 가능한 –x-----파일을 찾는다.
-perm 인자가 마이너스(-) 부호를 가지게 되면 setuid 설정 비트를 포함한 모든 퍼미션 비트들이 검사된다.
|
-type x
|
파일 타입이 x인 파일을 검색한다.
b(블록 특수 파일), c(문자 특수 파일), d(디렉터리), p(파이프), f(정규표현 일반 파일), l(심볼릭 링크 파일), s(소켓)
|
-atime +n
|
접근 시간이 n일 이전인 파일을 검색한다. (access)
|
-atime –n
|
접근 시간이 n일 이내인 파일을 검색한다. (access)
|
-ctime +n
|
n일 이전에 변경된 파일을 검색한다.
(change: 내용 수정이 아니라 모드 변경 또는 접근 시간 변경)
|
-ctime -n
|
n일 이내에 변경된 파일을 검색한다.
(change: 내용 수정이 아니라 모드 변경 또는 접근 시간 변경)
|
-mtime +n
|
n일 이전에 내용이 수정된 파일을 검색한다. (modify)
|
-mtime –n
|
n일 이내에 내용이 수정된 파일을 검색한다. (modify)
|
-empty
|
파일명이 비어있고(0 bytes) 일반 파일이거나 디렉터리를 검색한다.
|
-newer 파일명
|
파일명의 파일보다 최근에 수정된 파일을 검색한다.
|
-size n
|
파일 블록 크기가 n 이상인 파일을 검색한다.
b(블록-기본값), c(bytes), k(kbytes), w(2바이트 단어)
|
-links n
|
링크된 개수가 n인 파일을 검색한다.
|
-print
|
표준 출력
|
-exec 명령
|
검색된 파일을 찾으면 COMMAND 명령을 실행한다.
명령 인자(검색된 파일)는 {}으로 사용하며, 이때 명령 끝은 \;을 사용해야 한다. 즉, 명령구분 문자인 ‘;’을 탈출(\)시켜 주어야 한다.
|
operator
|
-a: and 연산, -o: or 연산, !: not 연산
|
-path 패턴
|
path가 패턴과 일치하는 path에 대해서 검색한다.
|
-regex 패턴
|
파일명이 패턴과 일치하는 정규표현식에 대하여 검색한다.
|
# find . -type f -exec file '{]' \; -> 현재 디렉토리에서 모든 파일을 검색하여 file 명령을 실행
# find $HOME mtime 0 -> 자신의 홈 디렉토리 아래에 24시간 안에 수정된 파일들을 검색하여 출력
# find . -name 'fi*' -> 현재 디렉터리부터 모든 하위 디렉터리까지 fi로 시작하는 모든 파일을 검색하여 출력
# find . -perm 755 -> 현재 디렉터리부터 모든 하위 데렉터리까지 퍼미션이 755인 파일과 디렉터리를 검색
# find /home -newer here.sh -> /home 디렉터리 아래에서 here.sh 파일보다 최근에 수정된 파일을 검색하여 출력
# find /home -size + 1024 -print -> /home 디렉터리 아래에서 파일의 블록 크기가 1024 이상인 파일을 검색하여 출력
# find -linux -type d -print -> lunux 계정의 홈디렉터리(/home/linux) 아래에서 디렉터리들만 검색하여 출력
# find /home \( -name a.out -o -name '*.0' \) -atime +7 -exec rm '{}' \;
-> /home 디렉터리 아래에서 파일명이 a.out 또는 .o로 끝나는 파일을 검색하고, 7일 동안 사용하지 않는 파일이면 rm명령을
사용하여 삭제
# find /tmp -name core -type f -print | xargs /bin/rm -f
-> /tmp 디렉터리 아래에서 파일명이 core 파일을 검색하고 삭제한다.
# find . - type f -mtime +1 | xargs -n 100 rm -f
-> 현재 디렉터리 아래에 1일전에 작성/변경된 파일을 찾아 아규먼트로 치환하고 rm-f 로 100개 단위로 검색된 파일들을 삭제
-tee 명령: 표준 입력으로부터 읽어서 파일로 저장하고 출력하는 명령
<tee 명령 옵션>
tee 옵션
|
의미
|
-a, --append
|
덮어쓰지 않고 주어진 파일에 표준 입력을 추가한다.
|
--help
|
표준 출력으로 사용법을 출력하고 정상적으로 종료한다.
|
-I, --ignore-interrupts
|
인터럽트 신호를 무시한다.
|
--version
|
표준 출력으로 버전 정보를 출력하고 정상적으로 종료한다.
|
# cat/ etc/passwd | grep fedora | tee fedora.txt -> 명령을 출력하면서 fedora.txt로 저장
# cat fedora.txt
# cat /etc/passwd | grep root | tee -a mulit.txt -> 명령을 출력하면서 multi.txt로 저장
# cat multi.txt
<yum 사용법>
1. 업데이트 목록 보기
# yum list updates
2. 업데이트 목록을 다운로드하고, 즉시 업데이트를 설치
# yum update -y
3. 설치된 rpm 패키지 목록 보기
# rpm -qa
# yum list installed
4. gcc 패키지가 설치되어 있는지 확인
# rpm -qa | grep gcc
# yum list installed gcc
5. gcc 패키지를 설치?
# yum install gcc gcc-c++
6. gcc를 패키지 업데이트
# yum update gcc gcc-c++
7. 패키지 이름으로 검색
# yum list 패키지명
# yum list 정규식
# yum list gcc
# yum list gcc*
8. 여러개의 패키지 설치
# yum install gcc gcc-c++
9. 패키지 삭제
# yum remove gcc gcc-c++
10 설치가 가능한 모든 패키지 확인
# yum list all
11. 패키지 그룹보기
# yum grouplist
12. 패키지 그룹 모두 설치
# yum groupinstall "Development Tools"
13. 그룹 패키지를 업데이트하려면?
# yum groupupdate "Development Tools"
14. 그룹패키지를 삭제
# yum groupremove :Development Tools"
15. 아키텍처를 지정하여 설치
# yum install mysql.i386
16. 파일을 가지고 있는 패키지명 확인
# rpm -qf /etc/passwd
# yum whatprovides /etc/passwd
17. 맨페이지 보기
# man yumJ
18. yum fastestmirror 패키지를 설치하면 yum 미러 서버 중 속도가 가장 빠른 서버를 자동으로 찾아서 연결해 준다.
# yum install yum-fastestmirror -y