在linux中,如何测试程序的输出是转到实时终端还是文件?

时间:2010-01-26 21:31:05

标签: linux terminal xterm gnome-terminal konsole

使用git时,似乎神奇地知道标准输出是通过管道还是文件,而不是显示在控制台上。例如,如果您启用了颜色,则执行

git status

它将为列出的不同类别的文件着色输出。但是,如果你这样做

git status | less

git status > status.txt

它删除了linux color formatting,你只能看到简单,无色的文字。

git如何检测其命令的输出是否要转发到终端?

4 个答案:

答案 0 :(得分:14)

isatty(int fd)将检查fd是指终端还是其他内容。它是GNU C库中unistd.h的一部分。

手册页:http://linux.die.net/man/3/isatty

顺便说一句:如果你想使用其他程序从程序中读取,但是你想让isatty认为你的程序是人类,那么就有办法做到这一点。您可以使用pseudo-terminal(pty)。例如,expect使用此技术。

答案 1 :(得分:8)

这是一个C代码,用于演示如何检测标准输出是否被重定向:

int main(int argc, char **argv){
    if (!isatty(fileno(stdout))){
      fprintf(stdout, "argv, argc, someone is redirecting me elsewhere...\n");
      return 1;
    }
    /* rest of C code here... */
}

这就是git知道输出是转到终端还是文件的方式。

答案 2 :(得分:3)

可以确认git依赖的是什么:

$ grep -ir "isatty" ./*
./builtin-commit.c:     if (isatty(0))
./builtin-config.c:         stdout_is_tty = isatty(1);
./builtin-pack-objects.c:   progress = isatty(2);
./builtin-prune-packed.c:   int opts = isatty(2) ? VERBOSE : 0;
./builtin-revert.c: if (isatty(0))
./builtin-shortlog.c:   if (!nongit && !rev.pending.nr && isatty(0))
./builtin-unpack-objects.c: quiet = !isatty(2);
./color.c:      stdout_is_tty = isatty(1);
./compat/winansi.c: if (!isatty(fileno(stream)))
./compat/winansi.c: if (!isatty(fileno(stream)))
./pack-redundant.c: if (!isatty(0)) {
./pager.c:  if (!isatty(1))
./pager.c:  if (isatty(2))
./remote-curl.c:    options.progress = !!isatty(2);
./transport.c:  args.no_progress = args.quiet || (!transport->progress && !isatty(1));
./transport-helper.c:   int no_progress = v < 0 || (!t->progress && !isatty(1));
./wt-status.c:   * will have checked isatty on stdout).

针对git源代码树运行。

注意fds 0 = stdin,1 = stdout,默认情况下2 = stderr,但这些当然可以被重定向或关闭(通常如果你是守护进程,你关闭文件描述符并重新打开你的文件描述符)要)。

答案 3 :(得分:2)

从shell脚本中,使用应用于文件描述符0(标准输入)的-t测试标志。

示例:

# Any Bourne-style shell
[ -t 0 ] && echo This is a terminal

# Modern interactive shells: ksh, bash, zsh
[[ -t 0 ]] && echo This is a terminal