2008. 6. 2.

실무에서 자주 사용되는 쉘 스크립트

실무에서 자주 사용되는 쉘 스크립트

<1>
(아파치 자동 재시작 스크립트)



리눅스 시스템을 관리하다 보면, 쉘 스크립트의 필요성을 절실히 느끼게 된다. 저자는 쉘프로그램관련 강좌(bash, awk, sed)를 쓰고 싶었다. bash문법, awk문법, sed사용법을 묶은 강좌를 만들고 싶었다.. 하지만, 이것은 나를 위한 정리일 뿐이다. 내가 정리하여 강좌를 쓴다면, 읽는 사람들은 필요하지도 않은 문법을 머리속에 넣어야 하고, 그 조합으로 실무에 적용시키기위해서 수 없이 많은 노력을 할 것이다. 이런 강좌는 필요하지 않다. 정리는 man 페이지를 보면 자세하게 나와 있다. 저자는 리눅스 시스템 관리에 자주 사용되는 쉘 스크립트를 경험담을 담아 강좌를 써 보려고 한다. 최대한 간단하게 만들어서 누구든 쉽게 써 보고 이해하기 쉽게 쉘스크립트를 만들고, 설명하려 할 것이다.

처음 시작할 쉘 스크립트는 '아파치 자동 재시작 스크립트'이다.
서 버를 계속해서 모니터링 해야 한다거나, 특정 수치를 초과 했을 때 조치를 해 줘야 하는 경우가 발생한다. 물론 그 문제점이 일어나지 않게 원인을 파악하여 처리하는 것이 가장 좋지만, 그럴 만한 시간이 없다면, 자동으로 실행되는 쉘 스크립트를 만들어서 띄워 두면 된다.

금번 강좌에서 아파치 프로세스가 특정 수치만큼 생성 되었을 때, 아파치를 자동 재 시작 해주는 쉘 스크립트를 만들어 보도록 하겠다.

먼저, 어떤일을 할 것인지 생각 해 보자...


1) 아파치 프로세스 수를 어떻게 알지??
기본적으로 아파치 프로세스 이름은 'httpd'이다 물론 다른 이름을 수 있다. 이 프로세스가 얼마나 떠 있는지 조사하려면?
ps
명령어가 떠 오를 것이다.
그리고 httpd 프로세스만 잡아서 갯수를 세려면?
grep 명령어와 wc 명령어가 필요하다.

이런 3명령어를 조합해서 결과를 만들어 보자.

ps -e : 현재 서버에서 실행중인 모든 프로세스들을 보여준다.

ps -e | grep -w httpd : 현재 서버에서 실행중인 프로세스 중 httpd 문자가 포함된 프로세스만 잡아 보여준다.
'-w' 옵션은 단어 단위 검색이다. httpds 이런 이름이 있어도 포함시키지 않겠다는 의미이다.

ps -e | grep -w httpd |wc -l: 위에서 잡은 결과의 줄 수를 세어 준다.
이렇게 하면 프로세스 수를 구할 수 있다.

위 명령을 단순화 시키려면,
pgrep -x httpd | wc -l : 'pgrep'은 프로세스이름에서 단어가 포함된 프로세스들의 pid를 얻기 위한 명령이다.
'-x' 옵션은 'grep'의 '-w'옵션처럼 단어 단위로 검색하기 위한 옵션이다.



2) 아파치를 재시작하는 방법?
아파치 서버를 운영한다면, 이 방법은 알고 있을 것이다.
컴파일 설치 했다면, /usr/local/apache/bin/apachectl restart
또 다른 방법은 apachectl stop, apachectl start 등의 방법이 있으며,
다른 방법은 아파치 프로세스를 모두 죽이고 시작하는 방법이 있을 것이다.
pgrep -x httpd | xargs kill -9
여기서 pgrep은 위에서 설명했고, xargs라는 명령이 뭘까?
xargs는 표준 입력으로 받은 내용을 xargs의 인자로 기술하는 명령어(kill -9)의 인자로 넣는 명령어이다.
다음 예를 보자.

pgrep -x httpd
5598
5843

실행결과가 위와 같다면, 5598과 5843은 httpd의 PID임을 알수 있다.
위 프로세스를 모두 죽이기 위해서는

