为什么“java -version”将其输出打印到错误流中?

8

让我们尝试重定向java的标准错误:

java -version 2> ~/error.txt

error.txt中记录了版本信息。

让我们尝试重定向标准输出:

java -version > ~/output.txt

output.txt是空的。

为什么java二进制文件将正常输出打印到错误流中?


大多数编译器都会这样做。 - user207421
@EJP那不是一个答案。我的后续问题是-为什么?JeffBowman有一个很好的解释。 - Kshitiz Sharma
你说得对。这不是一个答案。这就是为什么我把它发布为评论的原因。 - user207421
2个回答

12
根据Java文档
- showversion 显示版本信息并继续执行应用程序。此选项相当于-version选项,但后者指示JVM在显示版本信息后退出。
- version 显示版本信息,然后退出。此选项相当于-showversion选项,但后者在显示版本信息后不指示JVM退出。
现在考虑stderr的维基百科定义
标准错误是另一个输出流,通常由程序用于输出错误消息或诊断信息。
大多数POSIX中心工具为其stdout流规定了非常谨慎的规范,因此可以将工具的输出管道传输到其他位置。stderr的规定要少得多,并且经常用于日志记录和错误。
使用 -showversion,Java 允许版本信息被打印在正在运行的应用程序旁边。然而,如果版本信息被打印到 stdout,它将与正常的应用程序输出难以区分,并迫使您自行扫描并删除该输出行。当然,使用 -version 而不是 -showversion,版本字符串很可能是预期的输出,但保持一致性本身就是一个不错的结束。
值得一提的是,将请求的元数据打印到 stderr 和 stdout 中是一个开放的问题, 因此除了每个应用程序文档化的行为之外,几乎没有标准实践。
要解决这个问题,只需将 stderr 重定向到 stdout 即可:
VERSION=$(java -version 2>&1)

2
在OpenJdk 11.0.1上有4个选项:-version--version-showversion--showversionversionshowversion都具有相同的效果,但只使用一个破折号时会输出错误,而使用两个破折号则都会正常输出并且可以存储到变量中。如果出于某种原因您想要获取错误输出并将其存储到变量中,可以像这样操作:
Invoke-Expression "java -version" -ErrorVariable javaVaraible java : openjdk version "11.0.1" 2018-10-16 ... $javaVaraible java : openjdk version "11.0.1" 2018-10-16 ...
- Thibault

2
似乎Java命令与其他许多UNIX命令的不一致之处在于将版本输出发送到标准输出。可能是一个错误或者只是不一致的问题: mvn -v > ~/output.txt # 可以正常工作 有个错误报告,但已被关闭。可能Oracle无法解决这个问题,因为这可能会对期望其按照这种方式运行的系统造成问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接