3

我正在做标准重定向:

$ cat file.txt | /usr/bin/program

但是如果我直接在终端中运行它并复制粘贴输入,程序的行为会有所不同。当输入是终端时,它会显示一个进度条。无论如何,我想要进度条。

简而言之,我怎样才能“欺骗”输入来自终端而不是从文件重定向的程序?

4

3 回答 3

5

使用该expect程序可能是最简单的;它为您完成了大部分必要的工作。

必要的工作很繁琐。它涉及使用伪 tty,这些设备看起来像终端一样的程序。如果您要自己动手,那么您需要了解的 POSIX 系统调用是:

界面相对较新(第posix_openpt()6 版,与第 4 版相比,第 2 版列出的其他功能)。如果您的系统没有posix_openpt(),您需要为自己找一本 Unix 书籍(可能是 Stevens 或 Rochkind),以了解如何打开 pty 的 master 端,或者仔细阅读您的系统手册。但是,上面链接中的基本原理posix_openpt()也可能有所帮助——它也有使用其他功能的指南。Linux 有posix_openpt();Mac OS X 也是如此,通常通过推断 BSD 系统。

图书:

于 2013-02-25T03:30:47.787 回答
3

您需要使用伪 tty 来获得您想要的效果。'man pty' 会告诉你更多关于它的信息。

于 2013-02-25T01:54:47.983 回答
3

我假设程序将调用 glibc 函数isatty()来检查 stdin/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;
}

生成文件

# Make the shared Library
lib: libisatty.c
    gcc -shared -Wl,-soname,libisatty.so.1 -o libisatty.so.1.0  libisatty.c 
    ln -s libisatty.so.1.0 libisatty.so.1
    ln -s libisatty.so.1 libisatty.so

跑:

make lib

它应该构建得很好,我已经在 Ubuntu12.04 AMD 64 上对其进行了测试。

现在是测试库的时候了。:) 我已经使用该命令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

您应该看到彩色输出。

于 2013-02-25T01:58:01.937 回答