确定进程是否通过管道“连接”到另一个进程

确定进程是否通过管道“连接”到另一个进程

如果我这样做:

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 statS_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

测试文件描述符是否是管道既简单又便携。弄清楚管道另一端是什么则不然。

从外部来看,最新版本的lsofon 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,则它未连接到目标管道

如果未定义,则连接到目标管道

...至少根据我到目前为止的测试

相关内容