Linux配置JAR包为服务实现自启动

news2025/3/10 15:13:52

一、实现bash脚本

1.1 绘图工具

绘图需安装idea的插件plantUML-Integration

只需要上图一个就可以,别的也不需要装。

启动服务的逻辑如下

关闭服务的逻辑如下

1.2 逻辑实现

在/root路径下创建entrance文件,实现逻辑如下

#!/usr/bin/env bash
# 2>&1的含义
# 1表示标准输出
# 2表示标准错误输出
# 2>&1表示将标准错误输出重定向到标准输出

# 配置jar程序的pid保存文件
jar_pid=/root/jar_pid
# 配置jar的绝对路径
jar=/root/http-proxy-boot.jar

if [ "$1" = "start" ]; then
    # 如果jar_pid文件存在
    if [ -f "$jar_pid" ]; then
        # 如果jar_pid文件有值
        if [ -s "$jar_pid" ]; then
            echo "Existing PID file found during start."
            # 如果jar_pid文件可读
            if [ -r "$jar_pid" ]; then
                PID=`cat "$jar_pid"`
                # 与直接执行命令相比, 这样可以抑制输出
                ps -p $PID >/dev/null 2>&1
                # 等于0
                if [ $? -eq 0 ] ; then
                    echo "$jar appears to still be running with PID $PID. Start aborted."
                    echo "If the following process is not a $jar process, remove the PID file and try again:"
                    ps -f -p $PID
                    exit 1
                else
                    echo "Removing/clearing stale PID file."
                    # 与直接执行命令相比, 这样可以抑制输出
                    rm -f "$jar_pid" >/dev/null 2>&1
                    if [ $? != 0 ]; then
                        # 可写权限
                        if [ -w "$jar_pid" ]; then
                            cat /dev/null > "$jar_pid"
                        else
                            echo "Unable to remove or clear stale PID file. Start aborted."
                            exit 1
                        fi
                    fi
                fi
            else
                echo "Unable to read PID file. Start aborted."
                exit 1
            fi
        else
            rm -f "$jar_pid" >/dev/null 2>&1
            if [ $? != 0 ]; then
                if [ ! -w "$jar_pid" ]; then
                    echo "Unable to remove or write to empty PID file. Start aborted."
                    exit 1
                fi
            fi
        fi
    fi
    # 将命令行参数往前移一个. 比如sh test.sh 1 2, 在shift前, $1=1 $2=2, 在shift后, $1=2
    shift
    # eval是将字符串解析为命令执行,如 eval "ls -l"就相当于直接运行性ls -l
    eval "nohup java -jar \$jar >/dev/null 2>&1 &"
    # 将pid写入到jar_pid文件中
    echo $! > "$jar_pid"
    echo "$jar started."
elif [ "$1" = "stop" ]; then
    sleep=5
    # 当force为1时, 执行kill -9
    force=0
    shift
    # 若文件存在
    if [ -f "$jar_pid" ]; then
        # 若jar_pid有值
        if [ -s "$jar_pid" ]; then
            # kill -0不影响进程执行,而是检查进程是否正在运行
            kill -0 `cat "$jar_pid"` >/dev/null 2>&1
            # 如果大于0表示异常
            if [ $? -gt 0 ]; then
              echo "PID file found but either no matching process was found or the current user does not have permission to stop the process. Stop aborted."
              exit 1
            fi
        else
            echo "PID file is empty and has been ignored."
        fi
    else
      echo "$jar_pid was set but the specified file does not exist. Is $jar running? Stop aborted."
      exit 1
    fi
    # 与直接kill -15相比, 这样可以抑制输出
    kill -15 `cat "$jar_pid"` >/dev/null 2>&1
    if [ -f "$jar_pid" ]; then
        while [ $sleep -ge 0 ]; do
            # kill -0不影响进程执行,而是检查进程是否正在运行
            kill -0 `cat "$jar_pid"` >/dev/null 2>&1
            # 如果大于0表示异常, 表示进程已被关闭
            if [ $? -gt 0 ]; then
                rm -f "$jar_pid" >/dev/null 2>&1
                # 如果删除失败
                if [ $? != 0 ]; then
                    if [ -w "$jar_pid" ]; then
                        cat /dev/null > "$jar_pid"
                        force=0
                    else
                        echo "The PID file could not be removed or cleared."
                    fi
                fi
                echo "$jar stopped."
                break
            fi
            if [ $sleep -gt 0 ]; then
                sleep 1
            fi
            if [ $sleep -eq 0 ]; then
              echo "$jar did not stop in time."
              if [ $force -eq 0 ]; then
                echo "PID file was not removed."
              fi
              echo "To aid diagnostics a thread dump has been written to standard out."
              # kill -3 与 kill -15 类似, 只是kill -3 会多了一步生成核心存储,用于后续调试。kill -3适用于程序无响应时
              kill -3 `cat "$jar_pid"`
            fi
            # 自减
            sleep=`expr $sleep - 1`
        done
    fi
    KILL_SLEEP_INTERVAL=5
    if [ $force -eq 1 ]; then
        if [ -f "$jar_pid" ]; then
            PID=`cat "$jar_pid"`
            echo "Killing $jar with the PID: $PID"
            kill -9 $PID
            while [ $KILL_SLEEP_INTERVAL -ge 0 ]; do
                kill -0 `cat "$jar_pid"` >/dev/null 2>&1
                if [ $? -gt 0 ]; then
                    rm -f "$jar_pid" >/dev/null 2>&1
                    if [ $? != 0 ]; then
                        if [ -w "$jar_pid" ]; then
                            cat /dev/null > "$jar_pid"
                        else
                            echo "The PID file could not be removed."
                        fi
                    fi
                    echo "The $jar process has been killed."
                    break
                fi
                if [ $KILL_SLEEP_INTERVAL -gt 0 ]; then
                    sleep 1
                fi
                KILL_SLEEP_INTERVAL=`expr $KILL_SLEEP_INTERVAL - 1 `
            done
            if [ $KILL_SLEEP_INTERVAL -lt 0 ]; then
                echo "$jar has not been killed completely yet. The process might be waiting on some system call or might be UNINTERRUPTIBLE."
            fi
        fi
    fi
