Quão portáteis são /dev/stdin, /dev/stdout e /dev/stderr?

Quão portáteis são /dev/stdin, /dev/stdout e /dev/stderr?

Ocasionalmente, preciso especificar um "caminho equivalente" de um dos fluxos IO padrão ( stdin, stdout, stderr). Como trabalho com Linux 99% do tempo, apenas acrescento /dev/get /dev/stdin, etc., e este "parecefazer a coisa certa". Mas, por um lado, sempre me senti desconfortável com esse raciocínio (porque, é claro, "parece funcionar" até que não funciona). Além disso, não tenho bom senso para quão portátil é essa manobra.

Então eu tenho algumas perguntas:

  1. No contexto do Linux, é seguro (sim/não) igualar stdin, stdout, e stderrcom /dev/stdin, /dev/stdoute /dev/stderr?

  2. De forma mais geral, esta equivalência é "adequadamenteportátil"?

Não consegui encontrar nenhuma referência POSIX.

Responder1

Ele está disponível no Linux desde sua pré-história. Isso énãoPOSIX, embora muitos shells reais (incluindo AT&T kshe bash) irão simulá-lo se não estiver presente no sistema operacional; observe que esta simulação funciona apenas no nível do shell (ou seja, redirecionamento ou parâmetro de linha de comando, não como argumento explícito para, por exemplo, open()). Dito isto, deve estar disponível emmaioriasistemas Unix comerciais, de uma forma ou de outra (às vezes é escrito /dev/fd/Npara vários inteiros N, mas a maioria dos sistemas com isso fornecerá links simbólicos como o Linux e o *BSD fazem).

Responder2

os /dev/std{in,out,err}arquivos normalmente são apenas links simbólicos para /proc/self/fd/{0,1,2}(respectivamente). Como tal, não há nada a ganhar com o uso de métodos definidos em POSIX.

Se você deseja ser compatível com POSIX, a melhor maneira de fazer isso é usar o redirecionamento de saída. O redirecionamento de saída do shell é definido no arquivoPadrão POSIX. Além disso, os números dos descritores de arquivo STDIN, STDOUT, STDERR também fazem parte doPOSIX.
Resumindo, coisas como >&2certamente funcionarão.

Uma coisa importante a notar é que o uso de STDIN, STDOUT e STDERR é subjetivo à forma como o programa foi iniciado. Se o programa foi iniciado com o descritor de arquivo 1 sendo um identificador aberto para um arquivo, então seu programa só precisa aceitá-lo. Mesmo se você tivesse o programa aberto /dev/stdout, tudo o que ele faria seria abrir o descritor de arquivo 1, que ainda apontará para esse arquivo.
Se é isso que você está tentando contornar, você precisa abrir o TTY diretamente. Normalmente, sem qualquer redirecionamento, STDIN, STDOUT e STDERR são apenas descritores de arquivos abertos apontando para o mesmo TTY. Não há absolutamente nada mais do que isso.

Responder3

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

Mas falha em csh nestes:

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

Responder4

Um problema com /dev/stdoutamigos é que você pode não ter permissão para escrever para eles em determinadas circunstâncias. Por exemplo, encontrei isso ao invocar scripts deNix, e imagino ferramentas semelhantes que executam scripts em jails/sandboxes/containers/VMs/etc. pode encontrar problemas semelhantes.

Usar sintaxe como 1>&2funcionou nesses casos e, como eu sabia que estaria rodando em Bash, poderia usarsubstituição de processopara comandos que esperam nomes de arquivos.

informação relacionada