- Shell 如何获取 Java 程序的退出状态码 (Exit Status):这是最常用、最标准的 Unix/Linux 约定,用于表示程序是成功执行还是遇到了错误。
- Java 程序如何向 Shell 输出数据(标准输出/标准错误):这通常用于将计算结果、日志等信息传递回 Shell。
下面我将详细解释这两个方面,并提供完整的示例。

获取 Java 程序的退出状态码
在 Shell 中,任何一个命令执行后都会返回一个状态码,约定俗成的是:
0表示成功执行。- 非零 表示执行失败,不同的非零值可以代表不同的错误类型。
Java 程序的退出状态码由 System.exit(int status) 方法决定,如果不调用该方法,Java 程序正常执行完毕后,默认返回 0。
关键 Shell 变量:
在 Shell 中, 是一个特殊变量,它保存了上一个前台执行的命令的退出状态码。
示例步骤
步骤 1:创建一个简单的 Java 程序

这个程序会根据传入的参数决定是成功退出还是失败退出。
ExitStatusDemo.java:
public class ExitStatusDemo {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("用法: java ExitStatusDemo <success|fail>");
System.exit(1); // 参数错误,返回 1
}
String command = args[0];
if ("success".equalsIgnoreCase(command)) {
System.out.println("Java 程序执行成功,准备退出。");
System.exit(0); // 成功,返回 0
} else if ("fail".equalsIgnoreCase(command)) {
System.err.println("Java 程序执行失败,准备退出。");
System.exit(2); // 失败,返回 2
} else {
System.out.println("未知命令: " + command);
System.exit(3); // 未知错误,返回 3
}
}
}
步骤 2:编译 Java 程序
javac ExitStatusDemo.java
步骤 3:在 Shell 脚本中调用并检查返回值
创建一个 Shell 脚本,test_exit_status.sh。
test_exit_status.sh:
#!/bin/bash
echo "测试 1: 调用 Java 程序并传入 'success'"
java ExitStatusDemo success
# $? 保存了上一个命令的退出码
JAVA_EXIT_CODE=$?
echo "Java 程序的退出码是: $JAVA_EXIT_CODE"
if [ $JAVA_EXIT_CODE -eq 0 ]; then
echo "测试 1 结果: 成功"
else
echo "测试 1 结果: 失败"
fi
echo -e "\n----------------------------------------\n"
echo "测试 2: 调用 Java 程序并传入 'fail'"
java ExitStatusDemo fail
JAVA_EXIT_CODE=$?
echo "Java 程序的退出码是: $JAVA_EXIT_CODE"
if [ $JAVA_EXIT_CODE -eq 0 ]; then
echo "测试 2 结果: 成功"
else
echo "测试 2 结果: 失败"
fi
步骤 4:运行 Shell 脚本
首先给脚本添加执行权限,然后运行它:
chmod +x test_exit_status.sh ./test_exit_status.sh
预期输出:
测试 1: 调用 Java 程序并传入 'success'
Java 程序执行成功,准备退出。
Java 程序的退出码是: 0
测试 1 结果: 成功
----------------------------------------
测试 2: 调用 Java 程序并传入 'fail'
Java 程序执行失败,准备退出。
Java 程序的退出码是: 2
测试 2 结果: 失败
从输出中可以清楚地看到,Shell 成功捕获了 Java 程序通过 System.exit() 设置的返回值。
获取 Java 程序的标准输出
除了状态码,Java 程序通过 System.out.println() 输出的内容会进入标准输出流,而通过 System.err.println() 输出的内容会进入标准错误流,Shell 可以轻松捕获这些流。
关键 Shell 操作符
- 或反引号 `
` ...`:命令替换,它会捕获一个命令的标准输出,并将其作为字符串赋值给一个变量。 >:将标准输出重定向到文件。2>:将标准错误重定向到文件。&>:将标准输出和标准错误都重定向到文件。command 2>&1:将标准错误合并到标准输出。
示例步骤
步骤 1:创建一个输出数据的 Java 程序
OutputDemo.java:
public class OutputDemo {
public static void main(String[] args) {
// 正常输出,会进入标准输出
System.out.println("这是标准输出的第一条消息。");
// 错误信息,会进入标准错误
System.err.println("这是标准错误的消息。");
// 如果有参数,打印出来
if (args.length > 0) {
System.out.println("你传入的参数是: " + args[0]);
}
}
}
步骤 2:编译
javac OutputDemo.java
步骤 3:在 Shell 中捕获输出
场景 A:只捕获标准输出
#!/bin/bash echo "--- 只捕获标准输出 ---" # $(...) 会捕获 System.out.println 的内容 output=$(java OutputDemo hello) echo "从 Java 程序捕获到的标准输出内容是:" echo "'$output'" echo "Java 程序的退出码是: $?"
运行结果:
--- 只捕获标准输出 ---
这是标准错误的消息。 <-- 这行没有在 $output 变量中
从 Java 程序捕获到的标准输出内容是:
'这是标准输出的第一条消息。
你传入的参数是: hello'
Java 程序的退出码是: 0
场景 B:将标准输出和标准错误都重定向到文件
#!/bin/bash echo "--- 将所有输出重定向到文件 output.log ---" java OutputDemo test > output.log 2>&1 # 或者直接用 java OutputDemo test &> output.log echo "Java 程序的退出码是: $?" echo "请查看 output.log 文件的内容。"
output.log 文件的内容将是:
这是标准输出的第一条消息。
这是标准错误的消息。
你传入的参数是: test
最佳实践:结合状态码和标准输出
在实际应用中,一个健壮的 Shell 脚本通常会同时检查 Java 程序的退出状态码和。
- 用退出状态码判断“成功与否”:这是一个可靠、快速的信号。
- 用标准输出传递“数据”:这是传递计算结果、日志等详细信息的方式。
示例:一个完整的健壮调用
假设我们有一个 Java 工具,它执行一个计算,成功时返回结果,失败时返回错误信息。
Calculator.java:
public class Calculator {
public static void main(String[] args) {
if (args.length != 2) {
System.err.println("错误: 必须提供两个参数。");
System.exit(1);
}
try {
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
int sum = a + b;
System.out.println(sum); // 将计算结果输出到标准输出
System.exit(0);
} catch (NumberFormatException e) {
System.err.println("错误: 参数必须是整数。");
System.exit(2);
}
}
}
robust_call.sh:
#!/bin/bash
echo "执行计算: 10 + 20"
# 调用 Java 程序,并立即捕获其输出和退出码
# 使用 'if' 语句可以方便地检查退出码
if java Calculator 10 20; then
# 如果退出码为 0,则执行这里的代码
# $(...) 中的命令已经执行成功,所以可以直接捕获输出
result=$(java Calculator 10 20)
echo "计算成功!"
echo "结果是: $result"
else
# 如果退出码非 0,则执行这里的代码
echo "计算失败!" >&2 # 将错误信息输出到标准错误
exit 1 # 让当前脚本也以失败状态退出
fi
echo -e "\n执行计算: 10 abc"
if java Calculator 10 abc; then
result=$(java Calculator 10 abc)
echo "计算成功!"
echo "结果是: $result"
else
echo "计算失败!" >&2
exit 1
fi
运行 robust_call.sh 的输出:
执行计算: 10 + 20
30
计算成功!
结果是: 30
执行计算: 10 abc
错误: 参数必须是整数。
计算失败!
这个脚本清晰地展示了如何根据 Java 程序的成败执行不同的逻辑,并在成功时处理其返回的数据。
| 目的 | Java 端 | Shell 端 |
|---|---|---|
| 返回执行状态 | System.exit(0); (成功)System.exit(1); (失败) |
java MyProgramif [ $? -eq 0 ]; then ...或者 if java MyProgram; then ... |
| 返回数据 | System.out.println("data"); |
output=$(java MyProgram)echo "Got: $output" |
| 返回错误信息 | System.err.println("error msg"); |
java MyProgram 2> error.log或 java MyProgram > all.log 2>&1 |
| 最佳实践 | 用 System.exit() 表示程序是否成功,用 System.out/System.err 输出业务数据和日志。 |
先检查 或使用 if 判断成败,再决定是否处理 捕获的输出。 |
