nikoo 发表于 2018-9-17 12:09:37

通过Git WebHooks+脚本实现自动更新发布代码之Shell脚本(二)

#!/usr/bin/env bash  

  
# Public header
  
# =============================================================================================================================
  

  
# Check that we are root ... so non-root users stop here
  
[`id -u` -eq"0" ] ||exit 4
  

  
# 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
  
# =============================================================================================================================
  

  
# begin customization for special case
  
# project directory to waiting for update
  
config_project_dir=example_projects
  
# resources directory which contain config file and update files
  
config_resources_dir=example_resources
  
config_config_file=$config_resources_dir/config_update.conf
  
config_backup_dir=example_backup_dir
  
# log options
  
config_this_logfile=$WORKDIR/.update_backup.log
  
# end
  

  
function check_dependencies(){
  
    echo_b "Checking dependencies for update procedure. "
  

  
    if [ -z $config_project_dir ]; then
  
      echo_r "Error: config_project_dir is undefined! "
  
      exit 1
  
    fi
  

  
    if [ ! -d $config_resources_dir ]; then
  
      echo_r "Error: config_resources_dir is undefined! "
  
    fi
  

  
    if [ -z $config_config_file ]; then
  
      echo_r "Error: config_config_file is undefined! "
  
      exit 1
  
    fi
  

  
    left_disk_space=`df $config_backup_dir | tail -n1 | awk '{print $(NF -2)}'`
  
    # set 2097152 to project directory size
  
    if [ -z $config_project_dir -o ! -d $config_project_dir ]; then
  
      project_file_space_usage=$(du -s /root | awk '{print $1}')
  
      required_size=$(expr $project_file_space_usage \* 2)
  
    fi
  
    if [[ $left_disk_space -lt $required_size ]]; then
  
      echo_r "Disk space of $config_backup_dir is smaller than $required_size. "
  
      exit 1
  
    fi
  

  
    echo_g "All required dependencies check pass! "
  

  
}
  

  
function test_self(){
  
    # How to use this function:
  
    # First execute "$0 test_self", then execute "$0 update"
  

  
    echo_b "Test purpose begin. "
  

  
    # clean old test example
  
    echo_b "Clean old test example. "
  
    [ -d $WORKDIR/example_projects ] && rm -rf $WORKDIR/example_projects
  
    [ -d $WORKDIR/example_resources ] && rm -rf $WORKDIR/example_resources
  
    [ -d $WORKDIR/example_backup_dir ] && rm -rf $WORKDIR/example_backup_dir
  

  
    # make an example project directory
  
    if [ -z $config_project_dir -o ! -d $config_project_dir ]; then
  
      echo_b "Making an example project directory. "
  
      mkdir $WORKDIR/example_projects
  
      config_project_dir=example_projects
  
      # Padding example_projects directory
  
      touch $config_project_dir/example_filename
  
      mkdir $config_project_dir/example_directory
  
    fi
  

  
    # make an example resources directory
  
    if [ -z $config_resources_dir -o ! -d $config_resources_dir ]; then
  
      echo_b "Making an example resources directory. "
  
      mkdir$WORKDIR/example_resources
  
      config_resources_dir=$WORKDIR/example_resources
  
    fi
  

  
    # make an example config_update.conf
  
    if [ -z $config_config_file -o ! -f $config_config_file ]; then
  
      echo_b "Making an example config_update.conf file. "
  
      touch $config_resources_dir/config_update.conf
  
      config_config_file=$config_resources_dir/config_update.conf
  
    # Padding config_update.conf file
  
    cat >$config_config_file &1 ; then
  
            # do_cp
  
            do_cp $names
  
      elif grep $names $config_config_file | grep update >/dev/null 2>&1 ;then
  
            # do_cp
  
            do_cp $names
  
      elif grep $names $config_config_file | grep remove >/dev/null 2>&1 ;then
  
            # do_remove
  
            do_remove $names
  
      else
  
            exit 1
  
      fi
  
    done
  
    echo_g "Files operations finished successfully! "
  
}
  

  
# TODO
  