kill -9 5598
kill -9 5843

이런 명령을 내려야 하며, 100개라면 100번? 물론 killall 이라는 좋은 명령어가 있지만, 잘 죽지 않을 때는 kill 명령으로 죽여야 한다.


위와 같은 일을 쉽게 해 줄 수 있는 명령이 xargs 이다.
pgrep -x httpd | xargs kill -9
이렇게 하면,
pgrep -x httpd 의 결과인 5598, 5843 이 자동 kill -9 명령어 뒤에 붙어 실행 되는 것이다.
이 명령어 하나면, 프로세스가 1000개라도 상관 없다^^



3) 자동으로 실행 시켜 주는 반복 작업 시작..
만약 문제가 있는 시스템이라면, 시스템 관리자는 '1)'의 명령을 내려 프로세스를 수를 확인하고, 생각했던 수치 보다 많으면 '2)'번 명령어를 내려서 아파치를 재 시작 할 것이다. 언제 발생할지도 모르는 것 때문에 지속적으로 보고 있을 수 없고, 자리를 비울 수 도 없다.

bash 쉘에서는 반복작업을 위해서 여러가지 제어문을 제공한다.
지금 사용할 문법은 while 문이다.

while ( 조건 ) ; do
<문장>
done

위 '조건'이 만족하는한 '<문장>'은 계속 실행된다.

while ( true ) ; do
ls
done

위와같이 입력한다면, 계속.. 'ls'명령어를 실행 시킬 것이다.
대부분의 언어에서 그렇듯 반복문에서 빠져 나올려면, 'break' 문법이 있다.

while ( true ) ; do
ls
break
done


4) 반복 실행하여 프로세스가 특정 수치 이상이면 아파치 재 시작
우리의 목적한 일을 할 수 있는 쉘 프로그램을 만들어 보자.

while ( true ) ; do
if [ "`pgrep -x httpd | wc -l`" -ge "500" ] ; then
/usr/local/apache/bin/apachectl restart
fi
done

이렇게 작성하면 끝!!!
if 문은 조건을 비교하여 조건이 맞으면 then 이하의 문장을 실행한다. 문법은 다음과 같다.

if [ 조건 ] ; then
<문장>
fi

'조건'을 비교하기 위해서 '-ge' 를 썼다. ge(greater than or equal)이다. 크거나 같다의 의미.. 그렇다면,
gt(크다), le(작거나 같다), lt(작다), eq(같다) 등이 있을 것이라 예상할 수 있다.


5) 문제점 발견!!
위 쉘 스크립트를 돌려 두니.. 너무 자주 비교해서, 쉘스크립트가 서버에 부하를 준다..
그렇다면, sleep으로 비교 시간을 늘려 준다.

while ( true ) ; do
if [ "`pgrep -x httpd | wc -l`" -ge "500" ] ; then
/usr/local/apache/bin/apachectl restart
fi
sleep 1
done

위와같이 'sleep 1'을 입력하였다면, 1초가 쉬어라는 것이다. 1초간 쉬었다가 다시 비교하게 된다.



우리는 이것으로 원하는 결과를 얻었다.!
이젠 지속적으로 프로세스를 수를 확인하여 아파치를 재 시작해야 하는 노가다는 하지 않아도 된다. 하하하!!



이것으로 ' 실무에서 자주 사용되는 쉘 스크립트 #1' 강좌를 마무리 하겠습니다.
본 강좌의 설명이 어렵거나, 잘못된 부분이 있으면 언제든지 따끔한 지적을 바랍니다.



<2>

(MySQL DB관리 유틸리티)



지난번, 강좌(apache 자동 재 시작 프로그램)에 이어 실무에서 자주 사용되는 쉘 스크립트에 대한 강좌를 써 내려 가겠다. 물론 최대한 쉽고 최소한의 라인 수로 작성 가능한 쉘 스크립트에 대한 강좌를 쓸 것이다.
금번 강좌는 MySQL을 쉽게 관리 할 수 있는 툴이다. 서버 관리를 하다 보면, mysql 접속하여 여러가지 sql문으로 서버 상태를 알아 보거나, 모니터링 해야 할 때가 있다. 이럴 때 마다 로그인을 해서, sql문을 얻어내는 것은 아주 귀찮은 일이고, 또 익숙하지 않으면 아주 오랜 시간이 소요되는 작업이다. 내가 만들고자 하는 스크립트는 이런 작업을 쉽게 해 줄 수 있는 스크립트를 만드는 것이다.

