Насколько переносимы / dev / stdin, / dev / stdout и / dev / stderr?

55

Иногда мне нужно указать «путь-эквивалент» один из стандартных IO потоков ( stdin, stdout, stderr). Так как 99% времени я работаю с Linux, я просто собираюсь /dev/получить /dev/stdinи т. Д., И это « похоже, делает правильно». Но, с одной стороны, мне всегда было неловко по поводу такого обоснования (потому что, конечно, «это работает», пока оно не работает). Кроме того, у меня нет здравого смысла в том, насколько портативен этот маневр.

Итак, у меня есть несколько вопросов:

  1. В контексте Linux, это безопасно (да / нет) , чтобы уравнять stdin, stdoutи stderrс /dev/stdin, /dev/stdoutи /dev/stderr?

  2. В более общем смысле, является ли эта эквивалентность «адекватно переносимой »?

Я не мог найти ссылки на POSIX.

KJo
источник

Ответы:

36

Он был доступен в Linux еще в предыстории. Это не POSIX, хотя многие фактические оболочки (включая AT & T kshи bash) будут имитировать его, если его нет в ОС; обратите внимание, что это моделирование работает только на уровне оболочки (т.е. параметр перенаправления или командной строки, а не явный аргумент, например, например open()). Тем не менее, он должен быть доступен в большинстве коммерческих систем Unix, так или иначе (иногда это пишется /dev/fd/Nдля различных целых чисел N, но большинство систем с этим будут предоставлять символические ссылки, как Linux и * BSD).

geekosaur
источник
13
Действительно, /dev/std{in,out,err}они конкретно указаны как не являющиеся частью стандарта POSIX.1-2008 .
jw013
Похоже, что ashне поддерживает /dev/stdoutв initrd ( git.razvi.ro/… )
CMCDragonkai
@CMCDragonkai: Это не / dev / stdout, который может обрабатываться оболочкой, и что вы ожидали от initrd? Он пропускает большинство тонкостей, чтобы сделать его настолько малым, насколько это практически возможно.
Джошуа
22

эти /dev/std{in,out,err}файлы , как правило , только символические ссылки на /proc/self/fd/{0,1,2}(соответственно). Таким образом, ничто не выигрывает при использовании методов, определенных POSIX.

Если вы хотите быть POSIX-совместимым, лучший способ сделать это - использовать перенаправление вывода. Перенаправление вывода оболочки определено в стандарте POSIX . Кроме того, номера дескрипторов файлов STDIN, STDOUT, STDERR также являются частью POSIX .
Короче говоря, такие вещи >&2гарантированно работают.

Однако важно отметить, что использование STDIN, STDOUT и STDERR зависит от того, как была запущена программа. Если программа была запущена с файловым дескриптором 1, который является открытым дескриптором файла, то ваша программа просто должна его принять. Даже если бы вы открыли программу /dev/stdout, все, что нужно сделать, это открыть дескриптор файла 1, который все еще будет указывать на этот файл.
Если это то, что вы пытаетесь обойти, вам нужно открыть TTY напрямую. Обычно без какого-либо перенаправления STDIN, STDOUT и STDERR - это просто открытые файловые дескрипторы, указывающие на один и тот же TTY. В этом нет ничего более, чем это.

Патрик
источник
2
+1, особенно для части «одна важная вещь»; Я собираюсь переварить это по частям :)
Алоис Махдал
4
Вы можете уточнить , если /proc/self/fd/1или /dev/fd/1являются частью POSIX?
Стивен Пенни
/dev/std???только символические ссылки /proc/self/fdна Linux.
Стефан
5

POSIX 7 говорит, что они являются расширениями.

Базовые определения , раздел 2.1.1 Требования:

Система может предоставлять нестандартные расширения. Эти функции не требуются POSIX.1-2008 и могут включать, но не ограничиваются:

[...]

  • Дополнительные характер специальные файлы со специальными свойствами (например,  /dev/stdin,  /dev/stdout, и  /dev/stderr)

Найден путем поиска в POSIX HTML: где находится список функций API POSIX C?

Также довольно странно, uuencodeинструмент дает /dev/stdoutволшебный эффект :

Указание операнда decode_pathname/dev/stdout должно указывать, что uudecode должен использовать стандартный вывод.

В документации ядра Linux сказано, что все системы должны иметь ее.

https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/devices.rst

Compulsory links
These links should exist on all systems:
/dev/fd       /proc/self/fd   symbolic   File descriptors
/dev/stdin    fd/0            symbolic   stdin file descriptor
/dev/stdout   fd/1            symbolic   stdout file descriptor
/dev/stderr   fd/2            symbolic   stderr file descriptor

Однако я не смог найти, где эти символические ссылки созданы в ядре (дистрибутив предоставлен?).

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
источник
1

