IT/인프라

DBA를 위한 Linux 쉘 스크립팅 입문(3)

swhwang 2017. 3. 23. 22:57

BASH 스크립트

스크립트는 (사용자의 개입이 없는) 자동화된 프로세스의 일부로써, 또는 (사용자의 입력을 요구하는) 인터액티브한 작업의 일부로써 실행될 수 있습니다. 파일의 실행 권한을 갖고 있다면, 커맨드라인에서 파일 이름을 입력하여 직접 실행하는 것도 가능합니다. 파일의 실행 권한은 없는 대신 읽기 권한을 갖고 있는 경우에도 sh명령을 이용하여 스크립트를 실행할 수 있습니다.

스크립트가 사용자의 입력 없이 실행되도록 프로그래밍된 경우, 다양한 호출 방법을 이용할 수 있습니다. 스크립트를 백그라운드에서 실행하여, 세션이 끊어진 경우에도 계속 실행되도록 하려는 경우는 아래와 같이 커맨드를 입력합니다:

nohup /path_to_dir/myscript_here.sh &

이 옵션은 오랜 실행시간을 갖는 스크립트를 실행할 때 유용하게 활용됩니다. at 커맨드는 정해진 시간에 스크립트를 실행하는 명령, cron은 스케줄 기반으로 스크립트를 실행하기 위한 명령입니다.

지금부터 스크립트의 출력 전환, 루프, 조건부 로직, 변수 할당 등에 관련한 기초적인 내용을 설명하겠습니다.

print_args.sh. 매개변수(argument)는 커맨드의 오른쪽에 위치하여 스크립트에 함께 전달되는 문자열을 의미합니다. 첫 번째 매개변수에

접근하기 위해서는 $1 변수가 사용됩니다. $0 변수는 스크립트의 이름을 저장하는 용도로 사용됩니다. $# 변수는 스크립트에서 사용되는 매개변수의 수를 의미합니다. 스크립트에서 전달되는 매개변수를 일괄적으로 확인하기 위해서는 while 루프와 shift 커맨드를 사용하는 것이 일반적입니다. 이 커맨드를 이용하면 매개변수 리스트에 존재하는 모든 매개변수를 순서대로 확인하는 것이 가능합니다.

