方式一(java -jar jar包名)
1 2 3
| # 命令格式:java -jar jar包名
[root@localhost test_jar]# java -jar test_jar-1.0-SNAPSHOT.jar
|
分析: 执行此命令的时候,当前窗口被锁定,无法进行其它操作,直到main方法执行完毕,当前窗口才解除锁定。
缺点: 锁定窗口。当然,我可以通过CTRL + C打断程序运行,或直接关闭窗口,程序退出,不过在实际的工作环境中,是绝对不会允许这种粗暴的方式终止的运行,毕竟我们的项目都是给用户提供服务的,程序要是退出了,公司还营不营业了。
方式二(java -jar jar包名 &)
1 2 3
| 命令格式:java -jar jar包名 &
[root@localhost test_jar]# java -jar test_jar-1.0-SNAPSHOT.jar &
|
分析: &代表在后台运行。优点是当前ssh窗口不被锁定,但是当窗口关闭时,程序终止运行。
那么我们就会想,如何继续改进,让窗口关闭时,程序仍然运行呢?
方式三
方式三主要是引入nohup命令,具体使用主要包括下面三种方式。
命令格式:nohup java -jar jar包名 &
1 2
| # 命令格式: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包名 > 文件名 &
1 2
| # 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 &
1 2 3
| # 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 &
不输出日志
方式四:脚本方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| #!/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}' ` 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包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
| #!/bin/bash
PORTS=(9500 9600 9801 9802 9803 9804 9805 9901 9902)
MODULES=(gateway auth system job gen file risk supervise ssologin)
MODULE_NAMES=(网关模块 鉴权模块 系统管理模块 定时任务模块 代码生成模块 文件管理模块 风险预警模块)
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_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
|
启动:
1 2 3 4 5 6 7 8
| ./start.sh start all
./start.sh stop all
./start.sh restart all
./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】键进入修改模式
在末尾加上如下命令:
1 2 3 4
| cd /home/test`
sh /home/test/startup.sh
|
然后先按下【esc】键,再按下【:】键,在光标闪烁处输入:wq
。按回车,完成修改后,执行相应命令,设置执行权限,重启服务器,验证即可。
1 2
| chmod +x /etc/rc.d/rc.local chmod +x /home/test/startup.sh
|
有时服务器重启服务很多时,可能需要延迟启动,可以在之前的命令前加上sleep 60命令延迟启动
1 2 3
| sleep 60 cd /home/test sh /home/test/startup.sh
|
服务方式启动
1 2 3 4 5
| 可以添加一个 systemd的服务 基本上可以如图进行设置 一般位于 /etc/systemd/system/ 下面 比如可以建立一个文件为 app.service 可以使用 systemctl enable app 设置开机自动启动 然后使用systemctl start app 来启动服务
|
1 2 3 4 5 6 7 8 9
| [Unit] Description = Redis Server After = network.target [Service] ExecStart=/app/startup.sh ExecStop=/usr/bin/kill -15 $MAINPID Restart = always [Install] WantedBy = multi-user.target
|