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

时间:2021-07-17 00:19:00

When you use git it seems to magically know whether standard out is going through a pipe or into a file vs when it is being displayed to the console. For example, if you have colors enabled and you do

当你使用git时,似乎神奇地知道标准输出是通过管道还是文件与显示到控制台时。例如,如果您启用了颜色,那么就可以

git status

it will colorize the output for different categories of files being listed. However, if you do

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

git status | less

or

要么

git status > status.txt

it removes the linux color formatting and you only see plain, uncolored text.

它删除了linux颜色格式,你只能看到简单的未着色文本。

How does git detect whether the output of its commands are going to file vs going to the terminal?

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

4 个解决方案

#1


14  

isatty(int fd) will check whether the fd refers to a terminal or something else. It's part of unistd.h in the GNU C library.

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

Man page: http://linux.die.net/man/3/isatty

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

As an aside: if you want to read from a program using another program, but you want to fool isatty into thinking that your program is a human, there is a way to do that. You can use a pseudo-terminal (pty). This technique is used by expect, for example.

顺便说一句:如果你想使用另一个程序读取程序,但是你想愚蠢地认为你的程序是一个人类,那么就有办法做到这一点。您可以使用伪终端(pty)。例如,期望使用该技术。

#2


8  

This is a C Code to demonstrate how to detect if standard output is redirected:

这是一个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... */
}

That is how git knows whether the output is going to the terminal or to a file.

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

#3


3  

Can confirm that's what git relies on:

可以确认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).

Run against the git source tree.

针对git源代码树运行。

Note that fds 0=stdin, 1=stdout, 2=stderr by default, but these can of course be re-directed or closed (typically if you are a daemon you close your file descriptors and re-open the ones you want).

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

#4


2  

From a shell script, use the -t test flag applied to the file descriptor 0 (standard input).

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

Examples:

例子:

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

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

#1


14  

isatty(int fd) will check whether the fd refers to a terminal or something else. It's part of unistd.h in the GNU C library.

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

Man page: http://linux.die.net/man/3/isatty

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

As an aside: if you want to read from a program using another program, but you want to fool isatty into thinking that your program is a human, there is a way to do that. You can use a pseudo-terminal (pty). This technique is used by expect, for example.

顺便说一句:如果你想使用另一个程序读取程序,但是你想愚蠢地认为你的程序是一个人类,那么就有办法做到这一点。您可以使用伪终端(pty)。例如,期望使用该技术。

#2


8  

This is a C Code to demonstrate how to detect if standard output is redirected:

这是一个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... */
}

That is how git knows whether the output is going to the terminal or to a file.

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

#3


3  

Can confirm that's what git relies on:

可以确认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).

Run against the git source tree.

针对git源代码树运行。

Note that fds 0=stdin, 1=stdout, 2=stderr by default, but these can of course be re-directed or closed (typically if you are a daemon you close your file descriptors and re-open the ones you want).

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

#4


2  

From a shell script, use the -t test flag applied to the file descriptor 0 (standard input).

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

Examples:

例子:

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

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