while [ $# -ne 0 ]

do

echo $1

shift

done

스크립트가 파일 이름을 매개변수로 받고 (또는 파일 이름의 입력을 요구하고) 뒷부분에서 해당 파일을 읽는 작업을 수행하는 경우, 먼저 파일의 접근 및 읽기가 가능한지 확인하는 과정을 넣어 주어야 합니다. 예를 들어, 백업된 컨트롤 파일 중 하나를 선택하는 과정을 포함하는 복구용 스크립트의 경우, 아래와 같은 확인 과정이 필요합니다.

if [ ! -r $1 ]; then # not exists and is readable

echo "File $1 does not exist or is not readable."

exit;

fi

실제로 파일에 대해 테스트를 수행하기 위한 코드가 아래와 같습니다.

if [ ! -r $1 ];

대괄호([]) 안의 컨텐트가 TRUE인 것으로 평가되는 경우, if와 fi 사이에 정의된 커맨드가 실행되게 됩니다. 실제 테스트할 내용은 대괄호 안에 정의됩니다. 느낌표는 NOT의 의미를 갖습니다. -r 옵션은 파일이 읽기 가능한지를 점검합니다. 위 스크립트에서는 스크립트와 함께 전달된 첫 번째 매개변수를 테스트하고 있습니다. 다른 테스트 옵션( -d )을 사용하면, 입력된 항목이 디렉토리인지 확인할 수 있습니다 (is_a_directory.sh 참고).

do_continue.sh. 다음은 여러 가지 목적으로 사용자 입력을 읽어 들이는 일련의 커맨드로 구성된 스크립트입니다. 데이터의 손실 또는 예기치 않은 에러가 발생할 수 있는 프로세스를 실행하기 전에, 다음 단계의

커맨드를 정말로 실행할 것인지 사용자의 확인을 거치는 절차가 필요할 수 있습니다. 아래 예제에서는 사용자가 정말로 계속하기를 원하는지 묻는 프롬프트를 띄운 후, 커맨드라인으로부터 doContinue라는 이름의 변수를 읽어 들이고, 사용자가 입력한 값을 평가하고 있습니다. 사용자가 “y” 이외의 다른 값을 입력한 경우, 스크립트를 종료한다는 메시지를 사용자에게 띄운 후 스크립트의 나머지 부분을 실행하지 않고 바로 종료 처리합니다.

doContinue=n

echo -n "Do you really want to continue? (y/n) "

read doContinue

if [ "$doContinue" != "y" ]; then

echo "Quitting..."

exit

fi

적절한 권한과 환경을 갖춘 사용자만이 스크립트를 실행할 수 있도록 하는 것은 매우 중요합니다. 이 경우 스크립트를 실행하는 사용자가 누구인지 확인하는 과정이 필요하게 됩니다. 커맨드를 역인용부호(‘) 문자로 둘러싸면, 커맨드의 실행 결과가 스크립트로 반환되도록 할 수 있습니다. 아래 예제는 whoami 명령을 사용하여 현재 로그온한 사용자를 반환하고, date 커맨드를 이용하여 날짜를 확인하고 있습니다.

echo "You are logged in as 'whoami'";

if [ ‘whoami‘ != "oracle" ]; then

echo "Must be logged on as oracle to run this script."

exit

fi

echo "Running script at ‘date‘"

오라클 데이터베이스와 연동하도록 작성된 스크립트에서는 데이터베이스 암호와 같은 민감한 정보가 사용될 수 있습니다. stty –echo 커맨드는 스크린 echo를 비활성화하여 읽기 작업 과정에서 입력된 정보가 스크린 상에 표시되지 않도록 합니다. 암호 정보를 읽어 들여 변수(아래 예제의 pw)에 저장하고 난 뒤에는 다시 stty echo 명령을 사용하여 디스플레이를

활성화합니다.

stty -echo

echo -n "Enter the database system password: "

read pw

stty echo

Oracle 스크립트

파일 중 일부는 오라클 설치환경에 지정된 위치에 존재합니다. 오라클 인벤토리는 /etc/oraInst.loc 파일을 통해 확인할 수 있습니다. /etc/oratab 파일은 서버에 설치된 데이터베이스(또는 다른 오라클 프로그램)을 확인할 때 유용합니다.

get_inv_location.sh. 이 스크립트는 앞의 예제에 비해 덜 직관적입니다. 스크립트를 단계별로 나누어서 그 내용을 이해해 보기로 하겠습니다.

먼저 인벤토리 경로를 확인하기 위해서, (파일의 컨텐트를 출력하는) cat 커맨드의 실행 결과를 (주어진 패턴과 일치하는 라인을 출력하는 유틸리티인) grep으로 파이프(pipe) 처리합니다. 예제에서는 inventory_loc이라는 문자열을 포함하는 라인을 검색하고 있습니다.

cat /etc/oraInst.loc | grep inventory_loc

오라클이 2회 이상 설치되어 두 개 이상의 인벤토리 경로가 존재하는 경우, “#” 기호로 주석 처리된 라인을 제외하도록 설정할 수 있습니다. –v 옵션은 주어진 패턴을 포함하는 라인을 제외하도록 합니다.

cat /etc/oraInst.loc |grep -v "#"|grep inventory_loc

위 커맨드의 실행 결과 예가 아래와 같습니다:

inventory_loc=/u01/oraInventory

“>” 리다이렉션을 사용하면 표준 출력을 파일로 재설정할 수 있습니다. 파일이 존재하지 않는 경우에는 생성됩니다. 또 파일이 이미 존재하는 경우에는 덮어쓰기 처리됩니다.

cat /etc/oraInst.loc|grep -v "#"|grep inventory_loc > tmp

인벤토리 위치를 확인했다면, 이제 등호(=) 기호 앞의 데이터를 제거할

차례입니다. 이번에는 cat 커맨드의 실행 결과를 (가변 길이의 필드를 분할하는 용도로 자주 사용되는 패턴-스캐닝 언어인) awk를 이용하여 여러 개의 토큰(token)으로 분할합니다. –F 옵션은 awk가 등호 기호를 구분기호(delimeter)로 사용하도록 설정하는데 이용됩니다. 그런 다음 두 번째 토큰($2), 다시 말해 등호 기호 오른쪽의 전체 문자열을 출력합니다. 결과적으로 인벤토리 경로(/u01/oraInventory)가 얻어집니다.

cat tmp | awk -F= '{print $2}'

원하는 결과가 얻어졌다면 임시 파일은 삭제 처리합니다.

rm tmp