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

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

De vez en cuando necesito especificar una "ruta equivalente" de uno de los flujos de IO estándar ( ,, stdin) . Dado que el 99% del tiempo trabajo con Linux, simplemente antepongo get , etc., y esto "stdoutstderr/dev//dev/stdinparecehacer lo correcto". Pero, para empezar, siempre me ha inquietado ese razonamiento (porque, por supuesto, "parece funcionar" hasta que deja de funcionar). Además, no tengo buen sentido para Qué portátil es esta maniobra.

Entonces tengo algunas preguntas:

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

  2. En términos más generales, ¿esta equivalencia está "adecuadamenteportátil"?

No pude encontrar ninguna referencia POSIX.

Respuesta1

Ha estado disponible en Linux desde su prehistoria. EsnoPOSIX, aunque muchos shells reales (incluidos AT&T kshy bash) lo simularán 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, por ejemplo open()). Dicho esto, debería estar disponible enmayoríasistemas comerciales Unix, de una forma u otra (a veces se escribe /dev/fd/Ncon varios números enteros N, pero la mayoría de los sistemas con eso proporcionarán enlaces simbólicos como lo hacen Linux y *BSD).

Respuesta2

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

Si desea ser compatible con POSIX, la mejor manera de hacerlo es utilizar la redirección de salida. La redirección de salida del Shell se define en elestándar POSIX. Además, los números de descriptor de archivos STDIN, STDOUT, STDERR también forman parte dePOSIX.
En resumen, >&2se garantiza que cosas como estas funcionarán.

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 identificador abierto de un archivo, entonces su programa simplemente tiene que aceptarlo. Incluso si tuviera el programa abierto /dev/stdout, todo lo que haría sería abrir el descriptor de archivo 1, que seguirá apuntando a ese archivo.
Si esto es lo que estás intentando evitar, debes abrir el TTY directamente. Normalmente, sin ninguna redirección, STDIN, STDOUT y STDERR son simplemente descriptores de archivos abiertos que apuntan al mismo TTY. No hay absolutamente nada más que eso.

Respuesta3

/dev/{stdout,stdin,stderr} funciona 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

Respuesta4

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

Usar una sintaxis como 1>&2funcionó en estos casos y, como sabía que estaría ejecutando Bash, podría usarsustitución de procesospara comandos que esperan nombres de archivos.

información relacionada