linux - 检测 stdout 是否被重定向到管道(而不是文件、字符设备、终端或套接字)?

标签 linux unix posix sh

理想情况下,这可以在 shell 中编写脚本,但 Perl 或 Python 也可以。 C 代码可能会有帮助,但可能会失败。

我认识到重定向到 FIFO(命名管道)可能与真实管道无法区分, 这已经足够我不关心的边缘情况了。

严格的 POSIX 解决方案是最好的,与 UNIX/Linux 变体无关的解决方案次之,但至少我现在需要的是可以在 Darwin (MacOS X) 上运行的东西。

在您写下答案之前 - I already know about test -t - 这会告诉我 stdout 是否是终端(在这种情况下它绝对不是管道 - 但它不会告诉我 stdout 是否已被重定向到文件、非终端字符设备或 UNIX 域套接字而不是管道。

预期用例:我有一个命令应该在 shell 的反引号内运行, 以便它可以输出设置环境变量的命令。 如果标准输出未重定向到管道,我希望命令以错误中止, 在那种情况下,它肯定不是由 eval `mycommand`; 调用的。

如果在反引号内运行命令时 shell 会设置一些特殊的环境变量,这将很有帮助,但由于它可能特定于 bash 或 zsh 或其他东西,管道检测更为重要。

最佳答案

你可以做一个 fstat到文件描述符并检查返回结构,例如,st_mode = 0x1000 (S_IFIFO) 表示命名管道。

Python 示例:

from __future__ import print_function
import sys
import os

print(os.fstat(sys.stdout.fileno()), file=sys.stderr)

Windows 输出:

C:> python test_fd.py | more
nt.stat_result(st_mode=4096, st_ino=0L, st_dev=0, st_nlink=0, st_uid=0, st_gid=0, st_size=0L, st_atime=0L, st_mtime=0L, st_ctime=0L)

C:> python test_fd.py > test_fd.txt
nt.stat_result(st_mode=33206, st_ino=16888498602769633L, st_dev=0, st_nlink=1, st_uid=0, st_gid=0, st_size=0L, st_atime= 1401119520L, st_mtime=1401119520L, st_ctime=1401119349L)

关于linux - 检测 stdout 是否被重定向到管道(而不是文件、字符设备、终端或套接字)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23873078/

相关文章:

shell - 如何在 POSIX shell 脚本中迭代字符串的字符?

c++ - 将来自 stdin 的交互式输入与到 stdout 的异步输出相结合

regex - linux/unix 中的模式匹配或 RegEx 手册页?

macos - 如何在Mac OS X上列出POSIX信号量

linux - Bash 脚本 (awk-sed-grep) 检查下一行中的数字是否比上一行多 1

linux - BASH 中的基本 Shell 脚本

linux - 如何为父目录受限的其他 FTP 用户授予 apache web 目录访问权限

c++ - 从 C++ 使用 tar 创建压缩文件

python - 按行计算匹配某些规则的两个字符之间的大文件中的总字节数

c - getaddrinfo_a 线程安全吗?