/dev/stdin、/dev/stdout 和 /dev/stderr 的可移植性如何?

/dev/stdin、/dev/stdout 和 /dev/stderr 的可移植性如何?

有时我需要指定标准 IO 流之一的“等效路径”(stdinstdoutstderr)。由于 99% 的时间我都在使用 Linux,所以我只是预先/dev/准备好/dev/stdin等,而这个“似乎做正确的事”。但是,一方面,我一直对这样的理由感到不安(当然,因为“它似乎有效”,直到它不起作用)。此外,我对这个动作有多便携。

所以我有几个问题:

  1. 在 Linux 环境中,将stdin, stdout, 和stderr/dev/stdin, /dev/stdout, and 等同起来是否安全(是/否) /dev/stderr

  2. 更一般地说,这种等价是否“充分”便携的“?

我找不到任何 POSIX 参考资料。

答案1

它早在 Linux 上就已经存在了。这是不是POSIX,尽管许多实际的 shell(包括 AT&Tkshbash)会模拟它(如果操作系统中不存在);请注意,此模拟仅适用于 shell 级别(即重定向或命令行参数,而不是作为 例如 的显式参数open())。也就是说,它应该可以在最多商业 Unix 系统,以一种或另一种方式(有时它被拼写/dev/fd/N为各种整数N,但大多数系统都会像 Linux 和 *BSD 那样提供符号链接)。

答案2

这些/dev/std{in,out,err}文件通常只是/proc/self/fd/{0,1,2}(分别)的符号链接。因此,使用 POSIX 定义的方法没有任何好处。

如果您希望符合 POSIX 标准,最好的方法是使用输出重定向。 Shell 输出重定向定义在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

一个问题是/dev/stdout是,在某些情况下您可能无权给他们写信。例如,我在调用脚本时遇到过这种情况尼克斯,我想象类似的工具可以在监狱/沙箱/容器/虚拟机/等中运行脚本。可能会遇到类似的问题。

使用类似语法1>&2,因为我知道我将在 Bash 中运行,所以我可以使用流程替代对于需要文件名的命令。

相关内容