Наскільки портативними є / dev / stdin, / dev / stdout та / dev / stderr?


55

Іноді мені потрібно вказати «шлях-еквівалент» одного зі стандартних потоків введення - виведення ( stdin, stdout, stderr). Оскільки в 99% часу я працюю з Linux, я просто готуюсь /dev/отримати /dev/stdinінше, і це " здається, робить все правильно". Але, з одного боку, мені завжди було неприємно щодо такого обгрунтування (адже, звичайно, "це, здається, працює", поки цього не відбудеться). Крім того, я не маю жодного сенсу щодо того, наскільки портативний цей маневр.

Тож у мене є кілька питань:

  1. В контексті Linux, це безпечно (так / ні) , щоб зрівняти stdin, stdoutі stderrз /dev/stdin, /dev/stdoutі /dev/stderr?

  2. Загалом, чи є ця еквівалентність "адекватно переносною "?

Я не зміг знайти жодних посилань на POSIX.



Відповіді:


36

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


13
Дійсно, /dev/std{in,out,err}вони спеціально перераховані як не є частиною стандарту POSIX.1-2008 .
jw013

Здається, що ashне підтримує /dev/stdoutinitrd ( 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 of /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

Однак я не міг знайти, де ці символьні посилання створені в ядрі (надається distro?).


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éphane Chazelas

@ StéphaneChazelas Я спростував лише тому, що можу бачити, що це вводить в оману без уточнення (не ображаючи Оле).
Еван Керролл

0

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.