else
    echo "commands:"
    echo " start      Start jar"
    echo " stop       Stop jar"
fi

启动和关闭命令如下

sh /root/entrance start
sh /root/entrance stop

二、配置systemd服务

使用systemd的好处时,他由系统管理,统一的管理命令,而且可以支持自启动等操作。

延用上面的bash脚本,创建systemd服务

cat > /usr/lib/systemd/system/http-proxy-boot.service <<EOF
[Unit]
Description=http-proxy-boot
After=network.target
[Service]
Type=forking
# restart时, 先执行ExecStop, 再执行ExecStart
ExecStart=/root/entrance start
ExecStop=/root/entrance stop
PrivateTmp=true
# kill按理说,应该返回状态0,但是java比较特殊,返回的是143
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
EOF

之后就可以进行操作啦

systemctl start|stop|restart|enable|disable http-proxy-boot

三、参考致谢

如何在统信UOS系统中设置tomcat开机启动_统信uos系统部署tomcat-CSDN博客

tomcat/bin/catalina.sh at main · apache/tomcat

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1381826.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自动驾驶二维激光雷达标定板

自动驾驶是人类智慧的结晶&#xff0c;它融合了多种高科技技术&#xff0c;包括传感器技术、计算机视觉、人工智能等&#xff0c;它让汽车具备了自主感知和决策的能力&#xff0c;可以在复杂多变的道路环境中自如应对。这种技术带给我们的不仅仅是出行的便利&#xff0c;更是对…

Open3D 反算点云缩放系数(21)

Open3D 反算点云缩放系数(21) 一、算法介绍二、算法实现1.方法12.方法2(通用)一、算法介绍 上一章按照指定的系数,对点云进行了等比例缩放,这里输入缩放后的两块点云,反算二者之间的缩放系数。 二、算法实现 已知使用的俩点云是1/2的缩放关系,用于验证计算结果是否…

JQuery 操作Class滚动轮播展示效果

JQuery 操作Class滚动轮播展示效果 展示效果&#xff1a; 1.html <div class"list"><div class"item"><div class"icon"></div><div class"content">第一行xxxxxxxxx</div></div><div …

NetDevOps:华三交换机通过Netmiko或者Nornir获取接口信息通过TextFSM解析报错问题

python代码&#xff1a;实现功能获取交换机接口信息并通过TextFSM进行解析。 from netmiko import Netmiko import textfsm show_intf_cmd_mapping {hp_comware: display interface, }def ssh_device_2_get_intfs(device_type, host, username, password, port):dev_info {d…

java中多线程

文章目录 多线程进程和线程进程线程 继承Thread类方式实现多线程设置线程名字的两个方式获取正在运行的线程线程调度模型和线程优先级设置两种调度模型优先级设置 线程控制sleepjoin守护线程 线程生命周期 多线程 进程和线程 进程 进程&#xff1a;是正在运行的程序 是系统进…

【非监督学习 02】高斯混合模型

高斯混合模型&#xff08;Guassian Mixed Model, GMM&#xff09;也是一种常见的聚类算法&#xff0c;与K均值算法类似&#xff0c;同样使用了EM算法进行迭代计算。高斯混合模型假设每个簇的数据都是符合高斯分布的&#xff0c;当前数据呈现的分布就是各个簇的高斯分布叠加在一…

手写Webpack-Plugin

Plugin原理 一、Plugin作用 通过插件我们可以扩展webpack&#xff0c;使webpack可以执行更广泛的任务&#xff0c;拥有更强的构建能力。 Plugin工作原理 webpack 就像一条生产线&#xff0c;要经过一系列处理流程后才能将源文件转换成输出结果。 这条生产线上的每个处理流程…

