我注意到如果我输入:
ls --color=auto
Run Code Online (Sandbox Code Playgroud)
或者
ls --color=auto | cat
ls --color=auto > >(cat)
Run Code Online (Sandbox Code Playgroud)
我没有看到相同的输出。因此我假设一个程序有能力知道它的 STDOUT 是否通过管道传输到某个东西。问题是它是怎么知道的?
我查了ENV VAR提供env和env | cat,但我得到的是相同的。答案在别处。我想不通在哪里。
从这个问题我发现我可以使用isatty()谁提供这个功能?它是外壳还是内核的一部分?通过进一步我看到这个函数是 POSIX 标准的一部分。
现在我知道我有两个进程可以通过几种机制在它们之间进行通信:
Bash 和 ls 都是程序。因此他们只能使用列出的机制来交换信息。
这背后的真正问题是如何isatty()从 bash 获取信息?
该--color选项是 GNUls程序的一个特性。GNUls使用该isatty()函数来测试进程的标准输出是否为 TTY。部分相关源代码可以在这里看到:
case COLOR_OPTION:
{
int i;
if (optarg)
i = XARGMATCH ("--color", optarg, color_args, color_types);
else
/* Using --color with no argument is equivalent to using
--color=always. */
i = color_always;
print_with_color = (i == color_always
|| (i == color_if_tty
&& isatty (STDOUT_FILENO)));
Run Code Online (Sandbox Code Playgroud)
这背后的真正问题是 isatty() 如何从 bash 获取信息?
isatty()检查传递给它的文件描述符以查看文件描述符是否代表 TTY(终端设备)。isatty() 的确切工作方式可能因系统而异。如果您有兴趣,这里有一个来自 Apple OSX的Darwin 实现:
#include <termios.h>
#include <unistd.h>
int
isatty(fd)
int fd;
{
struct termios t;
return(tcgetattr(fd, &t) != -1);
}
Run Code Online (Sandbox Code Playgroud)
当您运行 时ls --color=auto,您的外壳程序 (bash) 使用外壳程序自己的标准输入、输出和错误作为“ls”进程的 stdin/out/err 启动“ls”程序。如果您以交互方式运行,那么您的 shell 的标准输出可能是一个终端,那么 ls 的标准输出可能是一个终端。当 ls 调用 isatty() 来测试它的标准输出是否是终端时,它可能会成功。
当你运行类似的东西时ls --color=auto | cat,你的 shell 会做三件事:
cat时将其标准输入设置为管道。ls时将其标准输出设置为管道。管道不是终端。当ls测试其标准输出是否为 tty 时,测试将失败。
| 归档时间: |
|
| 查看次数: |
1939 次 |
| 最近记录: |