8

我想通过管道运行程序的输出,但是当它检测到stdout不是交互式外壳时,它的行为显然不同。

我怎样才能像在正常情况下一样欺骗它通过管道写入?

4

3 回答 3

18

我假设程序将调用 glibc 函数isatty()来检查 stdout 是否是终端。这对于在终端上使用彩色输出或 ANSI 终端的其他功能(如光标定位或行擦除/重绘)的程序很常见。

您可以使用 LD_PRELOAD 环境变量来欺骗程序。LD_PRELOAD 由 ELF 链接器处理,并告诉动态库应该在所有其他库之前加载。使用此功能可以覆盖库函数,在您的情况下是 glibc 函数isatty()。例如,您可以关注这篇文章

我为你准备了一个例子:

首先创建文件libisatty.c

/**
 * Overrides the glibc function. Will always return true.
 *
 * Note: Although this should be ok for most applications it can
 * lead to unwanted side effects. It depends on the question
 * why the programm calls isatty()
 */
int isatty(int param) {
    return 1;
}

并将其编译为共享库:

gcc -shared -o libisatty.so  libisatty.c

它应该构建良好。

现在是测试库的时候了。:) 我已经使用该命令ls --color=auto进行测试。ls调用isatty()来决定它是否应该着色它的输出。如果输出被重定向到文件或管道,它将不会被着色。您可以使用以下命令轻松测试:

ls --color=auto        # should give you colorized output
ls --color=auto | cat  # will give you monochrome output

现在我们将使用 LD_PRELOAD 环境变量再次尝试第二个命令:

LD_PRELOAD=./libisatty.so ls --color=auto | cat

您应该看到彩色输出。

顺便说一句很酷的用户名:uʍopǝpısdn !!:D

于 2013-02-04T20:24:59.937 回答
2

使用script对我有用:

script outputfile.txt yourcommand
# any output ends up in outputfile.txt

我猜你可以用它来管道:

script out.txt yourcommand ; cat out.txt | nextcommand
于 2015-04-02T15:38:21.823 回答
0

你可能想试试这个:

./script.sh < `tty` > output

如果程序正在做类似的事情isatty(0),这可能就足够了。

于 2013-02-04T15:39:16.960 回答