Jak przenośne są / dev / stdin, / dev / stdout i / dev / stderr?

55

Od czasu do czasu muszę podać ścieżkę „równoważne” w jednym ze standardowych strumieni IO ( stdin, stdout, stderr). Ponieważ 99% czasu pracuję z Linuksem, po prostu przygotowuję się /dev/do zdobycia /dev/stdinitp., A to „ wydaje się właściwe”. Ale z jednej strony zawsze byłem zaniepokojony takim uzasadnieniem (ponieważ oczywiście „wydaje się, że działa”, dopóki nie zadziała). Co więcej, nie mam rozsądku, jak przenośny jest ten manewr.

Mam więc kilka pytań:

  1. W kontekście systemu Linux, jest to bezpieczne (tak / nie), aby zrównać stdin, stdouti stderrz /dev/stdin, /dev/stdouti /dev/stderr?

  2. Mówiąc bardziej ogólnie, czy ta równoważność jest „odpowiednio przenośna ”?

Nie mogłem znaleźć żadnych odniesień do POSIX.

kjo
źródło

Odpowiedzi:

36

Jest dostępny w Linuksie z powrotem do swojej prehistorii. To nie jest POSIX, chociaż wiele rzeczywistych powłok (w tym AT&T kshi bash) będzie go symulować, jeśli nie jest obecne w systemie operacyjnym; zauważ, że ta symulacja działa tylko na poziomie powłoki (tj. przekierowanie lub parametr wiersza poleceń, a nie jako wyraźny argument np open().). To powiedziawszy, powinno być dostępne w większości komercyjnych systemów Unix, w ten czy inny sposób (czasami jest pisane /dev/fd/Ndla różnych liczb całkowitych N, ale większość systemów z tym zapewnia łącza symboliczne, jak Linux i * BSD).

geekozaur
źródło
13
Rzeczywiście, /dev/std{in,out,err}są wyraźnie wymienione jako nie będące częścią standardu POSIX.1-2008 .
jw013
Wygląda na to, że ashnie obsługuje /dev/stdoutinitrd ( git.razvi.ro/… )
CMCDragonkai
@CMCDragonkai: To nie jest / dev / stdout, którym da się obsłużyć powłokę, a czego oczekiwałeś od initrd? Brakuje większości zalet, aby był tak mały, jak praktyczny.
Joshua,
22

te /dev/std{in,out,err}pliki są zwykle tylko dowiązania symboliczne do /proc/self/fd/{0,1,2}(odpowiednio). W związku z tym nic nie zyskało dzięki zastosowaniu metod zdefiniowanych w POSIX.

Jeśli chcesz być zgodny z POSIX, najlepszym sposobem na to jest przekierowanie danych wyjściowych. Przekierowanie wyjścia powłoki jest zdefiniowane w standardzie POSIX . Dodatkowo numery deskryptorów plików STDIN, STDOUT, STDERR są również częścią POSIX .
Krótko mówiąc, takie rzeczy jak na >&2pewno działają.

Należy jednak zauważyć, że użycie STDIN, STDOUT i STDERR jest subiektywne w stosunku do uruchomienia programu. Jeśli program został uruchomiony z deskryptorem pliku 1 będącym otwartym uchwytem pliku, wówczas program musi go zaakceptować. Nawet jeśli program ma być otwarty /dev/stdout, wystarczy otworzyć deskryptor pliku 1, który nadal będzie wskazywał na ten plik.
Jeśli właśnie to chcesz obejść, musisz bezpośrednio otworzyć TTY. Zwykle bez żadnych przekierowań STDIN, STDOUT i STDERR są po prostu otwartymi deskryptorami plików wskazującymi ten sam TTY. Nie ma w tym absolutnie nic więcej.

Patrick
źródło
2
+1, szczególnie w części „jedna ważna rzecz”;
Przełożę
4
Czy możesz wyjaśnić, /proc/self/fd/1czy /dev/fd/1jest częścią POSIX?
Steven Penny
/dev/std???są tylko dowiązaniami symbolicznymi do /proc/self/fdLinuksa.
Stéphane Chazelas
5

POSIX 7 mówi, że są to rozszerzenia.

Podstawowe definicje , sekcja 2.1.1 Wymagania:

System może zapewniać niestandardowe rozszerzenia. Są to funkcje niewymagane przez POSIX.1-2008 i mogą obejmować między innymi:

[...]

  • Dodatkowe postaci specjalnych plików o specjalnych właściwościach (na przykład  /dev/stdin,  /dev/stdouti  /dev/stderr)

Znaleziono przez grepowanie POSIX HTML: Gdzie jest lista funkcji API POSIX C?

Co dziwne, uuencodenarzędzie daje /dev/stdoutmagiczny efekt :

Określenie argumentu decode_pathname of /dev/stdout wskazuje, że uudecode ma używać standardowego wyjścia.

Dokumentacja jądra Linuksa mówi, że wszystkie systemy powinny ją mieć.

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

Nie mogłem jednak znaleźć, gdzie te dowiązania symboliczne są tworzone w jądrze (pod warunkiem dystrybucji?).

Ciro Santilli
źródło
1

/ dev / {stdout, stdin, stderr} działają w Bash na tych platformach:

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

Ale csh nie działa na tych:

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
źródło
6
Jaki był twój przypadek testowy? bashjest wyjątkowy, ponieważ można go samodzielnie skompilować w celu obsługi /dev/fd/xprzekierowań w systemach, które go nie mają/dev/fd
Stéphane Chazelas 22.04.16
@ StéphaneChazelas Poparłem głosowanie tylko dlatego, że widzę, że jest to mylące bez tego wyjaśnienia (bez obrazy Ole).
Evan Carroll
0

Jednym z problemów /dev/stdouti znajomych jest to, że w pewnych okolicznościach możesz nie mieć pozwolenia na pisanie do nich. Na przykład zetknąłem się z tym podczas wywoływania skryptów z Nix i wyobrażam sobie podobne narzędzia, które uruchamiają skrypty w więzieniach / piaskownicach / pojemnikach / maszynach wirtualnych / itp. mogą napotkać podobne problemy.

Używając składni podobnej do 1>&2działanej w tych przypadkach, a ponieważ wiedziałem, że będę działał w Bash, mogłem użyć zastępowania procesów dla poleceń, które oczekują nazw plików.

Warbo
źródło