먼저, 어떤일을 할 것인지 생각 해 보자...


1) MySQL의 프로세스 리스트를 보려면?
mysql의 프로세스 리스트는 ps 등의 명령어로 쉽게 볼 수 있다. 난 그런 것을 원하는 것이 아니고, 각 프로세스들이 하는 일들을 보고 싶다. mysql은 다음과 같은 방법으로 이런 일이 가능하게 제공한다.

mysqladmin -u root -p processlist

또는

mysql 접속한 상태에서
show processlist;

나는 일괄적으로 다음과 같은 방법으로 mysql 명령을 실행 시킬 것이다.

echo "쿼리;" | mysql -u"root" -p"비밀번호"

위 명령어는 다음과 같다.
echo "쿼리; " : "쿼리;"를 출력한다.
| : 파이프, 앞 명령어의 내용을 뒷 명령어의 표준 입력으로 넣는다.
mysql -u"root" -p"비밀번호" : mysql 서버에 접속한다. "비밀번호"는 서버의 비밀번호를 넣어준다.

우리가 원하는 일은 다음과 같이 한다.

echo "show processlist;" | mysql -u"root" -p"비밀번호"





2) root로 그냥 접속만 하려면?
'1)'의 프로세스 리스트를 보는 것 보다 쉽다. 단순하게..

mysql -u"root" -p"비밀번호"

이렇게만 하면 끝난다.



3) MySQL에 존재하는 database 들을 보려면?
'1)'의 프로세스 리스트를 응용하면,

echo "show databases;" | mysql -u"root" -p"비밀번호"

이렇게만 하면 끝난다.


이정도 했으면, 원하는 쿼리들을 위와 같은 방법으로 자유롭게 추가 할 수 있을 것이다.
내가 원하는 것은 위 명령어들을 모아서 쓰기 편리한 메뉴 방식으로 만드는 것이다.
어떻게 할까???
나는 키보드로 특정 문자들을 입력받아 변수에 넣을 것이다. 그리고 그 변수에 따라 위 명령어들을 실행 시킬 것이다. 이런 작업들을 특정 문자가 입력될 때 까지 반속 할 것이다.



4) 쉘 프로그램에서 키보드 입력 받기
나는 쉘 프로그램에서 키보드로 입력을 받아서 변수에 넣을 것이다. 어떻게 해야 할까

read <변수>

no라는 변수에 입력값을 넣으려면 다음과 같이 한다.
read no

이렇게 하면, '엔터'키를 누를 때 까지 입력을 받는다.

read no
echo "$no"

위와같이 하면 간단하게 입력받은 문자를 출력해서 보여 줄 수 있다.


5) 입력된 문자에 따라서 프로그램 실행 시키기
'4)'에서 입력받은 문자에 따라서, 프로그램을 실행시키기 위해서는 case문을 사용해야 한다.
다음과 같다.

case <변수> in
"값" )
<명령어> ;;
"값" )
<명령어> ;;
esac

위와같다.
위 방법을 우리가 목표 하는 것에 적용 시키면.

먼저 메시지를 뿌려 준다.

echo '
1. 프로세스 리스트 보기
2. mysql 접속
3. database 리스트 보기
'
echo -n "번호 선택 : "
read no

case $no in
"1" )
echo "show processlist;" | mysql -u"root" -p"비밀번호" ;;
"2" )
mysql -u"root" -p"비밀번호" ;;
"3" )
echo "show databases;" | mysql -u"root" -p"비밀번호" ;;
esac


위와같이 작성하면, 위 쉘 스크립트를 실행 시키면, 리스트가 나오며 입력 대기 할 것이고, 1,2,3 중 하나의 번호를 누르면 지정 명령어가 실행 될 것이다..
그렇다면, 다른 문자를 입력하면?? 조건에 만족하는 문자가 없으면 그냥 지나간다...



