Git WebHooks + 스 크 립 트 를 통 해 발표 코드 의 셸 스 크 립 트 를 자동 으로 업데이트 합 니 다.

이 글 은 'Git WebHooks + 스 크 립 트 를 통 해 게시 코드 를 자동 으로 업데이트 합 니 다' 라 는 내용 으로 게시 코드 를 자동 으로 업데이트 하 는 스 크 립 트 작성 방향 을 제공 합 니 다.본문의 각본 은 앞의 문장 중의 사고방식 과 그다지 다 르 지 않다.이 스 크 립 트 는 capistrano 의 일부 사상 과 이념 을 근거 로 간단 하고 이해 하기 쉬 운 셸 스 크 립 트 로 capistrano 가 원래 실현 한 자동화 배치 부분 을 실현 합 니 다.
스 크 립 트 의 특징 과 기능:
  • 스 크 립 트 의 심 볼 릭 링크 문 제 를 해결 하고 스 크 립 트 작업 디 렉 터 리 를 정확하게 가 져 옵 니 다 (tomcat 스 크 립 트 에서 배 웁 니 다).
  • 색상 에 따 르 면 서로 다른 등급 의 정 보 는 서로 다른 색상 으로 표 시 됩 니 다 (모두 두 가지 방안 입 니 다. 앞의 하 나 는 이름 모 를 외국 엔지니어 에 게 서 얻 었 고 그 다음 하 나 는 lnmp 1.2 스 크 립 트 에서 얻 었 습 니 다).
  • capistrano 디 렉 터 리 구 조 를 생 성 합 니 다.
  • 만 료 된 디 렉 터 리 와 파일 을 삭제 합 니 다.
  • 배치 요구 가 만족 하 는 지, 예 를 들 어 디스크 공간의 수요 등 을 검사 하고 다른 요 구 는 추가 해 야 한다.
  • 배치 실패 후 굴 러 가기;
  • 항목 을 폐기 한 후 항목 을 삭제 합 니 다.
  • 스 크 립 트 에서 가능 한 한 잘못 사용 (이상 판단) 과 일부 세부 사항 을 고려 합 니 다.

  • 스 크 립 트 에 존재 하 는 알려 진 문제:
    (1) 스 크 립 트 에 TODO 가 몇 개 있 는데 개선 해 야 합 니 다.
    (2) reposcory 디 렉 터 리 가 잠시 사용 되 지 않 았 습 니 다.
    (3) git 버 전 번호 가 져 오기;
    (4) 배치 후 생 성 된 로 그 는 최적화 되 어야 한다.
    (5) 스 크 립 트 는 기본적으로 영어 (Chinglish) 를 주석 으로 사용 하고 일부 주석 이 불완전 할 수 있 습 니 다.
    (6) 존재 할 수 있 는 다른 문제;
    후기 개선 과 일부 수요 변경 을 위해 이 스 크 립 트 를 쉽게 얻 을 수 있 도록 github 에서 가 져 올 수 있 습 니 다. bug, issue 및 improvement 을 제출 하 는 것 을 환영 하고 받 아들 일 수 있 습 니 다.
    github 주 소 는:
    https://github.com/DingGuodong/BashShellHeader/blob/master/example-deploy.sh
    스 크 립 트 내용 은 다음 과 같 습 니 다.
    #!/bin/bash
    
    # Public header
    # =============================================================================================================================
    # resolve links - $0 may be a symbolic link
    PRG="$0"
    
    while [ -h "$PRG" ]; do
      ls=`ls -ld "$PRG"`
      link=`expr "$ls" : '.*-> \(.*\)$'`
      if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
      else
        PRG=`dirname "$PRG"`/"$link"
      fi
    done
    
    # Get standard environment variables
    PRGDIR=`dirname "$PRG"`
    
    
    # echo color function
    function cecho {
        # Usage:
        # cecho -red sometext     #Error, Failed
        # cecho -green sometext   # Success
        # cecho -yellow sometext  # Warning
        # cecho -blue sometext    # Debug
        # cecho -white sometext   # info
        # cecho -n                # new line
        # end
    
        while [ "$1" ]; do
            case "$1" in
                -normal)        color="\033[00m" ;;
    # -black)         color="\033[30;01m" ;;
    -red)           color="\033[31;01m" ;;
    -green)         color="\033[32;01m" ;;
    -yellow)        color="\033[33;01m" ;;
    -blue)          color="\033[34;01m" ;;
    # -magenta)       color="\033[35;01m" ;;
    # -cyan)          color="\033[36;01m" ;;
    -white)         color="\033[37;01m" ;;
    -n)             one_line=1;   shift ; continue ;;
    *)              echo -n "$1"; shift ; continue ;;
    esac
    
    shift
    echo -en "$color"
    echo -en "$1"
    echo -en "\033[00m"
    shift
    
    done
    if [ ! $one_line ]; then
            echo
    fi
    }
    # end echo color function
    
    # echo color function, smarter
    function echo_r () {
        #Error, Failed
        [ $# -ne 1 ] && return 0
        echo -e "\033[31m$1\033[0m"
    }
    function echo_g () {
        # Success
        [ $# -ne 1 ] && return 0
        echo -e "\033[32m$1\033[0m"
    }
    function echo_y () {
        # Warning
        [ $# -ne 1 ] && return 0
        echo -e "\033[33m$1\033[0m"
    }
    function echo_b () {\
        # Debug
        [ $# -ne 1 ] && return 0
        echo -e "\033[34m$1\033[0m"
    }
    # end echo color function, smarter
    
    WORKDIR=$PRGDIR
    # end public header
    # =============================================================================================================================
    
    # Where to get source code
    SOURCEURL=https://github.com/DingGuodong/GitOSCAutoDeploy.git
    
    # Setting how many days do you want save old releases, default is 10 days
    save_old_releases_for_days=10
    
    function setDirectoryStructure() {
        if [ -f $WORKDIR/.lock ];then
            echo_g "Set directory structure has been done, skipping. "
            return
        fi
        echo_b "Setting directory structure."
        # learn from capistrano
        # Refer: http://capistranorb.com/documentation/getting-started/structure/
        # Refer: http://capistranorb.com/documentation/getting-started/structure/#
    
        # ├── current -> /var/www/my_app_name/releases/20150120114500/
        # ├── releases
        # │   ├── 20150080072500
        # │   ├── 20150090083000
        # │   ├── 20150100093500
        # │   ├── 20150110104000
        # │   └── 20150120114500
        # ├── repo
        # │   └── <VCS related data>
        # ├── revisions.log
        # └── shared
        #     └── <linked_files and linked_dirs>
    
        # current is a symlink pointing to the latest release. This symlink is updated at the end of a successful deployment. If the deployment fails in any step the current symlink still points to the old release.
        # releases holds all deployments in a timestamped folder. These folders are the target of the current symlink.
        # repo holds the version control system configured. In case of a git repository the content will be a raw git repository (e.g. objects, refs, etc.).
        # revisions.log is used to log every deploy or rollback. Each entry is timestamped and the executing user (username from local machine) is listed. Depending on your VCS data like branchnames or revision numbers are listed as well.
        # shared contains the linked_files and linked_dirs which are symlinked into each release. This data persists across deployments and releases. It should be used for things like database configuration files and static and persistent user storage handed over from one release to the next.
        # The application is completely contained within the path of :deploy_to. If you plan on deploying multiple applications to the same server, simply choose a different :deploy_to path.
    
        # Check directories for deploy
        # [ ! -d $WORKDIR/current ] && mkdir $WORKDIR/current
        [ ! -d $WORKDIR/release ] && mkdir $WORKDIR/release
        [ ! -d $WORKDIR/repository ] && mkdir $WORKDIR/repository
        [ ! -d $WORKDIR/share ] && mkdir $WORKDIR/share
        # end directories structure
        touch $WORKDIR/.lock
        echo_g "Set directory structure successfully! "
    }
    
    function checkDependencies() {
        echo_b "Checking dependencies for deploy procedure. "
        # Refer:
        # if [ -z ${var+x} ]; then
        #     echo "var is unset"; else echo "var is set to '$var'"
        # fi
        # if [ "$var x" = " x" ]; then
        #     echo "var is empty"; else echo "var is set to '$var'"
        # fi
        # if [ -z $var ]; then
        #     echo "var is empty"; else echo "var is set to '$var'"
        # fi
        if [[ -z $SOURCEURL ]]; then
            echo_r "Error: SOURCEURL is undefined! "
            exit 1
        fi
        DISKSPACE=`df $WORKDIR | tail -n1 | awk '{print $(NF -2)}'`
        if [[ $DISKSPACE -lt 2097152 ]]; then
            echo_y "Warning: Disk space of $WORKDIR is smaller than 2GB"
            #exit 1
        fi
    
        echo_g "All required dependencies check pass! "
    
    }
    
    function cleanOldReleases(){
        save_days=${save_old_releases_for_days:-10}
        if [ ! -d $WORKDIR/release ]; then
            echo_b "Can NOT find release directory, skipping . "
            return
        fi
        need_clean=$(find $WORKDIR/release -mtime +$save_days -exec ls {} \;)
        if [ ! -z $need_clean ]; then
            echo_g "Expired releases found and will be removed from project! "
            find $WORKDIR/release -mtime +$save_days -exec rm -rf {} \;
            if [ $? -eq 0 ]; then
                echo_g "Expired releases have removed from project! "
            else
                echo_r "Can NOT remove expired releases, please alter to Admin users. "
            fi
        else
            echo_g "All releases are not expired, skipping. "
        fi
    
    
    }
    function deploy() {
        # check a directories lock, Note: this is redundant
        if [[ ! -f $WORKDIR/.lock ]]; then
            setDirectoryStructure
        fi
        cleanOldReleases
        checkDependencies
    	# Make directory to release directory
    	SOURCEDIR="$WORKDIR/release/$(date +%Y%m%d%H%M%S)"
    	[ ! -d $SOURCEDIR ] && mkdir $SOURCEDIR
    
        # Get files from source code repository
        git clone $SOURCEURL $SOURCEDIR
        # svn co http://$SOURCEURL $WORKDIR/repository
    
        # TODO
        # get branchnames or revision numbers from VCS data
    
    
    	# Remove .git or .svn
    	[ -d $SOURCEDIR/.git ] && rm -rf $SOURCEDIR/.git
    	[ -d $SOURCEDIR/.svn ] && rm -rf $SOURCEDIR/.svn
    
    	# ifdef Complie
        # endif
    
    	# Make source code symbolic link to current
    	( [ -f $WORKDIR/current ] || [ -d $WORKDIR/current ] ) && rm -rf $WORKDIR/current
    	ln -s $SOURCEDIR $WORKDIR/current
    
    	# Move conf and logs directies from release to share
        [ -d $WORKDIR/release/conf ] && mv $WORKDIR/release/conf $WORKDIR/share/conf
        [ -d $WORKDIR/release/logs ] && mv $WORKDIR/release/logs $WORKDIR/share/logs
    
    	# Make conf and logs symbolic link to current
    	[ -d $WORKDIR/share/conf ] && ln -s $WORKDIR/share/conf $WORKDIR/current/conf
    	[ -d $WORKDIR/share/logs ] && ln -s $WORKDIR/share/logs $WORKDIR/current/logs
    
    	# Start service or validate status
    	if [[ -e $WORKDIR/current/bin/startup.sh ]]; then
    	    $WORKDIR/current/bin/startup.sh start
    	    RETVAL=$?
        else
            # TODO
            # external health check
    	    RETVAL=0
        fi
    	RETVAL=$?
    
    	# if started ok, then create a workable program to a file
    	if [[ $RETVAL -eq 0 ]]; then
    	# Note cat with eof must start at row 0, and with eof end only, such as no blank spaces, etc
    	cat >$WORKDIR/share/workable_program.log <<eof
    $SOURCEDIR
    eof
        echo_g "Deploy successfully! "
        echo_g "current workable version is $(cat $WORKDIR/share/workable_program.log)"
        ls --color=auto -l $WORKDIR/current
        else
            echo_r "Error: Deploy failed! "
            $0 rollback
    	fi
    }
    
    # Rollback to last right configuraton
    function rollback() {
    	# The key is find last files which can work
    	WORKABLE_PROGRAM=`cat $WORKDIR/share/workable_program.log`
        if [[ -z WORKABLE_PROGRAM ]]; then
            echo_r "Error: Can NOT find workable release version! Please check if it is first deployment! "
            exit 1
        fi
    	# # Stop service
    	if [[ -e $WORKDIR/current/bin/startup.sh ]]; then
    	    $WORKDIR/current/bin/startup.sh stop
    	fi
    
    	# Remove failed deploy
    	rm -rf $WORKDIR/current
    
    	# Remake source code symbolic link to current
    	ln -s $WORKABLE_PROGRAM $WORKDIR/current
    
    	# Remake conf and logs symbolic link to current
    	[ -d $WORKDIR/share/conf ] && ln -s $WORKDIR/share/conf $WORKDIR/current
    	[ -d $WORKDIR/share/logs ] && ln -s $WORKDIR/share/logs $WORKDIR/current
    
    	# Start service or validate status
    	if [[ -e $WORKDIR/current/bin/startup.sh ]]; then
    	    $WORKDIR/current/bin/startup.sh start
    	    RETVAL=$?
        else
            # TODO
            # external health check
    	    RETVAL=0
        fi
    	RETVAL=$?
    
    	# if started ok, then create a workable program to a file
    	if [[ $RETVAL -eq 0 ]]; then
    	    echo_g "Rollback successfully! "
    	    echo_g "current workable version is $WORKABLE_PROGRAM"
    	    ls --color=auto -l $WORKDIR/current
    	fi
    }
    
    function destroy() {
        # echo a warning message
        echo_y "Warning: This action will destroy all this project, and this is unrecoverable! "
        answer="n"
        echo_y "Do you want to destroy this project? "
        read -p "(Default no,if you want please input: y ,if not please press the enter button):" answer
        case "$answer" in
            y|Y|Yes|YES|yes|yES|yEs|YeS|yeS )
            # delete all file expect for this script self
            # find: warning: Unix filenames usually don't contain slashes (though pathnames do).  That means that '-name `./deploy.sh'' will probably evaluate to false all the time on this system.  You might find the '-wholename' test more useful, or perhaps '-samefile'.  Alternatively, if you are using GNU grep, you could use 'find ... -print0 | grep -FzZ `./deploy.sh''.
                # echo $WORKDIR/
                #find -L $WORKDIR -type f ! -name "$(basename $0)" -exec ls --color=auto -al {} \;
                # find -L . -type f ! -name "deploy.sh" -exec ls --color=auto -al {} \;
                # find -L . -type d -exec ls --color=auto -al {} \;
                # find -L ./ -maxdepth 1 ! -name "deploy.sh" ! -wholename "./"
            # ls | grep -v "fielname" |xargs rm -rf
            find -L $WORKDIR -maxdepth 1 ! -name "$(basename $0)" ! -wholename "$WORKDIR"  -exec rm -rf {} \;
            if [ $? -eq 0 ];then
                echo_g "Destory this project successfully! Now will exit with status 0. "
                exit 0
            else
                echo_r "Error: something go wrong! Please check or alter to Admin user! "
                exit 1
            fi
            ;;
            n|N|No|NO|no|nO)
            echo_g "destroy action is cancel"
            exit 0
            ;;
            *)
            echo_r "Are you kidding me? You are a bad kid! "
            exit 1
            ;;
        esac
    
    }
    
    # Just a test for call itself, comment it
    # if [[ $# -lt 1 ]]; then
    # 	$0 help
    # 	exit
    # fi
    case $1 in
        deploy)
            deploy
            ;;
        rollback)
            rollback
            ;;
        destroy)
            destroy
            ;;
        help|*)
            echo "Usage: $0 {deploy|rollback|destroy} with $0 itself"
            exit 1
            ;;
    esac
    
    # This is not essential with 'case .. esac' handled no args excutions
    # replace "exit 0" with ":"
    #exit 0
    :

    tag: 자동화 배치 스 크 립 트, Shell 배치 스 크 립 트, capistrano 의 셸 스 크 립 트 구현, 스 크 립 트 자동 업데이트 및 스크롤 백, 자동화 배치 셸 스 크 립 트 인 스 턴 스 구현
    --end--

    좋은 웹페이지 즐겨찾기