• jenkins-自动化部署(二)


    配置关联机器

    安装插件

    系统管理->插件管理->可选插件

    搜索" Publish over SSH" 因为我装了所以搜索不出来,搜索出来 打勾 点击直接安装就好了

    配置关联机器

    就是jenkins访问部署服务的机器

    系统管理-系统配置

    配置密码

    输入服务器密码 

    测试

    安装git

    因为我使用git作为源代码工具 所以在服务器安装git

    yum -y install git

    安装maven

    源码构建工具使用的maven 所以安装maven <<maven安装>>

    变量配置

    如果不配置,会出现shell执行mvn命令 报:jenkinsmvn: command not found

    将安装maven配置的变量设置到jenkins 如:

     vi /etc/profile

     

     

     

    安装jdk

    参考《jdk-安装》

    变量配置

    设置ssh免密登录

    1.设置免密

    注:需要在jenkins账户下创建秘钥,切换失败则参考下面

    参考:《linux-scp免密登录》

    2.因为jenkins是默认用jenkins账户取执行ssh jenkins账户是没有权限的

    su jenkins

    如果切换失败还是root账户

    vim /etc/passwd

    jenkins:x:986:980:Jenkins Automation Server:/var/lib/jenkins:/bin/false

    改为

    jenkins:x:986:980:Jenkins Automation Server:/var/lib/jenkins:/bin/bash

     

     再次执行

    [root@cicd ~]# su jenkins
    bash-4.1$

    结果命令提示符的用户名不是jenkins而变成了 bash-4.1$,原因是在安装jenkins时,jenkins只是创建了jenkins用户,并没有为其创建home目录。

    使用root账户执行

    vim ~/.bash_profile

    在文件末尾加上

    export PS1='[u@h W]$'

    刷新配置

    source ~/.bash_profile

    验证是否成功

    3.jenkins系统用户开通免密登陆

    使用root账户输入

    sudo visudo

    在文件末尾加上

    jenkins ALL=(ALL) NOPASSWD: ALL

    重启jenkins

    systemctl status jenkins
    systemctl stop jenkins
    systemctl start jenkins

    任务管理例子

    这是我们的每个tag对应一个环境,然后需要发布某个环境下服务切到环境下点一下就行了,因为我们多个需求并行开发 所以测试环境很多套,不同的环境发不同的分支互不影响:如bbc-preview1 就是第一套   pro就是生产

     

    创建任务

     

    2.构建设置

    3.变量设置,脚本和git需要使用

     

    4.设置源码地址和登录名密码信息

     5.设置构建步骤 使用shell

     

    编写jenkins服务shell脚本

    #!/bin/bash
    #目标服务器主目录
    _DEPLOYER='deploy'
    #程序的yml环境配置
    _PROFILES='alitest'
    #日志目录
    _LOG_DIRECTORY="/home/$_DEPLOYER/logs"
    #这里定义服务的配置多个服务空格隔开 如:SERVICE_CONFIG_TABLE='service-bridge;9910;1g service-bridge2;9910;1g'
    SERVICE_CONFIG_TABLE='service-bridge;9908;1g'
    #是否部署bridge的变量 不支持-的定义 所以改为_
    service_bridge=$service_bridge
    #读取上面hosts配置的变量
    hosts=$hosts
    #是否重新打包,写死,如果需要动态勾选在jenkens通过变量配置
    repackage=true
    #是否重新部署服务  写死 如果需要动态勾选在jenkens通过变量配置
    restart=true
    #写死,如果需要动态勾选 在上面配置  写死 如果需要动态勾选在jenkens通过变量配置
    skipTest=true
    TEST_ARGUMENT="";
    #maven打包是否跳过Test
    if $skipTest; then
        TEST_ARGUMENT="-Dmaven.test.skip=true"
    fi
    
    #是否需要重新打包 循环服务配置 进行逐个maven打包
    if $repackage; then
        #支持多服务配置 空格隔开 所以 用for in
        for SERVICE_CONFIG in $SERVICE_CONFIG_TABLE; do
            #通过;分割 取第一个 取出服务名字
            SERVICE_NAME=$(echo $SERVICE_CONFIG | cut -f 1 -d ';' )
            #将service-** 替换为service_**
            isDeployParameterName=${SERVICE_NAME/-/_};
            #根据名字获得value
            isDeployParameterValue=${!isDeployParameterName}
            #根据是否勾选了部署来判断是否部署
            if  $isDeployParameterValue; then
                #maven 命令 clean 并重新打包到targer
                mvn  -s "/var/lib/jenkins/workspace/preview-ch-micro-services/settings.xml" clean package -pl "$SERVICE_NAME" -am -U $TEST_ARGUMENT
                if [ $? -gt 0 ]; then
                    echo "编译错误"
                    exit 1
                fi
            fi
        done
        echo "打包成功[$branch]...准备scp到目标服务器"
        for SERVICE_CONFIG in $SERVICE_CONFIG_TABLE; do
            SERVICE_NAME=$(echo $SERVICE_CONFIG | cut -f 1 -d ';' )
            #将service-** 替换为service_**
            isDeployParameterName=${SERVICE_NAME/-/_};
            #根据名字获得value
            isDeployParameterValue=${!isDeployParameterName}
            #根据是否勾选了部署来判断是否部署
            if  $isDeployParameterValue; then
                #获得指定服务的变量名字
                hostParameterName=$isDeployParameterName"_hosts";
                #将打包后的jar 推送到目标服务器的projects目录
                #我们host是文本变量通过回车换行,其实变量值是空格隔开 直接循环
                for host in ${!hostParameterName};do
                    scp $SERVICE_NAME/target/*.jar root@$host:/home/$_DEPLOYER/projects
                    #判断上一个命令是否执行成功
                    if [ $? -eq 0 ]; then
                        echo "服务"$SERVICE_NAME"主机地址"$host"已最新包scp到服务器成功"
                    else
                        echo "服务"$SERVICE_NAME"主机地址"$host"最新包scp到服务器失败"
                    fi
    
                done
    
            fi
        done
    fi
    #是否发布  循环服务 执行脚本start_bash
    if $restart; then
        #支持多服务配置 空格隔开 所以 用for in
        for SERVICE_CONFIG in $SERVICE_CONFIG_TABLE; do
            SERVICE_NAME=$(echo $SERVICE_CONFIG | cut -f 1 -d ';' )
            #将service-** 替换为service_**
            isDeployParameterName=${SERVICE_NAME/-/_};
            #根据名字获得value
            isDeployParameterValue=${!isDeployParameterName}
            #根据是否勾选了部署来判断是否部署
            if  $isDeployParameterValue; then
                #通过;分割取第三个 获取内存大小
                MEMORY_MAX=$(echo $SERVICE_CONFIG | cut -f 3 -d ';' )
                #通过;分割去第二个 获取端口号
                SERVICE_PORT=$(echo $SERVICE_CONFIG | cut -f 2 -d ';' )
                #获得指定服务的变量名字
                hostParameterName=$isDeployParameterName"_hosts";
                #我们host是文本变量通过回车换行,其实变量值是空格隔开 直接循环
                for host in ${!hostParameterName};do
    
                    #1.在指定主机执行递归创建2个目录
                    #2.将projects的打包的jar复制到workspace
                    #3.调用远程服务器的start_bash脚本 执行服务发布
                    ssh root@$host "mkdir -p /home/deploy/logs && mkdir -p /home/deploy/workspace/$SERVICE_NAME-$SERVICE_PORT && 
                    cp /home/deploy/projects/$SERVICE_NAME.jar /home/deploy/workspace/$SERVICE_NAME-$SERVICE_PORT/app.jar && 
                    bash /home/deploy/start_bash -s -- -t/home/$_DEPLOYER/workspace/$SERVICE_NAME-$SERVICE_PORT/app.jar
                    -a-Xmx$MEMORY_MAX -Xms$MEMORY_MAX -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -Dspring.profiles.active=alitest -Dproject.name=service-bridge -Dcsp.sentinel.dashboard.server=192.168.20.4:9998 -f$_LOG_DIRECTORY/$SERVICE_NAME.log"
                    #判断上一个命令是否执行成功
                    if [ $? -eq 0 ]; then
                        echo "服务"$SERVICE_NAME"主机地址"$host"已经执行ssh脚本成功"
                    else
                        echo "服务"$SERVICE_NAME"主机地址"$host"执行ssh脚本失败"
                    fi
                done
            fi
        done
    fi

    有点多 好好读可以看得懂

    编写部署端脚本

    可以看到上面调用了start_bash 在指定目录创建

    JVA_HOME=/usr/java/jdk1.8.0_191
    JRE_HOME=/usr/java/jdk1.8.0_191/jre
    CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
    PATH=$JAVA_HOME/bin:$PATH
    export PATH JAVA_HOME CLASSPATH
    
    _TARGET=""
    _DIRECTORY=""
    _NAME=""
    _PORT=""
    _LOG=
    _LOG_FILE="/dev/null"
    _STOP=
    _PID=
    _COMMAND=
    _ARGUMENTS=""
    #getopts会将 对应入参封装到OPTARG里面 比如a 则会获取到-a参数 只有参数的才会进while循环 比如没有-a 就不会走case a
    while getopts "a:t:p:x:s:lf:kh" opt; do
      case $opt in
            a)
                    #$OPTARG" 为脚本-a的参数
                    _ARGUMENTS=" $OPTARG"
                    ;;
            t)
                    #OPTARG 为脚本的-t参数
                    _TARGET="$OPTARG"
                    _DIRECTORY=$(dirname $OPTARG)"/"
                    _NAME=$(echo $(basename $OPTARG) | cut -f 1 -d '.')
                    ;;
        p)
            _PORT=$OPTARG
            ;;
        l)
                    _LOG=true
                    ;;
            f)
                    _LOG=true
                    if [ ! "$OPTARG" = "" ]; then
                            _LOG_FILE=$OPTARG
                    fi
                    ;;
            s)
                    _STOP=true
                    ;;
            h)
                    _HELP_FORMAT="%-4s %-80s
    "
                    printf "$_HELP_FORMAT" "参数" "描述"
                    printf "$_HELP_FORMAT" "-t" "jar包绝对地址, 如: '-t/home/deployer/test.jar'"
                    printf "$_HELP_FORMAT" "-p" "jar包占用端口, 如: '-p7777'"
                    printf "$_HELP_FORMAT" "-a" "自定义参数, 如: '-a-DenableSecurity=true -Dtoken=xxxx'"
                    printf "$_HELP_FORMAT" "-l" "开启日志输出,不指定该参数则不输出日志. 日志默认输出到目标jar包相同目录下的同文件名.log"
                    printf "$_HELP_FORMAT" "-f" "强制开启日志输出,指定参数为'-f/var/log/test.log',则输出到/var/log/test.log文件"
                    printf "$_HELP_FORMAT" "-s" "强制关闭目标程序(不会启动目标文件),默认按端口,次之按文件"
                    exit
                    ;;
      esac
    done
    
    #根据PID获取端口
    function getPidByPort {
            if [ -f "/usr/sbin/lsof" ]; then
                    echo `/usr/sbin/lsof -i:"$1" | grep LISTEN | awk '{ print $2}'`
            else
                    echo `/usr/bin/lsof -i:"$1" | grep LISTEN | awk '{ print $2}'`
            fi
    }
    #根据PI获取file
    function getPidByFile {
           echo `ps aux | grep \\-jar | grep $1 | awk '{ print $2}'`
    }
    #获得PID
    function getPid {
     if [ "$_PORT" == "" ]; then
                    if [ ! "$_NAME" == "" ]; then
                            _PID=`getPidByFile "$_TARGET"`
                    fi
            else
                    _PID=`getPidByPort $_PORT`
            fi
    }
    #调用PID
    getPid
    echo $_PID
    #多有有则杀掉PID
    if [[ $_PID =~ ^[0-9]+$ ]]; then
            echo "kill process $_PID"
            kill $_PID;
            echo "sleep 5 seconds"
            sleep 5
            getPid
            if [[ $_PID =~ ^[0-9]+$ ]]; then
                    kill -9 $_PID
                    sleep 1
            fi
    fi
    
    if [ $_STOP ]; then
            getPid
            if [[ $_PID =~ ^[0-9]+$ ]]; then
                    echo "无法关闭进程:$_PORT"
                    exit;
            else
                    echo "已经关闭指定程序进程"
            fi
    #       exit;
    fi
    
    if [ "$_NAME" == "" ]; then
            echo "请指定需要启动的jar包的绝对地址,如: -t/home/test.jar"
            exit
    fi
    
    if [ $_LOG ]; then
            if [ "$_LOG_FILE" = "/dev/null" ]; then
                    _LOG_FILE="$_DIRECTORY$_NAME.log"
            else
                    mkdir -p "$(dirname $_LOG_FILE)"
            fi
    fi
    
    _COMMAND="nohup java -jar$_ARGUMENTS $_TARGET > $_LOG_FILE 2>&1 &"
    echo "正在执行:$_COMMAND"
    source /etc/profile
    eval $_COMMAND

    测试

     

  • 相关阅读:
    C#计算一段程序运行时间的三种方法
    jquery easyui combobox设置默认选中第一项
    ASP.NET Web API教程 分页查询
    ASP.NET Web Api 实现数据的分页
    开源.net 混淆器ConfuserEx介绍
    C#软件license管理(简单软件注册机制)
    MyBatis入门实例-包括实体类与数据库字段对应&CLOB字段处理
    MyBatis在insert插入操作时返回主键ID的配置
    MyBatis框架——mybatis插入数据返回主键(mysql、oracle)
    关于java中split的使用
  • 原文地址:https://www.cnblogs.com/LQBlog/p/13897082.html
Copyright © 2020-2023  润新知