/ dev / {stdout, stdin, stderr} работают в Bash на этих платформах:

Linux debian-ppc 3.16.0-4-powerpc #1 Debian 3.16.7-ckt25-1 (2016-03-06) ppc GNU/Linux
HP-UX hpux-ia6 B.11.31 U ia64 0107668277 unlimited-user license
AIX aix7 1 7 000ACFDE4C00
FreeBSD freebsd.polarhome.com 10.0-RELEASE-p7 FreeBSD 10.0-RELEASE-p7 #0: Tue Jul  8 06:37:44 UTC 2014     root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC  amd64
HP-UX hpux64 B.11.11 U 9000/785 2000587908 unlimited-user license
Darwin macosx 11.4.2 Darwin Kernel Version 11.4.2: Thu Aug 23 16:26:45 PDT 2012; root:xnu-1699.32.7~1/RELEASE_I386 i386
GNU hurd 0.7 GNU-Mach 1.6-486/Hurd-0.7 i686-AT386 GNU
Linux mandriva.polarhome.com 2.6.33.7-desktop-2mnb #1 SMP Mon Sep 20 18:19:20 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux
SunOS openindiana 5.11 oi_148 i86pc i386 i86pc
MirBSD miros.polarhome.com 10 Kv#10uAF-20110818 GENERIC#1330 i386
Linux pidora 3.12.23-2.20140626git25673c3.rpfr20.armv6hl.bcm2708 #1 PREEMPT Fri Jul 4 16:06:10 EDT 2014 armv6l armv6l armv6l GNU/Linux
QNX qnx 6.5.0 2010/07/09-14:44:03EDT x86pc x86
NetBSD netbsd.polarhome.com 6.1.3 NetBSD 6.1.3 (GENERIC) i386
OpenBSD openbsd.polarhome.com 4.9 GENERIC#671 i386
Linux raspbian 3.18.7+ #755 PREEMPT Thu Feb 12 17:14:31 GMT 2015 armv6l GNU/Linux
SCO_SV scosysv 5 6.0.0 i386
Linux redhat.polarhome.com 3.17.4-301.fc21.x86_64 #1 SMP Thu Nov 27 19:09:10 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
SunOS solaris-x86 5.11 11.3 i86pc i386 i86pc
Linux suse 3.4.63-2.44-desktop #1 SMP PREEMPT Wed Oct 2 11:18:32 UTC 2013 (d91a619) x86_64 x86_64 x86_64 GNU/Linux
SunOS solaris 5.10 Generic_147147-26 sun4u sparc SUNW,Sun-Fire-V210
Linux ubuntu 3.13.0-85-generic #129-Ubuntu SMP Thu Mar 17 20:50:15 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
UnixWare unixware 5 7.1.4 i386 x86at SCO UNIX_SVR5
OSF1 tru64.polarhome.com V5.1 2650 alpha
Linux debian 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt20-1+deb8u2 (2016-01-02) x86_64 GNU/Linux

Но терпит неудачу в csh на этих:

HP-UX hpux-ia6 B.11.31 U ia64 0107668277 unlimited-user license
Linux centos.polarhome.com 2.6.18-409.el5 #1 SMP Tue Mar 15 18:13:50 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux
HP-UX hpux64 B.11.11 U 9000/785 2000587908 unlimited-user license
AIX aix7 1 7 000ACFDE4C00
SCO_SV scosysv 5 6.0.0 i386
SunOS solaris-x86 5.11 11.3 i86pc i386 i86pc
SunOS openindiana 5.11 oi_148 i86pc i386 i86pc
SunOS solaris 5.10 Generic_147147-26 sun4u sparc SUNW,Sun-Fire-V210
UnixWare unixware 5 7.1.4 i386 x86at SCO UNIX_SVR5
OSF1 tru64.polarhome.com V5.1 2650 alpha
Оле Танге
источник
6
Каким был ваш тест? bashявляется особенным, поскольку он может быть скомпилирован для обработки /dev/fd/xперенаправлений в системах, которые не имеют/dev/fd
Стефан Шазелас
@ StéphaneChazelas Я понизил голос только потому, что вижу, что это вводит в заблуждение без этого разъяснения (без обид Оле).
Эван Кэрролл
0

Одна проблема с /dev/stdoutдрузьями заключается в том, что у вас может не быть разрешения писать им при определенных обстоятельствах. Например, я сталкивался с этим при вызове скриптов из Nix , и я представляю себе подобные инструменты, которые запускают скрипты в jails / sandboxes / container / VMs / etc. могут возникнуть аналогичные проблемы.

Использование синтаксиса вроде 1>&2работало в этих случаях, и, поскольку я знал, что буду работать в Bash, я мог бы использовать подстановку процессов для команд, которые ожидают имена файлов.

Warbo
источник