杰瑞科技汇

Linux shell如何调用Java程序?

java 命令

在 Shell 中调用 Java,本质上是使用系统的 java 命令来启动 Java 虚拟机,并加载你的 Java 类。

Linux shell如何调用Java程序?-图1
(图片来源网络,侵删)

java 命令的基本语法是:

java [options] class [args...]
  • [options]: JVM 的启动参数,-Xmx (设置最大堆内存)、-D (设置系统属性) 等。
  • class: 你想要执行的 Java 主类的全限定名(com.example.MyApp)。
  • [args...]: 传递给 Java 程序 main 方法的参数。

调用一个简单的 Java 程序

假设你有一个简单的 Java 项目结构如下:

my-project/
├── src/
│   └── com/
│       └── example/
│           └── Hello.java
└── lib/
    └── my-library.jar  (如果依赖了外部jar包)

Java 代码 (src/com/example/Hello.java)

package com.example;
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello from Java!");
        // 打印从 Shell 传递过来的参数
        if (args.length > 0) {
            System.out.println("Arguments received from Shell:");
            for (int i = 0; i < args.length; i++) {
                System.out.println("arg[" + i + "] = " + args[i]);
            }
        }
    }
}

编译 Java 代码

Linux shell如何调用Java程序?-图2
(图片来源网络,侵删)

my-project 目录下,使用 javac 命令编译:

# -d . 表示将生成的 .class 文件输出到当前目录
# -cp src 表示在 src 目录下查找源文件
javac -d . -cp src src/com/example/Hello.java

编译后,会生成 com/example/Hello.class 文件。

在 Shell 脚本中调用

创建一个名为 run.sh 的 Shell 脚本:

Linux shell如何调用Java程序?-图3
(图片来源网络,侵删)
#!/bin/bash
echo "--- Starting Java Application ---"
# 调用 java 命令
# 1. java: 命令本身
# 2. -cp .: 设置 classpath 为当前目录,因为 Hello.class 
# 3. com.example.Hello: 主类的全限定名
# 4. "arg1" "arg2": 传递给 main 方法的参数
java -cp . com.example.Hello "arg1 from shell" "arg2 with spaces"
echo "--- Java Application Finished ---"

执行 Shell 脚本

首先给 run.sh 添加执行权限,然后运行它:

chmod +x run.sh
./run.sh

预期输出:

--- Starting Java Application ---
Hello from Java!
Arguments received from Shell:
arg[0] = arg1 from shell
arg[1] = arg2 with spaces
--- Java Application Finished ---

处理复杂的依赖(多个 JAR 包)

在真实项目中,你的 Java 程序通常依赖很多 JAR 包,这时 classpath (-cp) 的设置会变得复杂。

假设你的项目结构如下:

my-project/
├── bin/                 # 存放编译后的 .class 文件
├── lib/                 # 存放所有依赖的 JAR 包
│   ├── library1.jar
│   └── library2.jar
└── src/
    └── com/
        └── example/
            └── App.java

编译

将编译后的 .class 文件放到 bin 目录:

mkdir -p bin
javac -d bin -cp "src:lib/*" src/com/example/App.java
  • -d bin: 输出到 bin 目录。
  • -cp "src:lib/*": 告诉编译器,源文件在 src,依赖的库在 lib 目录下的所有 JAR 包。

在 Shell 脚本中调用

直接在 -cp 中列出所有 JAR 路径非常繁琐且容易出错,推荐使用通配符 。

方法 A: 使用通配符(推荐)

#!/bin/bash
# 注意:通配符 * 会被 Shell 在执行 java 命令前展开
# java 命令会看到类似 java -cp bin:lib/library1.jar:lib/library2.jar ... 的形式
java -cp "bin:lib/*" com.example.App

方法 B: 使用 find 命令动态生成 classpath(更稳健)

这种方法可以更好地处理路径中包含空格或特殊字符的情况。

#!/bin/bash
# 使用 find 命令查找 lib 目录下所有 .jar 文件,并用冒号连接
LIB_CLASSPATH=$(find lib -name "*.jar" | tr '\n' ':')
# 最终的 classpath 是 bin 目录 + 所有 lib 下的 jar
# 注意结尾的冒号是为了语法清晰,但通常无害,最好去掉
FINAL_CLASSPATH="bin:${LIB_CLASSPATH%:}"
echo "Using classpath: ${FINAL_CLASSPATH}"
java -cp "${FINAL_CLASSPATH}" com.example.App