# no example here, please refer to your real production environment
  
#function do_clean_cache(){}
  
#function do_restart_service(){}
  

  
function service_operation(){
  
    echo_b "Begin services operations"
  
    configs=`awk -F '[ ]+' '/^config/ { print $2 }' $config_config_file`
  
    for names in $configs; do
  
      if grep $names $config_config_file | grep cleancache | grep enable >/dev/null 2>&1 ; then
  
            # do_clean_cache
  
            echo do_clean_cache $names
  
      elif grep $names $config_config_file | grep cleancache | grep disable >/dev/null 2>&1 ; then
  
            # echo a warning
  
            echo_y "Warning: disable action is NOT recommended, $names skipped."
  
      elif grep $names $config_config_file | grep restartservice | grep enable >/dev/null 2>&1 ; then
  
            # do_restart_service
  
            echo do_restart_service $names
  
      elif grep $names $config_config_file | grep restartservice | grep disable >/dev/null 2>&1 ; then
  
            # echo a warning
  
            echo_y "Warning: disable action is NOT recommended, $names skipped."
  
      else
  
            echo $names
  
            echo_r "Error: Wrong config file $config_config_file, please check it. "
  
            exit 1
  
      fi
  
    done
  
    echo_g "Services operations finished successfully! "
  
}
  

  
function check_remote_server_status(){
  
    # TODO
  
    # for remote call
  
    echo
  

  
}
  

  
function backup(){
  
    echo_b "Backup files before update"
  
#    backup_filename=backup_$(date +%F_%H_%M_%S).tgz
  
    backup_filename=backup_$(date +%Y_%m_%d_%H_%M_%S).tgz
  
    tar --create --gzip --absolute-names --file=$config_backup_dir/$backup_filename $config_project_dir
  
    if [ $? -eq 0 ]; then
  
      echo_g "Backup files before update finished and successfully! "
  
      echo "restore_least_file=$config_backup_dir/$backup_filename" > $config_this_logfile
  
    else
  
      echo_r "Error: Backup files before update failed! Please alter to administrator. "
  
      exit 1
  
    fi
  

  
}
  

  
function restore(){
  
    echo_b "Restore files for rollback"
  
    if [ -f $config_this_logfile ]; then
  
      . $config_this_logfile
  
    fi
  
    restore_least_file=${restore_least_file:-1}
  
    if [ -s $restore_least_file ]; then
  
      tar -C $config_project_dir/.. -zxf $restore_least_file
  
      if [ $? -eq 0 ]; then
  
            echo_g "Restore files finished and successfully! "
  
      else
  
            echo_r "Restore files failed! Please alter to administrator. "
  
            exit 1
  
      fi
  
    else
  
      echo_r "Can NOT find backup files in $config_backup_dir, backup once indeed? "
  
      exit 1
  
    fi
  

  
}
  

  
# TODO
  
# for remote call
  
# function remote_backup(){}
  
# function remote_restore(){}
  

  

  
function rollback(){
  
    echo_b "rollback after update failed"
  
    $0 restore
  

  
    echo_g "rollback finished and successfully! "
  
}
  

  
function update_status(){
  
    # TODO
  
    # no example here, please refer to your real production environment
  
    # check if update success or failure
  
    echo update_status
  
    # if failure, do rollback action
  
      # service_operation
  
}
  

  
function update(){
  
    # TODO
  
    # thinking carefully with all exit status, which is not good for automatic update
  
    check_dependencies
  
    backup
  
    file_operation
  
    service_operation
  
    update_status
  
}
  

  
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
  

  
}
  

  
case $1 in
  
    update)
  
      update
  
      ;;
  
    backup)
  
      backup
  
      ;;
  
    restore)
  
      restore
  
      ;;
  
    rollback)
  
      rollback
  
      ;;
  
    destroy)
  
      destroy
  
      ;;
  
    help|*)
  
      echo "Usage: $0 {update|backup|restore|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
  
:


页: [1]
查看完整版本: 通过Git WebHooks+脚本实现自动更新发布代码之Shell脚本(二)