确定STDERR是否要去terminal

我有一套Java程序,在我们的Linux服务器上用作命令行工具。 他们大多使用一个在STDERR上打印进度条的类,类似于Perl的Term::ProgressBar

我希望每当STDERR进入terminal时都会显示进度条,并且在STDERR被redirect时自动禁用自身,这样redirect的数据中就没有各种进度条了。

检查System.console() == null是我的第一个想法,但redirectSTDOUT就足以使这是true ,即使STDERR仍然要去terminal。 有什么我可以检查是特定于STDERR? 特定于Linux的解决scheme或使用本机API的解决scheme对于我的需求可以。

Solutions Collecting From Web of "确定STDERR是否要去terminal"

我想你要找的是isatty(3) ,在unistd.h 。 没有办法判断一个文件句柄是否已被重定向,句点,但会告诉你它是否仍然是交互式的。 在GNU coreutils中查看tty命令的源代码。

把@ chrylis的指针和这个答案结合起来并做一些调整之后,我最终得到的结果是:

  1. 使用本地方法签名创建和编译Java类
  2. 使用javah生成C头文件
  3. 创建.cpp文件,用isatty实现函数
  4. 将C ++代码编译到共享库中
  5. 运行Java程序,使用-Djava.library.path=...来告诉它你的自定义库在哪里

Java类:

 package com.example.cli; class LinuxTerminalSupport { public native boolean isStderrVisible(); static { System.loadLibrary("term"); } } 

蚂蚁目标生成.h

 <target name="generate-native-headers"> <javah destdir="native/" verbose="yes"> <classpath refid="compile.class.path"/> <class name="com.example.cli.LinuxTerminalSupport" /> </javah> </target> 

.cpp文件:

 #include "com_example_cli_LinuxTerminalSupport.h" #include "unistd.h" using namespace std; JNIEXPORT jboolean JNICALL Java_com_example_cli_LinuxTerminalSupport_isStderrVisible(JNIEnv * env, jobject obj) { return isatty(fileno(stderr)) == 1; } 

Makefile (更改java包含以反映您的$JAVA_HOME ):

 linux: LinuxTerminalSupport.o g++ -I/usr/java/jdk1.6.0_13/include -I/usr/java/jdk1.6.0_13/include/linux \ -o libterm.so -shared -Wl,-soname,term.so LinuxTerminalSupport.o -lc LinuxTerminalSupport.o: LinuxTerminalSupport.cpp g++ -c -I/usr/java/jdk1.6.0_13/include -I/usr/java/jdk1.6.0_13/include/linux LinuxTerminalSupport.cpp