传递带空格的参数

这是一个常见的陷阱,Shell 会对参数进行单词分割,如果你想传递一个包含空格的参数,必须用引号(单引号或双引号)把它括起来。

#!/bin/bash
# 错误示范:arg2 with spaces 会被拆分成两个独立的参数
# java MyProgram "arg1" arg2 with spaces
# 正确示范:使用引号
java MyProgram "arg1" "arg2 with spaces"

最佳实践:在你的 Shell 脚本中,始终用引号把所有传递给 Java 程序的参数括起来,除非你有特殊需求。

#!/bin/bash
ARG1="first argument"
ARG2="second argument with spaces"
# "$@" 会将所有参数作为一个整体传递,并保留引号
# 这是最安全的方式
java MyProgram "$@"

获取 Java 程序的返回值(Exit Code)

Java 程序可以通过 System.exit(int code) 返回一个整数状态码,在 Shell 中,我们可以通过特殊变量 来获取上一个命令的退出码。

修改 Java 代码

public class MyApp {
    public static void main(String[] args) {
        if (args.length > 0 && args[0].equals("error")) {
            System.out.println("Exiting with error code 1.");
            System.exit(1); // 返回错误码
        }
        System.out.println("Exiting with success code 0.");
        System.exit(0); // 返回成功码
    }
}

Shell 脚本

#!/bin/bash
echo "Running Java app successfully..."
java -cp . com.example.MyApp
echo "Exit code from Java: $?" # 应该输出 0
echo "------------------------------------"
echo "Running Java app with error..."
java -cp . com.example.MyApp "error"
echo "Exit code from Java: $?" # 应该输出 1

输出:

Running Java app successfully...
Exiting with success code 0.
Exit code from Java: 0
------------------------------------
Running Java app with error...
Exiting with error code 1.
Exit code from Java: 1

重定向输入、输出和错误流

你可以像使用其他 Linux 命令一样,重定向 Java 程序的 I/O。

  • >: 标准输出重定向到文件(覆盖)
  • >>: 标准输出重定向到文件(追加)
  • 2>: 标准错误重定向到文件
  • &>: 标准输出和标准错误都重定向到文件

Shell 脚本示例

#!/bin/bash
# 将标准输出和标准错误都重定向到 app.log 文件
java -cp . com.example.App > app.log 2>&1
# 或者使用更简洁的 &>
java -cp . com.example.App &> app.log
echo "Application output has been written to app.log"
# 检查退出码
if [ $? -eq 0 ]; then
    echo "Application finished successfully."
else
    echo "Application failed."
fi

最佳实践和总结

  1. 使用 find 生成 Classpath:对于包含多个 JAR 依赖的项目,使用 find 命令动态生成 classpath 是最稳健、最不容易出错的方法。

  2. 正确处理参数:在 Shell 脚本中,始终用引号()将传递给 Java 程序的参数括起来,以防止 Shell 的单词分割和 globbing(通配符展开)。

  3. 检查返回码:使用 变量检查 Java 程序的退出码,这对于编写健壮的自动化脚本至关重要。0 表示成功,非 0 表示失败。

  4. 日志管理:使用重定向 (>, >>, 2>) 将 Java 程序的输出和错误信息保存到文件中,便于后续排查问题。

  5. 设置 JAVA_HOME:在服务器环境中,最好在脚本开头或系统环境变量中设置 JAVA_HOME,以确保使用正确的 Java 版本。

    #!/bin/bash
    export JAVA_HOME=/path/to/your/java/home
    export PATH=$JAVA_HOME/bin:$PATH
    java -version # 验证版本
  6. 考虑构建工具:对于复杂项目,手动管理编译和运行流程很麻烦,强烈建议使用 MavenGradle 等构建工具,它们可以自动处理依赖、编译、打包和运行,并提供了标准化的脚本(如 mvn spring-boot:run)。

通过掌握以上技巧,你就可以在 Linux Shell 脚本中灵活、可靠地调用和控制你的 Java 应用程序了。

分享:
扫描分享到社交APP
上一篇
下一篇