【Linux】Linux环境下运行jar包的几种方式
方式一(java -jar jar包名)
# 命令格式:java -jar jar包名
[root@localhost test_jar]# java -jar test_jar-1.0-SNAPSHOT.jar分析: 执行此命令的时候,当前窗口被锁定,无法进行其它操作,直到main方法执行完毕,当前窗口才解除锁定。
缺点: 锁定窗口。当然,我可以通过CTRL + C打断程序运行,或直接关闭窗口,程序退出,不过在实际的工作环境中,是绝对不会允许这种粗暴的方式终止的运行,毕竟我们的项目都是给用户提供服务的,程序要是退出了,公司还营不营业了。
方式二(java -jar jar包名 &)
命令格式:java -jar jar包名 &
[root@localhost test_jar]# java -jar test_jar-1.0-SNAPSHOT.jar &分析: &代表在后台运行。优点是当前ssh窗口不被锁定,但是当窗口关闭时,程序终止运行。
那么我们就会想,如何继续改进,让窗口关闭时,程序仍然运行呢?
方式三
方式三主要是引入nohup命令,具体使用主要包括下面三种方式。
命令格式:nohup java -jar jar包名 &
# 命令格式:nohup java -jar jar包名 &[root@localhost test_jar]# nohup java -jar test_jar-1.0-SNAPSHOT.jar &nohup 意思是不挂断运行命令 ,当账户退出或终端关闭时,程序仍然运行。
当用 nohup 命令运行jar包时,缺省情况下该应用的所有输出被重定向到nohup.out的文件中,除非另外指定了输出文件。
命令格式:nohup java -jar jar包名 > 文件名 &
# nohup java -jar jar包名 > 文件名 &[root@localhost test_jar]# nohup java -jar test_jar-1.0-SNAPSHOT.jar > test.txt &command >test.file 是将commandd test.flie文件,即输出内容不打印到屏幕上,而是输出到 test.file文件中
命令格式: nohup java -jar jar包名 >output 2>&1 &
# nohup java -jar jar包名 >output 2>&1 &
[root@localhost test_jar]# nohup java -jar test_jar-1.0-SNAPSHOT.jar >output 2>&1 &命令格式:nohup java -jar spring-boot-demo.jar > /dev/null 2>&1 &
不输出日志
方式四:脚本方式
#!/bin/bash
#这里可替换为你自己的执行程序,其他代码无需更改APP_NAME=test_jar-1.0-SNAPSHOT.jar
#使用说明,用来提示输入参数usage() { echo "Usage: sh 脚本名.sh [start|stop|restart|status]" exit 1}
#检查程序是否在运行is_exist(){ pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' ` #如果不存在返回1,存在返回0 if [ -z "${pid}" ]; then return 1 else return 0 fi}
#启动方法start(){ is_exist if [ $? -eq "0" ]; then echo "${APP_NAME} is already running. pid=${pid} ." else nohup java -Xmx512m -Xms512m -jar $APP_NAME > ./logs/`log+%Y-%m-%d`.txt 2>&1 & echo "${APP_NAME} start success" fi}
#停止方法stop(){ is_exist if [ $? -eq "0" ]; then kill -9 $pid else echo "${APP_NAME} is not running" fi}
#输出运行状态status(){ is_exist if [ $? -eq "0" ]; then echo "${APP_NAME} is running. Pid is ${pid}" else echo "${APP_NAME} is NOT running." fi}
#重启restart(){ stop start}
#根据输入参数,选择执行对应方法,不输入则执行使用说明case "$1" in "start") start ;; "stop") stop ;; "status") status ;; "restart") restart ;; *) usage ;;esac附录一: nohup 和 &
使用
&后台运行程序:
- 结果会输出到终端
- 使用Ctrl + C,程序免疫
- 关闭session,程序关闭
使用
nohup运行程序
- 结果默认会输出到nohup.out
- 使用Ctrl + C,程序关闭
- 关闭session,程序免疫
平日线上经常使用nohup和&配合来启动程序
附录二:> /dev/null 2>&1
>标准重定向符,允许我们创建一个 0KB的空文件。它通常用于重定向一个命令的输出到一个新文件中。在没有命令的情况下使用重定向符号时,它会创建一个文件。/dev/null可以看作黑洞,等价于一个只写文件。所有写入它的内容都会永远丢失,尝试从它那儿读取内容则什么也读不到。也就是将所有产生的日志将被丢弃2>&1符号>&是一个整体代表将标准错误2重定向到标准输出1,如果是2>1的话,代表将标准错误输出到文件1,而不是重定向到标准输出流
先了解下1和2在Linux中代表什么
当Linux执行一个程序时,会自动打开三个流
- 0:标准输入流(默认是键盘)
- 1:标准输出流(默认是屏幕)
- 2:标准错误流(默认是屏幕)
| 名称 | 代码 | 操作符 | java中表示 | Linux中文件描述符 |
|---|---|---|---|---|
| 标准输入(stdin) | 0 | < 或 << | System.in | /dev/stdin -> /proc/self/fd/0 -> /dev/pts/0 |
| 标准输出(stdout) | 1 | >, >>, 1> 或 1>> | System.out | /dev/stdout -> /proc/self/fd/1 -> /dev/pts/0 |
| 标准错误输出(stderr) | 2 | 2> 或 2>> | System.err | /dev/stderr -> /proc/self/fd/2 -> /dev/pts/0 |
批量启动、停止jar包
#!/bin/bash# 端口号PORTS=(9500 9600 9801 9802 9803 9804 9805 9901 9902)# 系统模块MODULES=(gateway auth system job gen file risk supervise ssologin)# 系统模块名称MODULE_NAMES=(网关模块 鉴权模块 系统管理模块 定时任务模块 代码生成模块 文件管理模块 风险预警模块)# jar包数组JARS=(catsticloud-gateway.jar catsticloud-auth.jar catsticloud-modules-system.jar catsticloud-modules-job.jar catsticloud-modules-gen.jar catsticloud-modules-file.jar catsticloud-modules-risk.jar catsticloud-supervise.jar catsticloud-modules-ssologin.jar)# jar包路径JAR_PATH='/home/yunwei/gonggonganquan/jar'# 日志路径LOG_PATH='/home/yunwei/gonggonganquan/jar/logs'start() { local MODULE= local MODULE_NAME= local JAR_NAME= local command="$1" local commandOk=0 local count=0 local okCount=0 local port=0 for((i=0;i<${#MODULES[@]};i++)) do MODULE=${MODULES[$i]} MODULE_NAME=${MODULE_NAMES[$i]} JAR_NAME=${JARS[$i]} PORT=${PORTS[$i]} if [ "$command" == "all" ] || [ "$command" == "$MODULE" ];then commandOk=1 count=0 PID=`ps -ef |grep $(echo $JAR_NAME | awk -F/ '{print $NF}') | grep -v grep | awk '{print $2}'` if [ -n "$PID" ];then echo "$MODULE---$MODULE_NAME:已经运行,PID=$PID" else exec nohup java -jar $JAR_PATH/$JAR_NAME > /dev/null 2>&1 & PID=`netstat -apn | grep $PORT | awk '{print $7}' | cut -d/ -f 1` while [ -z "$PID" ] do if (($count == 30));then echo "$MODULE---$MODULE_NAME:$(expr $count \* 10)秒内未启动,请检查!" break fi count=$(($count+1)) echo "$MODULE_NAME启动中.................." sleep 10s PID=`netstat -apn | grep $PORT | awk '{print $7}' | cut -d/ -f 1` done okCount=$(($okCount+1)) echo "$MODULE---$MODULE_NAME:已经启动成功,PID=$PID" fi fi done if(($commandOk == 0));then echo "第二个参数请输入:all|gateway|auth|system|job|gen|file|risk|supervise|ssologin" else echo "............本次共启动:$okCount个服务..........." fi}
stop() { local MODULE= local MODULE_NAME= local JAR_NAME= local command="$1" local commandOk=0 local okCount=0 for((i=0;i<${#MODULES[@]};i++)) do MODULE=${MODULES[$i]} MODULE_NAME=${MODULE_NAMES[$i]} JAR_NAME=${JARS[$i]} if [ "$command" = "all" ] || [ "$command" = "$MODULE" ];then commandOk=1 PID=`ps -ef |grep $(echo $JAR_NAME | awk -F/ '{print $NF}') | grep -v grep | awk '{print $2}'` if [ -n "$PID" ];then echo "$MODULE---$MODULE_NAME:准备结束,PID=$PID" kill -9 $PID PID=`ps -ef |grep $(echo $JAR_NAME | awk -F/ '{print $NF}') | grep -v grep | awk '{print $2}'` while [ -n "$PID" ] do sleep 3s PID=`ps -ef |grep $(echo $JAR_NAME | awk -F/ '{print $NF}') | grep -v grep | awk '{print $2}'` done echo "$MODULE---$MODULE_NAME:成功结束" okCount=$(($okCount+1)) else echo "$MODULE---$MODULE_NAME:未运行" fi fi done if (($commandOk == 0));then echo "第二个参数请输入:all|gateway|auth|system|job|gen|file|risk|supervise|ssologin" else echo "............本次共停止:$okCount个服务............" fi}status() { local MODULE= local MODULE_NAME= local JAR_NAME= local command="$1" local commandOk=0 local count=0 local okCount=0 local port=0 for((i=0;i<${#MODULES[@]};i++)) do MODULE=${MODULES[$i]} MODULE_NAME=${MODULE_NAMES[$i]} JAR_NAME=${JARS[$i]} PORT=${PORTS[$i]} if [ "$command" == "all" ] || [ "$command" == "$MODULE" ];then commandOk=1 count=$(($i+1)) PID=`ps -ef |grep $(echo $JAR_NAME | awk -F/ '{print $NF}') | grep -v grep | awk '{print $2}'` if [ -n "$PID" ];then echo "$MODULE---$MODULE_NAME:已经运行,PID=$PID" okCount=$(($okCount+1)) else echo "$MODULE---$MODULE_NAME:未运行" fi fi done if(($commandOk == 0));then echo "第二个参数请输入:all|gateway|auth|system|job|gen|file|risk|supervise|ssologin" else echo "............共:$count 个服务,运行中$okCount个服务..........." fi}
case "$1" in start) start "$2" ;; stop) stop "$2" ;; status) status "$2" ;; restart) stop "$2" sleep 3s start "$2" ;; *) echo "第一个参数请输入:start|stop|restart|status" exit 1 ;;esac启动:
## 启动所有./start.sh start all## 停止所有./start.sh stop all## 重启所有./start.sh restart all## 启动某一个 这里的gateway与sh中的module中定义的一样即可./start.sh restart gateway问题1:
-bash: ./start.sh: Permission denied\原因: 无权限 解决方法:chmod +x ./文件名.sh
问题2:
bad interpreter\:No such file or directory的错误
原因: .sh脚本在windows系统下编写的,所以可能有不可见字符,从上图错误提示来看,很有可能脚本文件是DOS格式的,即每一行的行尾以\r\n来标识, 其ASCII码分别是0x0D, 0x0A。 解决方法:
- 通过
vim filename或者vi filename进入编辑,即我这是vim startup\_heartbeat.sh- 然后通过
shift+:进入命令模式。接着通过命令set ff或者set fileformat查看文件格式,即我这如下图:从中可以看到我这文件格式是dos- 修改文件格式dos为unix。通过命令
set ff=unix或set fileformat=unix修改,然后再执行set ff或者set fileformat,查看是否修改成功。即如下图所示- 启动命令,发现正常启动,至此完毕。
服务开机自启
一、新建jar包启动sh文件
新建startup.sh脚本文件,启动项目jar包
nohup java -jar test.jar >/dev/null 2>&1 &
二、设置自动启动命令
1.进入rc.d目录
执行cd /etc/rc.d 命令,进入rc.d目录
如图所示(示例):
2.修改rc.local文件内容
执行命令 vi rc.local,然后按下键盘上的【i】键进入修改模式
在末尾加上如下命令:
#进入项目目录cd /home/test`#执行sh文件sh /home/test/startup.sh然后先按下【esc】键,再按下【:】键,在光标闪烁处输入:wq。按回车,完成修改后,执行相应命令,设置执行权限,重启服务器,验证即可。
chmod +x /etc/rc.d/rc.localchmod +x /home/test/startup.sh有时服务器重启服务很多时,可能需要延迟启动,可以在之前的命令前加上sleep 60命令延迟启动
sleep 60cd /home/testsh /home/test/startup.sh服务方式启动
Terminal window 可以添加一个 systemd的服务 基本上可以如图进行设置一般位于 /etc/systemd/system/ 下面比如可以建立一个文件为 app.service可以使用 systemctl enable app 设置开机自动启动然后使用systemctl start app 来启动服务
[Unit]Description = Redis ServerAfter = network.target[Service]ExecStart=/app/startup.shExecStop=/usr/bin/kill -15 $MAINPIDRestart = always[Install]WantedBy = multi-user.target支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!
小王的博客














