/dev/stdin、/dev/stdout、/dev/stderr はどの程度移植可能ですか?

/dev/stdin、/dev/stdout、/dev/stderr はどの程度移植可能ですか?

時々、標準のIOストリーム(stdin、、 )の1つに「パス相当」を指定する必要があります。Linuxで作業する時間の99%は、などを取得するために先頭に付けるだけです。これは「stdoutstderr/dev//dev/stdin思われる「正しいことをする」という目的があるが、第一に、私はそのような理論的根拠に常に不安を感じてきた(もちろん、うまくいかないまでは「うまくいくように見える」から)。さらに、この策略がどの程度移植可能かという点についても、私にはよくわからない。

そこでいくつか質問があります。

  1. Linux のコンテキストでは、、、およびを、、stdinおよび と同一 視しても安全 (はい/いいえ) ですか?stdoutstderr/dev/stdin/dev/stdout/dev/stderr

  2. より一般的には、この同等性は「十分にポータブル「?」

POSIX リファレンスが見つかりませんでした。

答え1

Linuxでは昔から利用可能でした。ないPOSIX ですが、多くの実際のシェル (AT&Tkshやを含むbash) は、OS に存在しない場合はこれをシミュレートします。このシミュレーションはシェル レベル (つまり、リダイレクトまたはコマンド ライン パラメータ、たとえば への明示的な引数としてではないopen()) でのみ機能することに注意してください。とはいえ、次のシェルで利用できるはずです。ほとんど商用 Unix システムでは、何らかの方法で (/dev/fd/Nさまざまな整数で表記されることもありますNが、ほとんどのシステムでは、Linux や *BSD と同様にシンボリック リンクが提供されます)。

答え2

ファイル/dev/std{in,out,err}は通常、それぞれへのシンボリックリンクです/proc/self/fd/{0,1,2}。そのため、POSIX で定義されたメソッドを使用することで得られるメリットはありません。

POSIXに準拠したい場合は、出力リダイレクトを使用するのが最善の方法です。シェル出力リダイレクトは、POSIX標準さらに、STDIN、STDOUT、STDERRファイル記述子番号もPOSIXつまり
、 のようなことは>&2確実に機能します。

ただし、STDIN、STDOUT、および STDERR の使用は、プログラムの開始方法によって左右されることに注意してください。プログラムがファイル記述子 1 をファイルへのオープン ハンドルとして開始された場合、プログラムはそれを受け入れるだけです。プログラムに を開くように指示したとしても/dev/stdout、ファイル記述子 1 を開くだけで、そのファイルを指すことになります。
これを回避したい場合は、TTY を直接開く必要があります。通常、リダイレクトが行われていない場合、STDIN、STDOUT、および STDERR はすべて、同じ TTY を指すオープン ファイル記述子になります。それ以上のことはまったくありません。

答え3

/dev/{stdout,stdin,stderr} は、次のプラットフォームの Bash で動作します。

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

しかし、csh では次の場合に失敗します:

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

答え4

およびフレンドに関する1つの問題は/dev/stdout、特定の状況では書き込み権限がない可能性があることです。たとえば、スクリプトを呼び出すときにこれに遭遇しました。ニックスまた、jail/サンドボックス/コンテナ/VM などでスクリプトを実行する同様のツールでも同様の問題が発生する可能性があると思います。

このような場合には、次のような構文が機能し1>&2、Bashで実行することがわかっていたので、プロセス置換ファイル名を期待するコマンドの場合。

関連情報