确定STDERR是否要去终端

时间:2013-08-20 15:02:03

标签: java linux command-line-interface stderr io-redirection

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

我想在STDERR到达终端时显示进度条,并在重定向STDERR时自动禁用自身,以便重定向数据中没有各种进度条。< / p>

检查System.console() == null是我的第一个想法,但是重定向STDOUT就足以使true,即使STDERR仍在进入终端。有什么我可以检查特定于STDERR的东西吗?特定于Linux或使用本机API的解决方案可以满足我的需求。

2 个答案:

答案 0 :(得分:1)

我认为你所寻找的是isatty(3)unistd.h。没有办法判断文件句柄是否已被重定向,句点,但是它会告诉你它是否仍然是交互式的。请参阅GNU coreutils中的tty命令的源代码。

答案 1 :(得分:0)

@chrylis's pointerthis answer合并并进行一些调整后,我最终得到的是:

  1. 使用本机方法签名创建和编译Java类
  2. 使用javah生成C头文件
  3. 创建.cpp文件,使用isatty
  4. 实现功能
  5. 将C ++代码编译为共享库
  6. 运行Java程序,使用-Djava.library.path=...告诉它自定义库的位置
  7. 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