Меньше получает ввод с клавиатуры от stderr? - PullRequest
12 голосов
/ 18 сентября 2009

Я смотрю на код утилиты 'less', особенно на то, как он получает ввод с клавиатуры. Интересно, что в строке 80 файла ttyin.c он устанавливает дескриптор файла для чтения из:

     /*
      * Try /dev/tty.
      * If that doesn't work, use file descriptor 2,
      * which in Unix is usually attached to the screen,
      * but also usually lets you read from the keyboard.
      */
  #if OS2
      /* The __open() system call translates "/dev/tty" to "con". */
      tty = __open("/dev/tty", OPEN_READ);
  #else
      tty = open("/dev/tty", OPEN_READ);
  #endif
      if (tty < 0)
          tty = 2;

Разве файловый дескриптор 2 не является stderr? Если так, то WTH ?! Я думал, что ввод с клавиатуры был отправлен через стандартный ввод.

Интересно, что даже если вы сделаете ls -l * | less, после того как файл завершит загрузку, вы все равно сможете использовать клавиатуру для прокрутки вверх и вниз, но если вы сделаете ls -l * | vi, то vi будет кричать на вас, потому что это не так читать со стандартного ввода. Что за большая идея? Как я оказался в этой странной новой стране, где stderr - это способ сообщать об ошибках на экран и читать с клавиатуры? Я не думаю, что я больше в Канзасе ...

Ответы [ 4 ]

19 голосов
/ 18 сентября 2009
$ ls -l /dev/fd/
lrwx------ 1 me me 64 2009-09-17 16:52 0 -> /dev/pts/4
lrwx------ 1 me me 64 2009-09-17 16:52 1 -> /dev/pts/4
lrwx------ 1 me me 64 2009-09-17 16:52 2 -> /dev/pts/4

При входе в систему на интерактивном терминале все три стандартных файловых дескриптора указывают на одно и то же: ваш TTY (или псевдо-TTY).

$ ls -fl /dev/std{in,out,err}
lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stdin -> fd/0
lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stdout -> fd/1
lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stderr -> fd/2

По договоренности мы читаем из 0 и пишем в 1 и 2. Однако ничто не мешает нам поступать иначе.

Когда ваша оболочка запускает ls -l * | less, она создает канал из дескриптора файла ls 1 в дескриптор файла less 0. Очевидно, less больше не может читать ввод с клавиатуры пользователя из файлового дескриптора 0 & ndash; он пытается вернуть TTY, как может.

Если less не был отсоединен от терминала, open("/dev/tty") выдаст ему TTY.

Однако, если это не поможет ... что вы можете сделать? less делает последнюю попытку получения TTY, предполагая, что дескриптор файла 2 присоединен к тому же объекту, к которому был бы прикреплен дескриптор файла 0, если бы он не был перенаправлен.

Этот не является отказоустойчивым:

$ ls -l * | setsid less 2>/dev/null

Здесь less присваивается собственный сеанс (поэтому он больше не является частью активной группы процессов терминала, что приводит к сбою open("/dev/tty")), а его дескриптор файла 2 был изменен & ndash; теперь less завершается немедленно, потому что он выводит на TTY, но не получает никакого пользовательского ввода.

2 голосов
/ 18 сентября 2009

Ну ... во-первых, вы, кажется, пропустили вызов open(), который открывает '/ dev / tty'. Он использует файловый дескриптор 2 только в случае сбоя вызова open (). В стандартной системе Linux и, возможно, во многих Unix'ах, существует / dev / tty, который вряд ли вызовет сбой.

Во-вторых, комментарий вверху дает ограниченное количество объяснений того, почему они возвращаются к файловому дескриптору 2. Я предполагаю, что stdin, stdout и stderr в значительной степени связаны с '/ В любом случае, dev / tty / ', если не перенаправлен. А поскольку наиболее распространенные перенаправления для для stdin и / или stdout (по трубопроводу или < / >), но реже для stderr, вероятность того, что использование stderr, скорее всего, все еще будет подключена на «клавиатуру».

1 голос
/ 18 сентября 2009

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

0 голосов
/ 18 сентября 2009

Похоже, что это специфическая функция Linux, которая отправляет ввод с клавиатуры на FD 2.

...