如果我这样做:
x | y
有没有办法在 x 运行时检查它是否连接到 y?请注意,我不知道 y 是什么,并且我不负责启动 y。
具体来说,我谈论的是 Node.js 运行时,所以这可能是 Node.js 特定的问题。但最终,我想知道是否可以确定给定的任何运行时间。这可能吗?如何实现?
是否可以确定 stdout/stderr 是否连接到另一个进程的 stdin?我想这就是这个问题的目的。
答案1
检查程序的输出是否进入管道,基于https://nodejs.org/api/fs.html#fs_class_fs_stats,您想要调用fs.fstat(FileDescriptor)
然后调用isFIFO()
返回的stat
对象(FIFO ==先进先出==管道或命名管道):
$ </dev/null node -e 'var fs=require("fs");
fs.fstat(0,function(err,stats){ if(err) throw(err); console.log(stats.isFIFO()); }); '
false
$ : | node -e 'var fs=require("fs");
fs.fstat(0,function(err,stats){ if(err) throw(err); console.log(stats.isFIFO()); }); '
true
在 C 中,您将进行fstat
系统调用,然后使用宏测试.st_mode
返回的字段。struct stat
S_ISFIFO
如果您喜欢浪费 CPU 周期并希望使用外部二进制文件,您可以执行test -p /dev/fd/$THE_FD
来获取答案(或者在 shell 中调用该答案,其中test
将是内置函数,或者 run stat
,或者启动其他能够确定文件类型的东西)。
答案2
对于程序来说,确定其进程中任何给定的打开文件描述符是否引用管道或 FIFO 是可能的,而且相当简单。这是库函数使用的简单练习fstat()
。
您必须弄清楚如何调用fstat()
您选择的编程语言。在 C 或 C++ 语言中,执行此操作的函数非常简单:
#include <sys/types.h> // IEEE 1003.1:2008 不再需要 #include <sys/stat.h> #include <unistd.h> /// \brief 检查文件描述符是否打开并表示管道/FIFO 外部内联 bool /// \当且仅当描述符对管道/FIFO 打开时才返回 true 是_fifo( int fd ///< 要测试的文件描述符 ){ 结构体统计; 返回 0 <= fstat(fd, &s) && S_ISFIFO(s.st_mode); }
systemd中的libsystemd库有一个稍微复杂一些的sd_is_fifo()
库函数。
答案3
测试文件描述符是否是管道既简单又便携。弄清楚管道另一端是什么则不然。
从外部来看,最新版本的lsof
on Linux
:
$ sleep 100 | sleep 200 &
[1] 15314 15315
$ lsof -ad0-1 -E -p 15314
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sleep 15314 stephane 0u CHR 136,1 0t0 4 /dev/pts/1
sleep 15314 stephane 1w FIFO 0,10 0t0 17895049 pipe 15315,sleep,0r
显示 stdout 15314 是管道的写入端,而另一端的 stdin 为 15315。
答案4
使用 Node.js,在 *nix 系统上的运行时,这似乎有效:
const isTTY = process.stdout.isTTY;
如果为 true,则它未连接到目标管道
如果未定义,则连接到目标管道
...至少根据我到目前为止的测试