6) 실행이 끝나면 다시 메뉴 보여주기
명령어를 실행 시키고 빠져 나가 버리면, 다른 메뉴를 선택하기 위해서 또 명령어를 실행시켜야 한다. 하나의 명령어 실행 시키고 다시 메뉴 리스트를 반복적으로 보여 주기 위해서는 이전 강좌에서 배웠던, while 문을 사용하여 계속 실행 시키도록 해 보자.

while ( true ) ; do
<프로그램>
done

위와같은 문법을 우리 스크립트에 적용하면,

while ( true ) ; do
clean
echo '
1. 프로세스 리스트 보기
2. mysql 접속
3. database 리스트 보기
'
echo -n "번호 선택 : "
read no

case $no in
"1" )
echo "show processlist;" | mysql -u"root" -p"비밀번호" ;;
"2" )
mysql -u"root" -p"비밀번호" ;;
"3" )
echo "show databases;" | mysql -u"root" -p"비밀번호" ;;
esac
done


이렇게 하면, 선택한 명령어 실행이 끝나면, 다시 메뉴를 보여 줄 것이다.
clear 명령어는 화면의 내용을 지우라는 명령어이다. 메뉴가 줄줄줄~~ 내러 가는 일을 방지하기 위함니다.




7) 이 반복 메뉴에서 빠져 나오려면??
한 명령어 실행이 끝나면, 메뉴가 나올 것이다. Ctrl + C 키를 눌러 빠져 나올 수 있지만, 그건 좀 아닌 것 같은데... 하나의 항목을 추가 했다. 메뉴에서 'q'키를 누르면 빠져 나오게 한다.



while ( true ) ; do
clean
echo '
1. 프로세스 리스트 보기
2. mysql 접속
3. database 리스트 보기
q. 끝내기
'
echo -n "번호 선택 : "
read no

case $no in
"1" )
echo "show processlist;" | mysql -u"root" -p"비밀번호" ;;
"2" )
mysql -u"root" -p"비밀번호" ;;
"3" )
echo "show databases;" | mysql -u"root" -p"비밀번호" ;;
"q" )
exit 0 ;;
esac
done

위 쉘스크립트에서 'q'키를 누르면 exit 명령어를 실행시켜 빠져 나오게 된다. 물론 정상 종료이기 때문에 0을 리턴한다..




8) "비밀번호"가 바뀌면 다 고쳐 줘야 하나요??
비밀번호가 바뀌면 위 스크립트에서 "비밀번호" 부분을 모두 수정해야 한다. vi 등의 에디터에 치환 기능이 있어 한번에 치환 한다면 문제가 없다. 하지만, 비밀번호가 'mysql' 이라면, 얘기는 달라진다,.. 명령어인 'mysql'이 함께 바뀌기 때문에.. 하나 하나 수작업으로 고쳐야 한다.
변수라는 개념을 써서 이 부분을 해결 해 보자.

a="변수"
echo $a

이렇게 하면 출력값은 ?

변수

위와같이 출력된다. 변수라는 개념을 우리의 쉘스크립트에 적용시키면?

mysqlpw="비밀번호"

while ( true ) ; do
clean
echo '
1. 프로세스 리스트 보기
2. mysql 접속
3. database 리스트 보기
q. 끝내기
'
echo -n "번호 선택 : "
read no

case $no in
"1" )
echo "show processlist;" | mysql -u"root" -p"$mysqlpw" ;;
"2" )
mysql -u"root" -p"$mysqlpw" ;;
"3" )
echo "show databases;" | mysql -u"root" -p"$mysqlpw" ;;
"q" )
exit 0 ;;
esac
done

위와 같이 보라색 부분을 수정했다. 이렇게 수정하면, 상단의 변수만 수정 하면 다른 부분은 수정할 필요없이 적용되는 것이다.



우리는 이것으로
쉘 스크립트의 case문과, 변수, 키보드로부터 입력받기 를 알게 되었다.
여러가지 편리한 기능들을 넣어 둔다면, 나만의 관리툴로 만들 수 있을 것이다. [뿌듯]


이것으로 ' 실무에서 자주 사용되는 쉘 스크립트 #2' 강좌를 마무리 하겠습니다.
본 강좌의 설명이 어렵거나, 잘못된 부분이 있으면 언제든지 따끔한 지적을 바랍니다.


<3>

댓글 없음: