Linux环境下运行jar包的几种方式(附详细案例)

目录

 

一、 引言

二、运行jar包

1、方式一

2、方式二

3、方式三

三、脚本方式


一、 引言

    在学习过程中,我们大部分都是在windows等非Linux环境下进行开发、测试、部署等。但是在实际的工作当中,应用基本都是部署在Linux环境下,因此我们要熟悉Linux环境下应用的部署测试。如果做开发的还要兼职运维工作的话,那就更有必要掌握Linux环境下应用的部署方式。

      在Linux当中,运行jar包主要有以下几种方式。

      为了直观,本文还是以一个实际的项目作为演示,当然,是个极其简单的项目。

      首先,新建一个maven项目,pom.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>ztt</groupId>
    <artifactId>test_jar</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>hello.TestJar</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <!-- 项目编码-->
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

      注意:在pom.xml里面通过<mainClass>hello.TestJar</mainClass>指定了主类,如果不指定,可能会出现“xxx.jar中没有主清单属性”的问题。

      然后,编写一个带main方法的类。

package hello;

public class TestJar {
    public static void main(String[] args) {
        try {
            System.out.println("TestJar start!");
            for (int i = 0; i < 3; i++) {
                System.out.println("i:" + i);
            }
            // 暂停
            Thread.sleep(1000 * 10);
            System.out.println("TestJar finish!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

     

      如图所示,代码仅实现了简单的打印功能。在程序执行的过程中,我特意让主线程暂停了10秒,是为了在测试过程中方便观察。

      然后,将此jar包放到Linux环境下(建议使用winSCP操作),本文示例如下:

      然后,cd进入到此目录,下面我们开始就通过不同的方式来运行此jar包。

二、运行jar包

 

1、方式一

      命令格式:java -jar jar包名

      [root@localhost test_jar]# java -jar test_jar-1.0-SNAPSHOT.jar

      执行结果如下:

      10s之后,打印最后一行内容。

      分析:执行此命令的时候,程序会先打印前4行内容,然后暂停10s,当前窗口被锁定,无法进行其它操作,直到暂停时间结束,main方法执行完毕,当前窗口才解除锁定。

     因此,我们可以看到,此方式运行jar包一个极其严重的缺点:锁定窗口。当然,我可以通过CTRL + C打断程序运行,或直接关闭窗口,程序退出,不过在实际的工作环境中,是绝对不会允许这种粗暴的方式终止的运行,毕竟我们的项目都是给用户提供服务的,程序要是退出了,公司还营不营业了。

2、方式二

      命令格式:java -jar jar包名 &

      [root@localhost test_jar]# java -jar test_jar-1.0-SNAPSHOT.jar &

      执行结果如下:

      分析:&代表在后台运行。优点是当前ssh窗口不被锁定,但是当窗口关闭时,程序终止运行。

      那么我们就会想,如何继续改进,让窗口关闭时,程序仍然运行呢?

3、方式三

      方式三主要是引入nohup命令,具体使用主要包括下面三种方式。

(1)命令格式:nohup java -jar jar包名 &

      [root@localhost test_jar]# nohup java -jar test_jar-1.0-SNAPSHOT.jar &     

      nohup 意思是不挂断运行命令,当账户退出或终端关闭时,程序仍然运行。

      当用 nohup 命令运行jar包时,缺省情况下该应用的所有输出被重定向到nohup.out的文件中,除非另外指定了输出文件。

      执行结果如下:

      然后,我们在当前目录下看到了nohup.out文件。

打开nohup.out文件,发现前面所有的输出都重定向到了此文件里面。

(2)nohup java -jar jar包名 > 文件名 &

     [root@localhost test_jar]# nohup java -jar test_jar-1.0-SNAPSHOT.jar > test.txt &

      执行结果如下:

然后,再当前目录下出现test.txt文件。

      大家文件,发现输出都重定向到了test.txt文件里面。

(3)nohup java -jar jar包名 >output 2>&1 &

      [root@localhost test_jar]# nohup java -jar test_jar-1.0-SNAPSHOT.jar >output 2>&1 &

      linux shell中"2>&1"含 义:

      对于& 1 更准确的说应该是文件描述符 1,而1表示标准输出stdout。
      对于2 ,表示标准错误stderr。
      2>&1 的意思就是将标准错误重定向到标准输出。

      而标准输出又导入文件output里面,所以结果是标准错误和标准输出都导入文件output里面了。

      至于为什么需要将标准错误重定向到标准输出的原因,那就归结为标准错误没有缓冲区,而stdout有。这就会导致 >output 2>output, 文件output被两次打开,而stdout和stderr将会竞争覆盖,这肯定不是我门想要的。

      执行命令,结果如下:

      再当前目录下,出现了output文件,打开查看内容,在第一行出现了一行乱码(编码问题,不影响程序运行)。

      乱码处理之后的原文是:nohup: 忽略输入。其实就是标准错误的内容,因为>output 2>&1的作用是将标准输出和标准错误都重定向到output文件里。

(4)nohup java -jar jar包名 >/dev/null 2>&1 &

      [root@localhost test_jar]# nohup java -jar test_jar-1.0-SNAPSHOT.jar >/dev/null 2>&1 &

      这里谈一下/dev/null文件的作用。/dev/null是一个虚拟的空设备,可以看作是一个"黑洞",黑洞的特性是只进不出,哪怕是光都逃不掉,/dev/null亦是如此。

      它等价于一个只写文件,所有写入它的内容都会永远丢失。如果尝试从它那儿读取内容,那么什么也读不到。

      明白了/dev/null之后,我们再来看这个命令。>/dev/null 表示将标准输出信息重定向到"黑洞",2>&1 表示将标准错误重定向到标准输出,由于标准输出已经重定向到“黑洞”了(即:标准输出此时也是"黑洞"),再将标准错误输出定向到标准输出,相当于标准错误输出也被定向至“黑洞”。

      执行上述命令,不同于前面的那些命令,可以看到各种标准输出,这里什么也看不到。

三、脚本方式

      脚本方式的本质依然是上面介绍的那些命令,只不过shell脚本更加的方便,并且可以干更多的事情。

      这里依然以test_jar-1.0-SNAPSHOT.jar这个小demo为例,编写如下脚本test_jar.sh:

#!/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  > test2.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

      然后,执行这个脚本:

 

 

  • 57
    点赞
  • 248
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

架构帅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值