亚马逊时尚如何运用人工智能帮助您找到合适的尺码

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

React16源码: React中的schedule调度整体流程

schedule调度的整体流程 React Fiber Scheduler 是 react16 最核心的一部分&#xff0c;这块在 react-reconciler 这个包中这个包的核心是 fiber reconciler&#xff0c;也即是 fiber 结构fiber 的结构帮助我们把react整个树的应用&#xff0c;更新的流程&#xff0c;能够拆成…

GitHub Copilot的使用方法和快捷按键

GitHub Copilot是GitHub与OpenAI合作开发的一款人工智能编码助手。它基于GPT&#xff08;Generative Pre-trained Transformer&#xff09;模型&#xff0c;可以为你提供代码补全、建议和生成的功能 使用方法&#xff1a; 安装插件&#xff1a; 首先&#xff0c;确保你的开发环…

二阶构造设计模式

目录 构造函数回顾 深入思考 实验 构造函数的真相 半成品对象 引入二阶构造设计模式 设计理念 二阶构造设计模式图 二阶构造示例 完整demo 小结 构造函数回顾 类的构造函数用于对象的初始化。构造函数与类同名并且没有返回值。构造函数在对象定义时自动被调用 深入…

Grounding DINO:开放集目标检测,将基于Transformer的检测器DINO与真值预训练相结合

文章目录 背景知识补充CLIP (Contrastive Language-Image Pre-training)&#xff1a;打破文字和图像之间的壁垒DINO(Data-INterpolating Neural Network)&#xff1a;视觉 Transformer 的自监督学习Stable Diffusion&#xff1a;从文本描述中生成详细的图像Open-set Detector开…

系列七、Spring Security中基于Jdbc的用户认证 授权

一、Spring Security中基于Jdbc的用户认证 & 授权 1.1、概述 前面的系列文章介绍了基于内存定义用户的方式&#xff0c;其实Spring Security中还提供了基于Jdbc的用户认证 & 授权&#xff0c;再说基于Jdbc的用户认证 & 授权之前&#xff0c;不得不说一下Spring Se…

【Blog】记录一下如何让自己的自建网站让百度搜索收录

记录一下如何让自己的自建网站让百度搜索收录 目录 记录一下如何让自己的自建网站让百度搜索收录一、前言二、开始操作1、第一步&#xff1a;进入设置2、第二步&#xff1a;开始设置3、第三步&#xff1a;让百度收录我们自己的文章 三、知识点记录1、注意事项2、可能会出现的问…

暄桐写字计划 | 开始布局我们的2024

暄桐是一间传统美学教育教室&#xff0c;创办于2011年&#xff0c;林曦是创办人和授课老师&#xff0c;教授以书法为主的传统文化和技艺&#xff0c;皆在以书法为起点&#xff0c;亲近中国传统之美&#xff0c;以实践和所得&#xff0c;滋养当下生活。      暄桐林曦老师有…

Kafka的安装、管理和配置

Kafka的安装、管理和配置 1.Kafka安装 官网: https://kafka.apache.org/downloads 下载安装包,我这里下载的是https://archive.apache.org/dist/kafka/3.3.1/kafka_2.13-3.3.1.tgz Kafka是Java生态圈下的一员&#xff0c;用Scala编写&#xff0c;运行在Java虚拟机上&#xf…

ENNOID-BMS从控板分析-基于LTC6813的版本

LTC6813简单说明 单体电压采集部分&#xff0c;总共可以采集18个电芯电压&#xff0c;这18个电压分别交给3个16位Delta-Sigma ADC来进行采样&#xff1b;官方手册宣称的采样误差低于2.2mV&#xff0c;采样范围为0~5V&#xff0c;所有18个电芯采样一次只要290uS时间。电压均衡部…

C++学习笔记——友元、嵌套类、异常

目录 一、友元 一个使用友元的示例代码 输出结果 二、嵌套类 一个使用嵌套类的示例代码 输出结果 三、异常 一个使用异常处理的示例代码 输出结果 四、结论 五、使用它们的注意事项 上一篇文章链接&#xff1a; C中的继承和模板是非常强大和灵活的特性&#xff0c;它…

跟着cherno手搓游戏引擎【5】layer(层)、Glad

编写基类层&#xff1a; Layer.h:提供Attach链接、Detach解绑、Update刷新、Event事件、GetName方法 #pragma once #include"YOTO/Core.h" #include"YOTO/Event/Event.h" namespace YOTO {class YOTO_API Layer{public:Layer(const std::string& nam…

【c/python】用GTK实现一个带菜单的窗口

一、用python 在GTK中创建一个带菜单的窗口&#xff0c;可以通过使用Gtk.MenuBar、Gtk.Menu和Gtk.MenuItem组件来构建菜单。以下是一个基本的例子&#xff0c;展示了如何使用Python的PyGObject库创建一个简单的带菜单栏的GTK窗口。 import gi gi.require_version(Gtk, 3.0) f…