首页 文章

欺骗应用程序认为它的标准输出是一个终端,而不是管道

提问于
浏览
124

我正试图做相反的事情

Detect if stdin is a terminal or pipe?

我正在运行一个正在更改其输出格式的应用程序,因为它检测到stdout上的管道,我希望它认为它是一个交互式终端,以便在重定向时获得相同的输出 .

我认为将它包装在 expect 脚本中或在PHP中使用 proc_open() 会这样做,但事实并非如此 .

有什么想法吗?

8 回答

  • 52

    Expect should 附带的unbuffer脚本可以处理这个问题 . 如果不是,则应用程序可能正在查看除其输出所连接的内容之外的其他内容,例如 . TERM环境变量设置为什么 .

  • 18

    参考之前的答案,在Mac OS X上,“脚本”可以像下面这样使用......

    script -q /dev/null commands...
    

    但是,因为它可能会将返回码从“\ n”更改为“\ r \ n”,所以我需要像这样运行 .

    script -q /dev/null commands... | perl -pe 's/\r\n/\n/g'
    

    如果这些命令之间存在某些管道,则需要刷新stdout . 例如:

    script -q /dev/null commands... | ruby -ne 'print "....\n";STDOUT.flush' |  perl -pe 's/\r\n/\n/g'
    
  • 14

    我不能用PHP实现't know if it',但是如果你真的需要子进程来查看TTY,你可以创建一个PTY .

    在C:

    #include <stdio.h>
    #include <stdlib.h>
    #include <sysexits.h>
    #include <unistd.h>
    #include <pty.h>
    
    int main(int argc, char **argv) {
        int master;
        struct winsize win = {
            .ws_col = 80, .ws_row = 24,
            .ws_xpixel = 480, .ws_ypixel = 192,
        };
        pid_t child;
    
        if (argc < 2) {
            printf("Usage: %s cmd [args...]\n", argv[0]);
            exit(EX_USAGE);
        }
    
        child = forkpty(&master, NULL, NULL, &win);
        if (child == -1) {
            perror("forkpty failed");
            exit(EX_OSERR);
        }
        if (child == 0) {
            execvp(argv[1], argv + 1);
            perror("exec failed");
            exit(EX_OSERR);
        }
    
        /* now the child is attached to a real pseudo-TTY instead of a pipe,
         * while the parent can use "master" much like a normal pipe */
    }
    

    实际上我的印象是expect本身确实创造了一个PTY .

  • 0

    基于Chris' solution,我提出了以下小助手函数:

    faketty() {
        script -qfc "$(printf "%q " "$@")" /dev/null
    }
    

    古怪的外观 printf 是正确扩展 $@ 中脚本参数的必要条件,同时保护命令的可能引用部分(参见下面的示例) .

    Usage:

    faketty <command> <args>
    

    Example:

    $ python -c "import sys; print sys.stdout.isatty()"
    True
    $ python -c "import sys; print sys.stdout.isatty()" | cat
    False
    $ faketty python -c "import sys; print sys.stdout.isatty()" | cat
    True
    
  • 14

    随处可见Python,

    echo fakepassword | python -c 'import pty, sys; pty.spawn(sys.argv[1:])' ssh
    
  • 154

    啊哈!

    script 命令做我们想要的......

    script --return -c "[executable string]" /dev/null
    

    诀窍!

  • 14

    对于具体答案的评论太新了,但我想我会跟进ingomueller-net发布的 faketty 函数,因为它最近帮助了我 .

    我发现这是创建一个我不想要/不需要的 typescript 文件所以我添加了/ dev / null作为脚本目标文件:

    function faketty { script -qfc "$(printf "%q " "$@")" /dev/null ; }

  • 7

    还有一个pty程序包含在“UNIX环境中的高级编程,第二版”一书的示例代码中!

    以下是在Mac OS X上编译pty的方法:

    http://codesnippets.joyent.com/posts/show/8786

相关问题