본문 바로가기

IT/Linux

Shell Script 기초 [RabbitMQ init.d 분석]

회사에서 RabbitMQ를 사용하는데, shell을 분석해보기로 했다. 리눅스는 조금 다뤄봤지만 쉘을 쓸일이 딱히 없어서...잘 모름:(

아무튼, 텍스트들을 통해서 서비스를 실행시킨다는건 매력적인 일인것 같아서 즐겁게 작업했다. 

본래 원노트를 통해서 정리해서 옆에 저 꿀같은 자료들이 보기 좋게 정리되어있지만, 상황상 쭉 나열해야할거 같고,

PPT도 만들었지만... 딱히 공유가 어려울것 같아서 귀찮지만 재정리...ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ








































#!/bin/sh

# 주석기호.

하지만 #! 매직넘버로.

실행 가능한  스크립트라는 것을 나타내는 특별 표시자

( 프로그램이 쉘인지프로그램 언어인지유틸리티인지)

( 파일이 어떤 명령어 해석기의 명령어 집합인지 알려주는 역할여기서는 #!/bin/sh내가 사용하려는 명령어 해석기가 sh  임을 알려 주는 .)

또한, #! 다음엔 정확히 Full Path 기록해야 .

#rabbitmq-server RabbitMQ broker

Rabbitmq-server RabbitMQ broker 라는 것을 코맨트 한것 같음.

# chkconfig: - 80 05

Chkconfig : 자동실행 설정(서비스를 등록하거나 삭제 or 특정 런레벨에서 서비스를 실행시키는 설정)

etc/rc.d/init.d라는 디렉터리에 실행시킬 실행 스크립트를 넣어줘야 함.

 

Chkconfig [런레벨][시작 우선순위] [종료 우선순위

그런데 런레벨을 -  설정하면어떤 레벨에서든 시작하지 않겠다는 부팅시 자동시작하지 않겠다.라는 .

# description: Enable AMQP service provided by RabbitMQ

 chkconfig 적용할 내용에 대한 설명

설명이다 줄을 넘어갈 경우 \ 사용하여 늘려   있다.

### BEGIN INIT INFO

# Provides:        

# Required-Start:    

# Required-Stop:     

# Short-Description: 

# Description:       

### END INIT INFO

LSB Header이다순서를 맞추지 않으면 순서 때문에 issue 발생할 수도 있다.

Init script 의해 제공되는 facility 이름 지정 (유일값일 )

서비스가 시작되는 동안 반드시 사용이 가능한 상태로 있어야 하는 boot facilities

서비스가 종료 되기 전에 절대 종료되어선  되는 boot facilities

Init script 하는 일을 간단하게 설명

Init script 하는 일을 보다 자세히 설명

$remote_fs $network 들은 facility names이다.

# Source function library.

. /etc/init.d/functions

 

Initscript 서비스가 실행중일때 initscript 실행하거나 서비스가 비활성화 상태일  initscript 멈추는 과정에서 민감하게 행동해야한다관계없는 유저의 프로세스들을 죽이면  된다따라서 해결책으로, init-script function들을/etc/init.d/functions 통해서 제공하는 방법을 택했고 init-script 실행할때 먼저 . /etc/init.d/functions 실행하게 된다.

PATH=/sbin:/usr/sbin:/bin:/usr/bin

NAME=rabbitmq-server

DAEMON=/usr/sbin/${NAME}

CONTROL=/usr/sbin/rabbitmqctl

DESC=rabbitmq-server

USER=rabbitmq

ROTATE_SUFFIX=

INIT_LOG_DIR=/var/log/rabbitmq

PID_FILE=/var/run/rabbitmq/pid

 

START_PROG="daemon"

LOCK_FILE=/var/lock/subsys/$NAME

PATH  이하 내용들 정의.

Call  때는 $SMTHLDB

test -x $DAEMON || exit 0

test -x $CONTROL || exit 0

Test 파일의 각종 상태를 검사하여 결과를 알려주는 작업을 한다.

Test -옵션 파일명을 사용한다

여기서 -x 사용하였는데, -x 경우 파일이 실행하기 권한이 있으면 참을 반환한다.

Test 대신, [] 대괄호를 사용하는 방법도 존재한다

또한 ||  or 명령으로 참이 나오면 진행을 멈춘다.(exit n  쉘을 종료하고, n을 반환 함. N 대한 코드가 따로 정리됨.)

 

따라서 데몬이 실행이 되면 다음 test 넘어가고

데몬이 실행되지 않으면 정상종료를 한다는 얘기

RETVAL=0

변수 설정

Set -e

Set 스크립트에서 옵션을 켜고   사용한다

여기서는  -e  사용하여   번째 에러에서 스크립트를 취소(0 이 아닌 상태로 종료하는 명령어)를 적용하였다.

[ -f /etc/default/${NAME} ] && . /etc/default/${NAME}

[]  test와 같다. True false 반환함.

&& 명령이 거짓이  때까지 명령을 수행한다.

(|| 참이 나올  까지)

따라서

[ -f /etc/default/${NAME} ]  = test -f /etc/default/rabbitmq-server  같다.

, /etc/default/rabbitmq-server이 존재하며 정규 파일일 경우 다음 명령을 수행하라는 뜻이며,

다음 명령은  파일을 실행하라는 명령이다.

정리하면 /etc/default/rabbitmq-server 파일이 존재하고 정규파일이면 실행시키라는 .

ensure_pid_dir () {

    PID_DIR=`dirname ${PID_FILE}`

    if [ ! -d ${PID_DIR} ] ; then

        mkdir -p ${PID_DIR}

        chown -R ${USER}:${USER} ${PID_DIR}

        chmod 755 ${PID_DIR}

    fi

}

PID_DIR 만드는 functions

PID_DIR 변수를 정의하고,

만약, PID_DIR 디렉터리가 아니면

PID_DIR이란 Dir 구성한다. (mkdir 옵션 -p  path까지의 모든 계층구조를 만들라는 , -m 쓰이는데권한 설정이다.)

그리고 chown 사용하여 USER:USER 소유로 PID_DIR 소유를 부여

Chmod 권한은 755 설정함

그리고 if 종료

 

remove_pid () {

    rm -f ${PID_FILE}

    rmdir `dirname ${PID_FILE}` || :

}

PID_FILE 삭제하는 function

프롬프트 없이 PID_FILE 삭제

PID_FILE 디렉터리 삭제.

 

start_rabbitmq () {

    status_rabbitmq quiet

    if [ $RETVAL = 0 ] ; then

        echo RabbitMQ is currently running

    else

        RETVAL=0

        ensure_pid_dir

        set +e

        RABBITMQ_PID_FILE=$PID_FILE $START_PROG $DAEMON \

            > "${INIT_LOG_DIR}/startup_log" \

            2> "${INIT_LOG_DIR}/startup_err" \

            0<&- &

        $CONTROL wait $PID_FILE >/dev/null 2>&1

        RETVAL=$?

        set -e

        case "$RETVAL" in

            0)

                echo SUCCESS

                if [ -n "$LOCK_FILE" ] ; then

                    touch $LOCK_FILE

                fi

                ;;

            *)

                remove_pid

                echo FAILED - check ${INIT_LOG_DIR}/startup_\{log, _err\}

                RETVAL=1

                ;;

        esac

    fi

}

Rabbitmq 실행시키는 function이다.

Status_rabbitmq function quiet이란 것을 parameter 넘김.

만약 RETVAL 0이면

RabbitMQ 현재 사용중이란 message 띄워줌

그것이 아니라면,

RETVAL 0으로 설정하고

Ensure_pid_dir 실행하여 PID_DIR 잡아주고.

Bash set 통해 error setting 변경해준다.

그리고 RABBITMQ_PID_FILE 정의해준다

그리고, "daemon" /usr/sbin/rabbitmq-server  통하여 서비스를 실행시킨다. (\  다음 문장도 연속적으로  라인처럼 처리하라는 명령)

출력값은 log 작성하고, error값은 err 작성 그리고 (0<&) 통해 stdin 종료, & 백그라운드로 실행.

$CONTROL 실행이 모두 종료될 때까지 기다렸다가, $PID_FILE 수행한다그리고 모둔 출력값을 출력하지 않는다.

RETAVAL 가장 최근에 실행되어 반환된 종료값을 넣어준다.

Bash 옵션을 -e로 세팅해준다. Error나면 바로 반환

만약 RETVAL 0 경우

SUCCESS 박아주고

LOCK_FILE null 아닐경우, LOCK_FILE touch (수정시간 조절)

 

 

 

 외의 모든 문자의경우

Pid 삭제하고

FAILED - check ${INIT_LOG_DIR}/startup_\{log, _err\}  출력하고,

RETVAL 1 정의한다.

 

 

 

 

stop_rabbitmq () {

    status_rabbitmq quiet

    if [ $RETVAL = 0 ] ; then

        set +e

        $CONTROL stop ${PID_FILE} > ${INIT_LOG_DIR}/shutdown_log 2> ${INIT_LOG_DIR}/shutdown_err

        RETVAL=$?

        set -e

        if [ $RETVAL = 0 ] ; then

            remove_pid

            if [ -n "$LOCK_FILE" ] ; then

                rm -f $LOCK_FILE

            fi

        else

            echo FAILED - check ${INIT_LOG_DIR}/shutdown_log, _err

        fi

    else

        echo RabbitMQ is not running

        RETVAL=0

    fi

}

Function 시작한다

 status_rabbitmq quiet으로 수행.

만약 RETVAL 0이면 set -e해제

 

status_rabbitmq() {

    set +e

    if [ "$1" != "quiet" ] ; then

        $CONTROL status 2>&1

    else

        $CONTROL status > /dev/null 2>&1

    fi

    if [ $? != 0 ] ; then

        RETVAL=3

    fi

    set -e

}

우선 set +e 통해 error 나면 스크립트를 취소하는 설정을 해제했다.

Status_rabbitmq quiet으로 넘어오면.(start에서 넘겨줌)

만약 넘어온 변수  첫째가 quiet 같지 않으면

$CONTROL (/usr/sbin/rabbitmqctl) 라고 하면, rabbitmqctl status  인한 출력 값을 바로 화면에 뿌려주지만,

Status 2>&1이라고 하면,  error  까지도 모두 화면에 뿌려주는 역할을 한다.

만약 넘어온 변수  첫째가 quiet 같으면

Rabbitmqctl status  인한 출력 값과 에러 값이 있을지라도 출력하지 않겠다.

 

그리고 만약가장 최근에 실행한 명령의 종료값이 0 같다면, RETVAL 3으로 정의하겠다.

 

그리고 bash 설정을 통해 error  경우  줄에서 스크립트를 종료하겠다.

 

rotate_logs_rabbitmq() {

    set +e

    $CONTROL rotate_logs ${ROTATE_SUFFIX}

    if [ $? != 0 ] ; then

        RETVAL=1

    fi

    set -e

}

 

restart_running_rabbitmq () {

    status_rabbitmq quiet

    if [ $RETVAL = 0 ] ; then

        restart_rabbitmq

    else

        echo RabbitMQ is not runnning

        RETVAL=0

    fi

}

 

case "$1" in

    start)

        echo -n "Starting $DESC: "

        start_rabbitmq

        echo "$NAME."

        ;;

    stop)

        echo -n "Stopping $DESC: "

        stop_rabbitmq

        echo "$NAME."

        ;;

    status)

        status_rabbitmq

        ;;

    rotate-logs)

        echo -n "Rotating log files for $DESC: "

        rotate_logs_rabbitmq

        ;;

    force-reload|reload|restart)

        echo -n "Restarting $DESC: "

        restart_rabbitmq

        echo "$NAME."

        ;;

    try-restart)

        echo -n "Restarting $DESC: "

        restart_running_rabbitmq

        echo "$NAME."

        ;;

    *)

        echo "Usage: $0 {start|stop|status|rotate-logs|restart|condrestart|try-restart|reload|force-reload}" >&2

        RETVAL=1

        ;;

esac

 

exit $RETVAL