如何从 shell 检查 stdin 是否为 /dev/null?

如何从 shell 检查 stdin 是否为 /dev/null?

在 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

相关内容