$ 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, но не получает никакого пользовательского ввода.