Обманите приложение, думая, что его стандартный вывод - это терминал, а не труба - PullRequest
129 голосов
/ 09 сентября 2009

Я пытаюсь сделать противоположность

Определить, является ли stdin терминалом или каналом?

Я запускаю приложение, которое меняет свой формат вывода, потому что оно обнаруживает канал в stdout, и я хочу, чтобы оно считало, что это интерактивный терминал, поэтому я получаю тот же вывод при перенаправлении.

Я думал, что обернуть его в скрипт expect или использовать proc_open() в PHP это сделает, но это не так.

Есть идеи?

Ответы [ 7 ]

162 голосов
/ 10 сентября 2009

Ага!

Команда script делает то, что мы хотим ...

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

Трюк!

55 голосов
/ 05 декабря 2013

Основываясь на решении Криса , я предложил следующую маленькую вспомогательную функцию:

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

Причудливый вид printf необходим для правильного расширения аргументов скрипта в $@ при защите возможных частей команды в кавычках (см. Пример ниже).

Usage:

faketty <command> <args>

Пример:

$ 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
20 голосов
/ 11 сентября 2009

Сценарий unbuffer , который поставляется с Ожидается, что должен обработать это нормально. Если нет, приложение может смотреть на что-то, кроме того, к чему его выход подключен, например. значение переменной окружения TERM.

16 голосов
/ 09 сентября 2009

Я не знаю, выполнимо ли это из PHP, но если вам действительно нужен дочерний процесс для просмотра TTY, вы можете создать PTY .

В С:

#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, хотя.

14 голосов
/ 27 ноября 2012

Ссылаясь на предыдущий ответ, в Mac OS X можно использовать «скрипт», как показано ниже ...

script -q /dev/null commands...

Но, поскольку он может изменить код возврата с "\ n" на "\ r \ n", мне нужно было работать следующим образом.

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

Если между этими командами есть какой-то канал, вам нужно сбросить стандартный вывод. например:

script -q /dev/null commands... | ruby -ne 'print "....\n";STDOUT.flush' |  perl -pe 's/\r\n/\n/g'
7 голосов
/ 29 января 2017

Слишком новы, чтобы комментировать конкретный ответ, но я подумал, что буду следить за функцией faketty, опубликованной ingomueller-net выше, так как она недавно помогла мне.

Я обнаружил, что это создает файл typescript, который мне не нужен / не нужен, поэтому я добавил / dev / null в качестве целевого файла сценария:

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

0 голосов
/ 05 августа 2010

В пример кода книги "Расширенное программирование в среде UNIX, второе издание" включена также pty-программа!

Вот как компилировать pty в Mac OS X:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...