¿Qué tan portátiles son / dev / stdin, / dev / stdout y / dev / stderr?

55

De vez en cuando necesito especificar un "camino equivalente" de una de las corrientes de IO estándar ( stdin, stdout, stderr). Como el 99% del tiempo trabajo con Linux, solo prefiero /dev/obtener /dev/stdin, etc., y esto " parece hacer lo correcto". Pero, por un lado, siempre me ha inquietado esa razón (porque, por supuesto, "parece funcionar" hasta que no funciona). Además, no tengo un buen sentido de lo portátil que es esta maniobra.

Entonces tengo algunas preguntas:

  1. En el contexto de Linux, ¿es seguro (sí / no) a equiparar stdin, stdouty stderrcon /dev/stdin, /dev/stdouty /dev/stderr?

  2. En términos más generales, ¿es esta equivalencia "adecuadamente portátil "?

No pude encontrar ninguna referencia POSIX.

kjo
fuente

Respuestas:

36

Ha estado disponible en Linux nuevamente en su prehistoria. Es no POSIX, aunque muchas conchas reales (incluyendo AT & T kshy bash) simulará que si no está presente en el sistema operativo; tenga en cuenta que esta simulación solo funciona a nivel de shell (es decir, redirección o parámetro de línea de comando, no como argumento explícito para, por ejemplo open()). Dicho esto, debería estar disponible en la mayoría de los sistemas comerciales de Unix, de una forma u otra (a veces se deletrea /dev/fd/Npara varios enteros N, pero la mayoría de los sistemas con eso proporcionarán enlaces simbólicos como Linux y * BSD).

geekosaur
fuente
13
De hecho, /dev/std{in,out,err}se enumeran específicamente como parte del estándar POSIX.1-2008 .
jw013
Parece que ashno es compatible /dev/stdoutcon initrd ( git.razvi.ro/… )
CMCDragonkai
@CMCDragonkai: Eso no es un / dev / stdout que puede ser manejado por el shell, ¿y qué esperabas de initrd? Le faltan la mayoría de las bondades para que sea lo más pequeño posible.
Joshua
22

los /dev/std{in,out,err}archivos normalmente son solo enlaces simbólicos a /proc/self/fd/{0,1,2}(respectivamente). Como tal, no se gana nada con el uso de métodos definidos por POSIX.

Si desea cumplir con POSIX, la mejor manera de hacerlo es utilizar la redirección de salida. La redirección de salida de Shell se define en el estándar POSIX . Además, los números de descriptor de archivo STDIN, STDOUT, STDERR también forman parte de POSIX .
En resumen, cosas como >&2están garantizadas para trabajar.

Sin embargo, una cosa importante a tener en cuenta es que el uso de STDIN, STDOUT y STDERR es subjetivo de cómo se inició el programa. Si el programa se inició con el descriptor de archivo 1 como un controlador abierto para un archivo, entonces su programa solo tiene que aceptarlo. Incluso si tuviera que abrir el programa /dev/stdout, todo lo que haría sería abrir el descriptor de archivo 1, que todavía apuntará a ese archivo.
Si esto es lo que está tratando de evitar, debe abrir el TTY directamente. Normalmente, sin ninguna redirección, STDIN, STDOUT y STDERR son descriptores de archivos abiertos que apuntan al mismo TTY. No hay absolutamente nada más que eso.

Patricio
fuente
2
+1, especialmente para la parte de "una cosa importante"; Voy a digerir esto en partes :)
Alois Mahdal
44
¿Pueden aclarar si son /proc/self/fd/1o /dev/fd/1son parte de POSIX?
Steven Penny
/dev/std???son solo enlaces simbólicos /proc/self/fden Linux.
Stéphane Chazelas
5

POSIX 7 dice que son extensiones.

Definiciones básicas , Sección 2.1.1 Requisitos:

El sistema puede proporcionar extensiones no estándar. Estas son características no requeridas por POSIX.1-2008 y pueden incluir, pero no están limitadas a:

[...]

  • Archivos especiales de caracteres adicionales con propiedades especiales (por ejemplo,  /dev/stdin,  /dev/stdout, y  /dev/stderr)

Encontrado por grep el HTML POSIX: ¿Dónde está la lista de las funciones API POSIX C?

También bastante extraño, la uuencodeherramienta da /dev/stdoutun efecto mágico :

La especificación de un operando decode_pathname de /dev/stdout indicará que uudecode debe utilizar la salida estándar.

La documentación del kernel de Linux dice que todos los sistemas deberían tenerlo.

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

Sin embargo, no pude encontrar dónde se crean esos enlaces simbólicos en el núcleo (¿se proporciona la distribución?).

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
fuente
1

/ dev / {stdout, stdin, stderr} funcionan en Bash en estas plataformas:

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

Pero falla en csh en estos:

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
Ole Tange
fuente
66
¿Cuál fue tu caso de prueba? bashes especial, ya que se puede compilar para manejarlo /dev/fd/xsolo para redireccionamientos en sistemas que no tienen/dev/fd
Stéphane Chazelas
@ StéphaneChazelas He votado en contra solo porque puedo ver que esto es engañoso sin esa aclaración (sin ofender a Ole).
Evan Carroll
0

Un problema con /dev/stdouty amigos es que es posible que no tenga permiso para escribirles en determinadas circunstancias. Por ejemplo, me he encontrado con esto al invocar scripts de Nix , e imagino herramientas similares que ejecutan scripts en cárceles / sandboxes / container / VMs / etc. puede encontrar problemas similares.

Usar la sintaxis como 1>&2funcionó en estos casos y, dado que sabía que estaría ejecutando en Bash, podría usar la sustitución de procesos para los comandos que esperan nombres de archivo.

Warbo
fuente