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


55

Ocasionalmente eu preciso especificar um "caminho-equivalente" de um dos IO padrão córregos ( stdin, stdout, stderr). Desde 99% do tempo em que trabalho com Linux, prefiro /dev/obter /dev/stdin, etc., e isso " parece fazer a coisa certa". Mas, por um lado, sempre me senti desconfortável com essa justificativa (porque, é claro, "parece funcionar" até que não funcione). Além disso, não tenho bom senso de quão portátil é essa manobra.

Então, eu tenho algumas perguntas:

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

  2. De maneira mais geral, essa equivalência é "adequadamente portátil "?

Não encontrei nenhuma referência POSIX.



Respostas:


36

Está disponível no Linux de volta à sua pré-história. É não POSIX, embora muitas conchas reais (incluindo a AT & T kshe bash) irá simular-lo se ele não está presente no sistema operacional; note que esta simulação só funciona no nível do shell (isto é, parâmetro de redirecionamento ou linha de comando, não como argumento explícito, por exemplo open()). Dito isto, ele deve estar disponível na maioria dos sistemas Unix comerciais, de uma maneira ou de outra (às vezes é escrito /dev/fd/Npara vários números inteiros N, mas a maioria dos sistemas com isso fornecerá links simbólicos como o Linux e o * BSD).


13
De fato, /dev/std{in,out,err}são especificamente listados como não parte do padrão POSIX.1-2008 .
Jw013

Parece que ashnão suporta /dev/stdoutem initrd ( git.razvi.ro/... )
CMCDragonkai

@CMCDragonkai: Esse não é um / dev / stdout que pode ser tratado pelo shell, e o que você esperava do initrd? Está faltando a maioria das especialidades para torná-lo o menor possível.
Joshua

22

os /dev/std{in,out,err}arquivos normalmente são apenas links simbólicos para /proc/self/fd/{0,1,2}(respectivamente). Como tal, nada se ganha com o uso de métodos definidos pelo 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 padrão POSIX . Além disso, os números dos descritores de arquivo STDIN, STDOUT, STDERR também fazem parte do POSIX .
Em suma, coisas como >&2são garantidas para o trabalho.

Uma coisa importante a ser observada, porém, é que o uso de STDIN, STDOUT e STDERR é subjetivo ao modo como o programa foi iniciado. Se o programa foi iniciado com o descritor de arquivo 1 como um identificador aberto para um arquivo, seu programa apenas precisa aceitá-lo. Mesmo se você abrisse o programa /dev/stdout, tudo o que faria seria abrir o descritor de arquivo 1, que ainda apontará para esse arquivo.
Se é isso que você está tentando contornar, é necessário abrir o TTY diretamente. Normalmente, sem nenhum redirecionamento, STDIN, STDOUT e STDERR são apenas descritores de arquivos abertos, apontando para o mesmo TTY. Não há absolutamente nada além disso.


2
+1, especialmente para a parte "uma coisa importante"; Eu estou indo para digerir isso em partes :)
Alois Mahdal

4
Você pode esclarecer se /proc/self/fd/1ou /dev/fd/1faz parte do POSIX?
Steven Penny

/dev/std???são apenas links simbólicos /proc/self/fdno Linux.
Stéphane Chazelas 26/01

5

O POSIX 7 diz que são extensões.

Definições básicas , Seção 2.1.1 Requisitos:

O sistema pode fornecer extensões não padrão. Esses são recursos não exigidos pelo POSIX.1-2008 e podem incluir, mas não estão limitados a:

[...]

  • Arquivos adicionais de caracteres especiais com propriedades especiais (por exemplo,  /dev/stdin,  /dev/stdoute  /dev/stderr)

Encontrado ao grepping o HTML do POSIX: Onde está a lista das funções da API do POSIX C?

Estranhamente, a uuencodeferramenta fornece /dev/stdoutum efeito mágico :

A especificação de um operando decode_pathname/dev/stdout deve indicar que o uudecode deve usar a saída padrão.

A documentação do kernel Linux diz que todos os sistemas devem ter.

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

No entanto, não consegui encontrar onde esses links simbólicos são criados no kernel (distribuição fornecida?).


1

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

Mas falha no 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

6
Qual foi o seu caso de teste? bashé especial, pois ele pode ser compilado para identificador /dev/fd/xpor si só para redirecionamentos em sistemas que não possuem/dev/fd
Stéphane Chazelas

@ StéphaneChazelas Eu diminuí a votação apenas porque posso ver isso sendo enganoso sem esse esclarecimento (sem ofensa a Ole).
Evan Carroll

0

Um problema com os /dev/stdoutamigos é que você pode não ter permissão para escrever neles em determinadas circunstâncias. Por exemplo, encontrei isso ao invocar scripts do Nix e imagino ferramentas semelhantes que executam scripts em cadeias / caixas de areia / contêineres / VMs / etc. pode encontrar problemas semelhantes.

Usando a sintaxe como 1>&2trabalhava nesses casos e, como eu sabia que estaria rodando no Bash, eu poderia usar a substituição de processo por comandos que esperam nomes de arquivos.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.