Wie portabel sind /dev/stdin, /dev/stdout und /dev/stderr?

Wie portabel sind /dev/stdin, /dev/stdout und /dev/stderr?

Gelegentlich muss ich ein „Pfadäquivalent“ eines der Standard-IO-Streams ( stdin, stdout, stderr) angeben. Da ich 99 % der Zeit mit Linux arbeite, stelle ich einfach /dev/get /dev/stdinusw. voran und dies „scheintdas Richtige zu tun". Aber zum einen war mir eine solche Begründung immer unangenehm (denn natürlich "es scheint zu funktionieren", bis es nicht mehr funktioniert). Darüber hinaus habe ich keine Ahnung, wie übertragbar dieses Manöver ist.

Ich habe also ein paar Fragen:

  1. Ist es im Linux-Kontext sicher (ja/nein), stdin, stdout, und stderrmit /dev/stdin, /dev/stdout, und gleichzusetzen /dev/stderr?

  2. Allgemeiner gesagt: Ist diese Äquivalenz „angemessentragbar"?

Ich konnte keine POSIX-Referenzen finden.

Antwort1

Es ist seit seiner Vorgeschichte unter Linux verfügbar. Es istnichtPOSIX, obwohl viele echte Shells (einschließlich AT&T kshund bash) es simulieren, wenn es nicht im Betriebssystem vorhanden ist; beachten Sie, dass diese Simulation nur auf Shell-Ebene funktioniert (d. h. Umleitung oder Befehlszeilenparameter, nicht als explizites Argument für z. B. open()). Das heißt, es sollte verfügbar sein aufam meisten/dev/fd/Nkommerzielle Unix-Systeme, auf die eine oder andere Weise (manchmal wird es für verschiedene Ganzzahlen geschrieben N, aber die meisten Systeme mit dieser Schreibweise stellen symbolische Links bereit, wie dies bei Linux und *BSD der Fall ist).

Antwort2

die /dev/std{in,out,err}Dateien sind normalerweise nur symbolische Links zu /proc/self/fd/{0,1,2}(bzw.). Daher ist es nicht besser, Methoden zu verwenden, die POSIX-definiert sind.

Wenn Sie POSIX-kompatibel sein möchten, ist die beste Möglichkeit, dies zu erreichen, die Verwendung der Ausgabeumleitung. Die Shell-Ausgabeumleitung ist definiert inPOSIX-Standard. Zusätzlich sind die Dateideskriptornummern STDIN, STDOUT und STDERR Teil vonPOSIX
Kurz gesagt: Dinge wie funktionieren >&2garantiert.

Wichtig zu beachten ist jedoch, dass die Verwendung von STDIN, STDOUT und STDERR davon abhängt, wie das Programm gestartet wurde. Wenn das Programm mit Dateideskriptor 1 als offenem Handle für eine Datei gestartet wurde, muss Ihr Programm dies einfach akzeptieren. Selbst wenn Sie das Programm öffnen würden /dev/stdout, würde es nur Dateideskriptor 1 öffnen, der immer noch auf diese Datei zeigen wird.
Wenn Sie dies umgehen möchten, müssen Sie das TTY direkt öffnen. Normalerweise sind STDIN, STDOUT und STDERR ohne Umleitung allesamt offene Dateideskriptoren, die auf dasselbe TTY zeigen. Mehr ist absolut nicht nötig.

Antwort3

/dev/{stdout,stdin,stderr} funktioniert in Bash auf diesen Plattformen:

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

Aber es schlägt in csh bei Folgendem fehl:

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

Antwort4

Ein Problem mit /dev/stdoutund Freunden ist, dass Sie unter bestimmten Umständen keine Berechtigung haben, ihnen zu schreiben. Dies ist mir beispielsweise beim Aufrufen von Skripten vonNix, und ich kann mir vorstellen, dass ähnliche Tools, die Skripte in Jails/Sandboxen/Containern/VMs usw. ausführen, auf ähnliche Probleme stoßen könnten.

Die Verwendung der Syntax wie 1>&2funktionierte in diesen Fällen und da ich wusste, dass ich in Bash arbeiten würde, konnte ich verwendenProzesssubstitutionfür Befehle, die Dateinamen erwarten.

verwandte Informationen