美文网首页
Ubuntu下制作Nginx deb安装包

Ubuntu下制作Nginx deb安装包

作者: 4ffde5305e8f | 来源:发表于2017-07-15 18:24 被阅读0次

    因为工作需要需要制作deb安装包。
    在老大的帮助下,终于搞成功了。
    下面来看一下制作方法。我们以制作Nginx的deb安装包为例子。
    首先看一下 脚本目录结构:


    image.png

    build.sh 打包deb脚本
      nginx nginx控制脚本,用来在命令行执行 nginx start stop restar等命令。提取于nginx官方的deb包中。
      post与pre则为打包成deb包后,安装deb包时所需要执行的脚步。
    余下则是源码压缩包,都是nginx所需要的依赖。

    #!/usr/bin/env bash
    ##############################
    #     编译Nginx二进制安装包     #
    ##############################
    
    ################ 设置一些全局变量 #################
    
    # 用来保存 打包后的 deb文件
    WORKDIR="/home/zhai"
    test -z $WORKDIR &&
        echo -e "工作目录不存在,即将退出程序" &&
        exit 1
    
    # i386是32位的,amd64是64位
    [[ `uname -m` == "x86_64" ]] && ARCH="x86_64" || ARCH="i386"
    
    # 获得linux发行版,版本号,版本名称
    LINUX=$(python -c "import platform;dist=platform.dist();print dist[0].lower(), dist[1], dist[2]")
    LINUX_VERSION="$(echo $LINUX | cut -d' ' -f1)"
    LINUX_VS_NUMBER="$(echo $LINUX | cut -d' ' -f2)"
    LINUX_VS_NAME="$(echo $LINUX | cut -d' ' -f3)"
    
    # 获得发行版+版本号 如 ubuntu14
    ITERATION="$LINUX_VERSION$(echo $LINUX_VS_NUMBER | cut -d'.' -f1)"
    # 版权信息
    PACKAGE="nginx"
    VERSION="1.12.0"
    VENDOR="ZHAI"
    URL="http://www.jianshu.com/u/4ffde5305e8f"
    LICENSE="GPL"
    
    # 临时文件,保存压缩文件解包后的内容
    BUILD_PATH="/tmp/$PACKAGE"
    # 程序安装路径
    # 这个路径是为了方便后面打包deb,
    # 要保证此路径下 只能有一个文件夹,就是你的安装程序。
    # 每次打包前,都要清理次目录,保证打包环境的干净。
    INSTALL_PATH="/opt/deb"
    
    # 根据发行版选择对应的打包格式
    case $LINUX_VERSION in
        ubuntu|debian)
            TARGET="deb"
            ;;
        centos|redhat)
            TARGET="rpm"
            ;;
        *)
            echo "不支持的平台."
            exit 1
    esac
    
    ################## 开始编译安装 ###################
    
    # 清理旧的解包文件
    # 清理打包环境,保证打包前 此路径下文件环境的干净。
    rm -rf $BUILD_PATH
    rm -rf $INSTALL_PATH
    mkdir -p $BUILD_PATH
    mkdir -p $INSTALL_PATH
    
    # # ${var} 与 $var 是一个意思 都是引用(使用)一个变量
    # # $var 引用$后面第一个变量的值,这个第一个变量指的是 从$开始 一直到遇到第一个空格,非英文字符或者另外一个$为止
    # #   当你需要一个动态变量拼接字符的时候 
    # #   例如:var 是动态变量,num=$var-path   这时候 引用的是 var-path变量 而不是 var变量。
    # # 怎么办呢 ?这时候就该${}出马了
    # # ${var} 引用一个变量var ${}的作用范围只能在 {}以内。
    # # num=${var}-path 引用的是 变量 var 而不是 var-path 因为${}的作用范围只能在{}以内
    SOURCE_DIR=$(pwd)
    # 安装依赖 zlib
    tar xvf zlib-*.gz -C $BUILD_PATH
    cd ${BUILD_PATH}/zlib*
    ./configure
    make
    make install
    cd $SOURCE_DIR
    
    # 安装依赖 openssl
    tar xvf openssl-*.gz -C $BUILD_PATH
    cd ${BUILD_PATH}/openssl**
    ./config
    make
    make install 
    cd $SOURCE_DIR
    
    # 解包pcre源码
    # pcre 依赖不需要安装,只需要把源码路径配置到 nginx编译参数中即可
    tar xvf pcre-*.gz -C $BUILD_PATH
    
    # 编译安装nginx
    # # 配置编译参数
    #   prefix nginx安装路径
    #   剩下两个参数表示,开启ssl,和pcre功能。
    # 暂时只用设置这两个参数,可以根据需求进行添加。
    tar xvf ${PACKAGE}-${VERSION}.tar.* -C $BUILD_PATH
    cd ${BUILD_PATH}/${PACKAGE}-${VERSION}
    PREFIX="nginx"
    ./auto/configure --prefix=$INSTALL_PATH/$PREFIX \
        --with-http_ssl_module \
        --with-pcre=$BUILD_PATH/pcre*   # 配置prce源码文的路径
    make
    make install
    cd $SOURCE_DIR
    
    #################### 开始打包deb #####################
    # FPM常用参数:
    # -s:指定源类型
    # -t:指定目标类型,即想要制作为什么包
    # -n:指定包的名字
    # -v:指定包的版本号
    # -C:指定打包的相对路径 
    # -d:指定依赖于哪些包
    # -f:第二次包时目录下如果有同名安装包存在,则覆盖它
    # -p:输出的安装包的目录,不想放在当前目录下就需要指定
    # --post-install:软件包安装完成之后所要运行的脚本;同--offer-install
    # --pre-install:软件包安装之前所要运行的脚本;同--before-install
    # --post-uninstall:软件包卸载完成之后所要运行的脚本;同--offer-remove
    # --pre-uninstall:软件包卸载之前所要运行的脚本;同—before-remove
    
    # 有几个地方需要说一下
    # -C 值的就是 你的程序安装路径 例如 你程序安装在 /opt/deb/nginx
    # 那么 -C 路径就是 /opt/deb 而不是 /opt/deb/niginx 切记
    # 因为 fpm 会把 -C 路径下的 所有文件夹都打包了。
    # 因此 要保证 -C 路径下 只能有一个你的软件目录,而不能有其他的。
    # 列如:-C 为 /opt/deb 此时 deb下有三个文件目录 nginx apaceh php 那么 
    # fpm 会把这三个文件全部打包在一起。这不是我们想要,我们只想要单独的nginx。
    # 所以要保证 nginx下只有一个文件目录。
    
    # fpm打包后的deb,在安装的时候,安装路径为 -C 路径下的 文件目录为顶级安装路径。
    # 也就是说 -C只是一个 打包时候所用的 寻找安装程序位置的路径。
    # 安装deb时候 将 -C 转换为 /  也就是 根路径去安装 
    # 例如 -C /opt/deb
    # 软件为 nginx 此时完整路径为 /opt/deb/nginx
    # 安装的时候 其实是安装在 /nginx 直接安装在了根路径下,而不是 /opt/deb下。
    
    # 怎么才能安装在 /opt/deb下呢?
    # 这时候就需要 --prefix 参数了。
    # --prefix 指定安装软件时候的 绝对路径。
    # 例如 指定 --prefix 为 /home/wo/deb
    # 那么软件就会安装在 /home/wo/deb/nginx 路径下。
    
    # 还有一点
    # 软件最终安装好时候的路径 一定要 与 软件编译安装时指定的安装路径一样,不然会有很多的路径错误。
    # 这点很重要
    # 例如 nginx 编译时候 指定的安装路径为 -prefix=/opt/deb/nginx
    # 那么打包成deb 安装的时候 安装路径一定也要是 /opt/deb/nginx
    SCRIPTS_PATH=$(pwd)
    case $LINUX_VERSION in
        ubuntu|debian)
            fpm -f -s dir \
                -t $TARGET \
                -n $PACKAGE \
                -v $VERSION \
                -C $INSTALL_PATH \
                -p $BUILD_PATH/ \
                --prefix $INSTALL_PATH \
                --iteration $ITERATION \
                --license $LICENSE \
                --vendor $VENDOR \
                --url $URL \
                --deb-no-default-config-files \
                --pre-install $SCRIPTS_PATH/pre-install \
                --post-install $SCRIPTS_PATH/post-install \
                --pre-uninstall $SCRIPTS_PATH/pre-uninstall \
                --post-uninstall $SCRIPTS_PATH/post-uninstall
            ;;
        centos|redhat)
            fpm -f -s dir \
                -t $TARGET \
                -n $PACKAGE \
                -v $VERSION \
                -C $INSTALL_PATH \
                -p $BUILD_PATH/ \
                --prefix $INSTALL_PATH
                --iteration $ITERATION \
                --license $LICENSE \
                --vendor $VENDOR \
                --url $URL \
                --pre-install $SCRIPTS_PATH/pre-install \
                --post-install $SCRIPTS_PATH/post-install \
                --pre-uninstall $SCRIPTS_PATH/pre-uninstall \
                --post-uninstall $SCRIPTS_PATH/post-uninstall
            ;;
        *)
            echo "Unsupport platform."
            exit 1
    esac
    PACKDIR=${WORKDIR}/packages/LINUX_VERSION/`echo $LINUX_VS_NUMBER| cut -d'.' -f1`/${ARCH}
    #cd -
    # 移动deb到 工作目录
    mkdir -p $PACKDIR
    mv ${BUILD_PATH}/${PACKAGE}_${VERSION}-${ITERATION}_*.${TARGET} ${PACKDIR}/${PACKAGE}-${VERSION}.${ARCH}.${TARGET}
    

    pre-install脚本
    pre-install 运行期间为 软件安装之前,如果有Nginx旧版本在运行,那么就会结束Nginx旧版本进行,避免deb包的安装失败。

    #!/usr/bin/env bash
    
    #############################################
    ######  软件包安装之前所要运行的脚本   #######
    #############################################
    
    # 结束 nginx进程,如果存在的话
    retval=$(ps -A | grep nginx | grep -v grep | awk '{print $1}' | wc -l)
    if [[ $retval -ne 0 ]]; then
        ps -A | grep nginx | grep -v grep | awk '{print $1}' | xargs kill -9
    fi
    

    post-install脚本
    post-install 运行期间为 软件安装完成之后,负责一些环境变量的设置。

    #!/usr/bin/env bash
    
    #############################################
    #####     软件包安装完成后所要运行的脚本     #####
    #############################################
    
    LINUX=$(python -c "import platform;dist=platform.dist();print dist[0].lower(), dist[1], dist[2]")
    LINUX_VERSION="$(echo $LINUX | cut -d' ' -f1)"
    NGINX_PATH="/opt/deb/nginx/nginx"
    NGINX_CONF="/opt/deb/nginx/conf/nginx.conf"
    # pid 文件路径
    PID_PATH="pid        /opt/deb/nginx/logs/nginx.pid;"
    
    # 将pid路径配置到 nginx配置文件中
    case $LINUX_VERSION in
        ubuntu|debian)
            LN=$(grep -n "#pid" $NGINX_CONF | cut -d: -f1)
            sed -i "$LN a\\$PID_PATH" $NGINX_CONF
            
            # 删除旧nginx控制脚本,如果有的话,并将新nginx控制脚本移过去
            test -f /etc/init.d/nginx && rm -rf /etc/init.d/nginx
            cp $NGINX_PATH /etc/init.d/nginx
            ;;
        centos|redhat)
            LN=$(grep -n "#pid" $NGINX_CONF | cut -d: -f1)
            sed -i "$LN a\\$PID_PATH" $NGINX_CONF
    
            rm /etc/init.d/nginx -f
            cp $NGINX_PATH /etc/init.d/nginx
            ;;
        *)
            ;;
    esac
    

    pre-uninstall脚本
    pre-uninstall脚本运行期间为 程序卸载删除之前,负责结束程序进程解除占用。

    #!/usr/bin/env bash
    
    #############################################
    ######     软件包安装之前所要运行的脚本     ######
    #############################################
    
    # 结束 nginx进程,如果存在的话
    retval=$(ps -A | grep nginx | grep -v grep | awk '{print $1}' | wc -l)
    if [[ $retval -ne 0 ]]; then
        ps -A | grep nginx | grep -v grep | awk '{print $1}' | xargs kill -9
    fi
    

    post-uninstall脚本
    post-uninstall脚本运行期间为 程序卸载删除完成后,负责清理程序残留文件。

    #!/usr/bin/env bash
    
    #############################################
    #####     软件包安装完成后所要运行的脚本     #####
    #############################################
    
    LINUX=$(python -c "import platform;dist=platform.dist();print dist[0].lower(), dist[1], dist[2]")
    LINUX_VERSION="$(echo $LINUX | cut -d' ' -f1)"
    
    INSTALL_PATH="/opt/deb"
    NGINXDIR=$INSTALL_PATH/nginx
    case $LINUX_VERSION in
        ubuntu|debian)
            test -d $NGINXDIR && rm -rf $NGINXDIR
            ;;
        centos|redhat)
            test -d $NGINXDIR && rm -rf $NGINXDIR
            ;;
        *)
            ;;
    esac
    test -f /etc/init.d/nginx && rm -rf /etc/init.d/nginx
    

    nginx为控制Nginx启动,停止,重启的脚本。提取与官方deb安装包中(安装官方deb包后,脚本路径为 /etc/init.d/nginx),有几个地方需要改一下就可以使用了。

    #!/usr/bin/env bash
    
    ### BEGIN INIT INFO
    # Provides:   nginx
    # Required-Start:    $local_fs $remote_fs $network $syslog $named
    # Required-Stop:     $local_fs $remote_fs $network $syslog $named
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: starts the nginx web server
    # Description:       starts nginx using start-stop-daemon
    ### END INIT INFO
    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
    ################ 此处为修改的部分 ###########################
    
    # nginx 执行文件路径
    NGINX_PATH="/opt/deb/nginx/sbin/nginx"
    # nginx配置文件路径
    NGINX_CONF="/opt/deb/nginx/conf/nginx.conf"
    # 开启日志输出
    # 开启日志输入,一定不能写在这里,不然会被默认值给覆盖了。
    # 一定要写在 最后面 case "$1" in 这一行的上面
    # VERBOSE='yes'
    #DAEMON=/usr/sbin/nginx
    DAEMON=$NGINX_PATH
    NAME=nginx
    DESC=nginx
    
    # Include nginx defaults if available
    if [ -r /etc/default/nginx ]; then
        . /etc/default/nginx
    fi
    
    test -x $DAEMON || exit 0
    
    . /lib/init/vars.sh
    . /lib/lsb/init-functions
    
    # Try to extract nginx pidfile
    PID="/opt/deb/nginx/logs/nginx.pid"
    if [ -z "$PID" ]
    then
        PID=/run/nginx.pid
    fi
    #################   修改结束   ###################
    
    # Check if the ULIMIT is set in /etc/default/nginx
    # ulimit 用于限制 shell 启动进程所占用的资源
    # nginx 默认是没有开启的
    if [ -n "$ULIMIT" ]; then
        # Set the ulimits
        ulimit $ULIMIT
    fi
    
    #
    # Function that starts the daemon/service
    #
    do_start()
    {
        # Return
        #   0 if daemon has been started
        #   1 if daemon was already running
        #   2 if daemon could not be started
        start-stop-daemon --start --quiet --pidfile $PID --exec $DAEMON --test > /dev/null \
            || return 1
        start-stop-daemon --start --quiet --pidfile $PID --exec $DAEMON -- \
            $DAEMON_OPTS 2>/dev/null \
            || return 2
    }
    
    test_nginx_config() {
        $DAEMON -t $DAEMON_OPTS >/dev/null 2>&1
    }
    
    #
    # Function that stops the daemon/service
    #
    do_stop()
    {
        # Return
        #   0 if daemon has been stopped
        #   1 if daemon was already stopped
        #   2 if daemon could not be stopped
        #   other if a failure occurred
        start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PID --name $NAME
        RETVAL="$?"
    
        sleep 1
        return "$RETVAL"
    }
    
    #
    # Function that sends a SIGHUP to the daemon/service
    #
    do_reload() {
        start-stop-daemon --stop --signal HUP --quiet --pidfile $PID --name $NAME
        return 0
    }
    
    #
    # Rotate log files
    #
    do_rotate() {
        start-stop-daemon --stop --signal USR1 --quiet --pidfile $PID --name $NAME
        return 0
    }
    
    #
    # Online upgrade nginx executable
    #
    # "Upgrading Executable on the Fly"
    # http://nginx.org/en/docs/control.html
    #
    do_upgrade() {
        # Return
        #   0 if nginx has been successfully upgraded
        #   1 if nginx is not running
        #   2 if the pid files were not created on time
        #   3 if the old master could not be killed
        if start-stop-daemon --stop --signal USR2 --quiet --pidfile $PID --name $NAME; then
            # Wait for both old and new master to write their pid file
            while [ ! -s "${PID}.oldbin" ] || [ ! -s "${PID}" ]; do
                cnt=`expr $cnt + 1`
                if [ $cnt -gt 10 ]; then
                    return 2
                fi
                sleep 1
            done
            # Everything is ready, gracefully stop the old master
            if start-stop-daemon --stop --signal QUIT --quiet --pidfile "${PID}.oldbin" --name $NAME; then
                return 0
            else
                return 3
            fi
        else
            return 1
        fi
    }
    # 开启日志输出
    # 这个开启日志的 一定要写在这里,不然会被默认值给覆盖了。
    VERBOSE='yes'
    case "$1" in
        start)
            [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
            do_start
            case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
            esac
            ;;
        stop)
            [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
            do_stop
            case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
            esac
            ;;
        restart)
            log_daemon_msg "Restarting $DESC" "$NAME"
    
            # Check configuration before stopping nginx
            if ! test_nginx_config; then
                log_end_msg 1 # Configuration error
                exit 0
            fi
    
            do_stop
            case "$?" in
                0|1)
                    do_start
                    case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 1 ;; # Old process is still running
                        *) log_end_msg 1 ;; # Failed to start
                    esac
                    ;;
                *)
                    # Failed to stop
                    log_end_msg 1
                    ;;
            esac
            ;;
        reload|force-reload)
            log_daemon_msg "Reloading $DESC configuration" "$NAME"
    
            # Check configuration before reload nginx
            #
            # This is not entirely correct since the on-disk nginx binary
            # may differ from the in-memory one, but that's not common.
            # We prefer to check the configuration and return an error
            # to the administrator.
            if ! test_nginx_config; then
                log_end_msg 1 # Configuration error
                exit 0
            fi
    
            do_reload
            log_end_msg $?
            ;;
        configtest|testconfig)
            log_daemon_msg "Testing $DESC configuration"
            test_nginx_config
            log_end_msg $?
            ;;
        status)
            status_of_proc -p $PID "$DAEMON" "$NAME" && exit 0 || exit $?
            ;;
        upgrade)
            log_daemon_msg "Upgrading binary" "$NAME"
            do_upgrade
            log_end_msg 0
            ;;
        rotate)
            log_daemon_msg "Re-opening $DESC log files" "$NAME"
            do_rotate
            log_end_msg $?
            ;;
        *)
            echo "Usage: $NAME {start|stop|restart|reload|force-reload|status|configtest|rotate|upgrade}" >&2
            exit 3
            ;;
    esac
    
    :
    

    打包后的deb 就保存在我们设置的工作目录中。


    image.png

    在看一下 deb的信息 :


    image.png
    我们看到确实安装在 /opt/deb/nginx路径之下
    我们安装一下
    image.png
    image.png

    安装成功 ,没毛病。运行一下,试一试控制命令:


    image.png
    ok 很完美! image.png

    ok 好了 完美运行

    相关文章

      网友评论

          本文标题:Ubuntu下制作Nginx deb安装包

          本文链接:https://www.haomeiwen.com/subject/uzkzhxtx.html