Это на Ubuntu 16.04 с bash 4.3.42 и tcsh 6.19
Если открыть виртуальную консоль, не используемую X, и запустить bash, я увижу stdin, stdout, stderr и выделенный файловый дескриптор для tty (судя по всему).
$ cd /dev/fd
$ ls
0 1 2 255
$ ls -al .
... .
... ..
... 0 -> /dev/tty3
... 1 -> /dev/tty3
... 2 -> /dev/tty3
... 255 -> /dev/tty3
Если я использую tcsh, то вижу пять файловых дескрипторов, отличных от std{in, out, err}, указывающих на tty, а std{in, out, err} все сопоставлены с /dev/null
.
% cd /dev/fd
% ls -al
... .
... ..
... 0 -> /dev/null
... 1 -> /dev/null
... 15 -> /dev/tty3
... 16 -> /dev/tty3
... 17 -> /dev/tty3
... 18 -> /dev/tty3
... 19 -> /dev/tty3
... 2 -> /dev/null
Зачем tcsh
нужно так много файловых дескрипторов, указывающих на tty, и в чем преимущество сопоставления 0, 1 и 2 с /dev/null
? Не означает ли это, что требуется немного больше учета, когда tcsh
разветвляются процессы, чтобы они писали в / читали с консоли?
решение1
tcsh
организовано по-другому bash
(неудивительно). Оба старые и полны интересных странностей для внимательного читателя.
Это различие обусловлено способом tcsh
управления файловыми дескрипторами. В отличие от bash
, он не предоставляет сценаристу способ манипулировать пронумерованными файловыми дескрипторами. Разработчики посчитали удобным организовать свои файловые дескрипторы подвижущийсястандартные потоки в «сохраненную» область (не используемую реальными скриптами), и при запуске команд, этодубликатыте, которые относятся к командам (т.е. подпроцессу), изакрываетсяих после завершения команд.
В исходном коде,sh.h
имеет этот кусокчто объясняет использование этих файловых дескрипторов:
/*
* The shell moves std in/out/diag and the old std input away from units
* 0, 1, and 2 so that it is easy to set up these standards for invoked
* commands.
*/
#define FSAFE 5 /* We keep the first 5 descriptors untouched */
#define FSHTTY 15 /* /dev/tty when manip pgrps */
#define FSHIN 16 /* Preferred desc for shell input */
#define FSHOUT 17 /* ... shell output */
#define FSHDIAG 18 /* ... shell diagnostics */
#define FOLDSTD 19 /* ... old std input */
Для обеих оболочек существует несколько ссылок на одно и то же «реальное» устройство /dev/fd
(по крайней мере, для Linux), поскольку именно так организован драйвер псевдотерминала.
Кстати, вы получите другой результат, если запустите tcsh
из другой оболочки. Но если ваша оболочка по умолчанию — tcsh
, скорее всего, вы увидите те дескрипторы файлов, которые описаны в вопросе.
решение2
Это почти наверняка связано с вашей tcsh
конфигурацией (например ~/.login
, ~/.cshrc
/etc/csh.*
) — найдите все, что перенаправляет stdin, stdout, stderr.
При запуске tcsh
на моей системе я получаю:
$ tcsh
> ls -lF /dev/fd/
total 0
lrwx------ 1 cas cas 64 Jun 26 13:28 0 -> /dev/pts/29
lrwx------ 1 cas cas 64 Jun 26 13:28 1 -> /dev/pts/29
lrwx------ 1 cas cas 64 Jun 26 13:28 2 -> /dev/pts/29
lr-x------ 1 cas cas 64 Jun 26 13:28 3 -> /proc/16570/fd/