在 Linux 上,有没有办法让 shell 脚本检查其标准输入是否从空设备 (1, 3) *重定向,理想情况下不读取任何内容?
预期的行为是:
./checkstdinnull
-> no
./checkstdinnull < /dev/null
-> yes
echo -n | ./checkstdinnull
-> no
EDIT
mknod secretunknownname c 1 3
exec 6<secretunknownname
rm secretunknownname
./checkstdinnull <&6
-> yes
我怀疑我“只是”需要读取输入的最大/最小数量设备。但我找不到从 shell 中做到这一点的方法。
*没有必要只是
/dev/null
,但是任何即使使用 手动创建,也为空设备mknod
。
答案1
在 Linux 上,你可以这样做:
stdin_is_dev_null(){ test "`stat -Lc %t:%T /dev/stdin`" = "`stat -Lc %t:%T /dev/null`"; }
在没有 stat(1) 的 Linux 上(例如路由器上的 busybox):
stdin_is_dev_null(){ ls -Ll /proc/self/fd/0 | grep -q ' 1, *3 '; }
在 *bsd 上:
stdin_is_dev_null(){ test "`stat -f %Z`" = "`stat -Lf %Z /dev/null`"; }
在 *bsd 和Solaris 等系统上,/dev/stdin
、/dev/fd/0
和/proc/PID/fd/0
不是像Linux 上那样的“神奇”符号链接,而是将切换到真实文件的字符设备当打开时。其路径上的 stat(2) 将返回与打开的文件描述符上的 fstat(2) 不同的内容。
这意味着即使安装了 GNU coreutils,linux 示例也无法在那里工作。如果 GNU stat(1) 的版本足够新,您可以使用参数-
让它在文件描述符 0 上执行 fstat(2),就像 *bsd 中的 stat(1) 一样:
stdin_is_dev_null(){ test "`stat -Lc %t:%T -`" = "`stat -Lc %t:%T /dev/null`"; }
检查也很容易便携式的任何提供 fstat(2) 接口的语言,例如。在perl
:
stdin_is_dev_null(){ perl -e 'exit((stat STDIN)[6]!=(stat "/dev/null")[6])'; }
答案2
在 Linux 上,要确定标准输入是否从 重定向/dev/null
,您可以检查是否/proc/self/fd/0
具有与 相同的设备和 inode /dev/null
:
if [ /proc/self/fd/0 -ef /dev/null ]; then echo yes; else echo no; fi
您可以使用/dev/stdin
代替/proc/self/fd/0
.
如果要检查标准输入是否从空设备重定向,则需要比较主设备号和次设备号,例如使用stat
(另请参阅莫斯维的回答):
if [ "$(stat -Lc %t:%T /dev/stdin)" = "$(stat -Lc %t:%T /dev/null)" ]; then echo yes; else echo no; fi
或者,如果你不关心这个存在Linux 特定的,
if [ "$(stat -Lc %t:%T /dev/stdin)" = "1:3" ]; then echo yes; else echo no; fi
答案3
可移植地,要检查 stdin 是否是null
设备(打开/dev/null
或不打开(如 ) 的副本/dev/null
),使用zsh
(顺便说一下,其stat
内置早于 GNU 和 FreeBSD stat
(但不是 IRIX')):
zmodload zsh/stat
if [ "$(stat +rdev -f 0)" = "$(stat +rdev /dev/null)" ]; then
echo stdin is open on the null device
fi
(请注意,它没有说明文件描述符是否以只读、只写或读+写模式打开)。
要检查它是否在当前/dev/null
文件上打开(不是/some/chroot/dev/null
例如),仅在 Linux 上(其中/dev/stdin
实现为在 fd 0 上打开的文件的符号链接,而不是在打开时像其他系统中的 a 一样的特殊设备dup(0)
):
if [ /dev/stdin -ef /dev/null ]; then
echo stdin is open on /dev/null
fi
在非 Linux 上,您可以尝试:
if sh -c 'lsof -tad0 -p"$$" /dev/null' > /dev/null 2>&-; then
echo stdin is open on /dev/null
fi