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

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

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

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

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

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

Мне не удалось найти никаких ссылок на POSIX.

решение1

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

решение2

файлы /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. Больше в этом ничего нет.

решение3

/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     [email protected]:/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

решение4

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

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

Связанный контент