3

Я заметил, что если я наберу:

ls --color=auto

или же

ls --color=auto | cat
ls --color=auto > >(cat)

Я не вижу того же результата. Поэтому я предполагаю, что у программы есть способность знать, передан ли ее STDOUT к чему-либо. Вопрос в том, как это узнать?

Я проверил переменные ENV с env и env | cat но я получаю то же самое. Ответ где-то еще. Я не могу понять где.

Из этого вопроса я обнаружил, что я могу использовать isatty() которые предоставляют эту функцию? это часть оболочки или ядра? Идя дальше, я вижу, что эта функция является частью стандарта POSIX.

Теперь я знаю, что у меня есть два процесса, которые могут взаимодействовать между ними с несколькими механизмами:

  • STDIN/STDOUT/STDERR
  • Код выхода
  • Переменные среды
  • Системные звонки

Bash и ls - обе программы. Таким образом, они могут использовать только перечисленные механизмы для обмена информацией.

Настоящий вопрос заключается в том, как isatty() получает информацию из bash?

1 ответ1

4

Опция --color является функцией программы GNU ls . GNU ls использует 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)));

Настоящий вопрос заключается в том, как isatty() получает информацию из bash?

isatty() проверяет файловый дескриптор, переданный ему, чтобы увидеть, представляет ли файловый дескриптор TTY (терминальное устройство). Точный способ работы isatty () может отличаться в разных системах. Вот реализация Дарвина из Apple OSX, если вам интересно:

#include <termios.h>
#include <unistd.h>

int
isatty(fd)
    int fd;
{
    struct termios t;

    return(tcgetattr(fd, &t) != -1);
}

Когда вы запускаете ls --color=auto , ваша оболочка (bash) запускает программу "ls", используя собственный стандартный ввод, вывод и ошибку оболочки как stdin/out/err для процесса "ls". Если вы работаете в интерактивном режиме, тогда stdout вашей оболочки, вероятно, является терминалом, тогда стандартный вывод ls, вероятно, будет терминалом. Когда ls вызывает isatty (), чтобы проверить, является ли его стандартный вывод терминалом, это, вероятно, будет успешным.

Когда вы запускаете что-то вроде ls --color=auto | cat , твоя оболочка делает три вещи:

  1. Создать трубу.
  2. Запустите cat со стандартным входом, установленным как pipe.
  3. Запустите ls со стандартным выводом, заданным как pipe.

Труба не является терминалом. Когда ls проверяет, является ли его стандартный вывод tty, проверка завершится неудачно.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .