将命名管道输入重定向到文件

Posted

技术标签:

【中文标题】将命名管道输入重定向到文件【英文标题】:Redirect named pipe input to file 【发布时间】:2019-10-30 12:27:02 【问题描述】:

我想创建一个可以写入的文件,如Datadog Datagram docs 中所述:

echo -n 'a' >/dev/udp/localhost/8125
echo -n 'b' >/dev/udp/localhost/8125
echo -n 'c' >/dev/udp/localhost/8125

写入该文件的所有内容都应该(而不是由 Datadog 处理并通过代理发送给他们)写入日志文件。执行上述三行后,日志文件应包含以下内容:

a
b
c

我认为一个命名管道和一个处理它的后台进程将是完美的。然而,它并没有按预期工作,后台进程从不写任何东西,即使写似乎工作。

我创建了以下脚本:

#!/usr/bin/env bash
set -Eeuo pipefail

log=/var/log/datadog-agent.log
touch $log

# https://docs.datadoghq.com/developers/dogstatsd/datagram_shell/
pipe=/dev/udp/localhost/8125
if [[ ! -p $pipe ]]; then
    rm -f $pipe
    mkdir -p "$(dirname $pipe)"
    mkfifo -m 0666 $pipe
fi
trap 'rm -f $pipe' EXIT

while :; do
    read -r line <$pipe
    echo "$line" >>$log
done

还有以下 systemd 服务:

[Unit]
Description=Fake Datadog Agent

[Service]
ExecStart=/usr/local/bin/datadog-agent
Type=exec

[Install]
WantedBy=multi-user.target

服务在执行systemctl enable --now datadog-agent 后正确启动,但是,正如我所说,没有任何内容被写入日志文件。

这对我来说很奇怪,因为打开了两个 shell 实例,我在第一个 shell 中编写了以下内容:

mkfifo pipe
while :; do read -r line <pipe; echo "$line"; done

然后在第二个 shell 中开始发送数据正确打印行。

【问题讨论】:

mkfifo -m 0666 /dev/udp/localhost/8125 - 你认为这里会发生什么? /dev/udp/* 不是文件,不是fifo,它是经过特殊处理的特殊文件。如果您在/dev/udp 创建自己的fifo,则不再处理它,您只是在写入fifo。 @KamilCuk 我认为内核不知道 /dev/udp 和 /dev/tcp。我相信这些是只有 shell 才能识别的特殊字符串。 bash 处理 /dev/udp 和 /dev/tcp 并尝试创建套接字。 这个 datadog 程序从 udp 套接字 读取,而不是管道或文件。 我想将回显到该特定路径的任何内容捕获到插入换行符的文件中。 查看 bash 源代码,我相信您将不得不 patch bash to do that。无论如何,看起来都像 bash redirects 路径。在不改变写作方面的情况下,我认为您无能为力,echo 123 | tee /dev/udp/localhost/8125 之类的东西可能会起作用。 【参考方案1】:

问题的答案在它的 cmets 中找到。因此,这个问题不应该没有答案。

问题中的代码按预期工作,但是,命名管道所在的路径是一个特殊路径,这就是发送给它的数据永远不会到达脚本的原因。 Bash 中对应的特殊大小写可以在redir.c 中找到。

解决问题的方法是在该端口上使用真正的 UDP 服务器:

socat -u -v -x udp-listen:8125,fork /dev/null &>/var/log/datadog-agent.log

【讨论】:

以上是关于将命名管道输入重定向到文件的主要内容,如果未能解决你的问题,请参考以下文章

Bash 将 stdio 重定向到命名管道

无法将多个 shell 语句重定向到命名管道

将子进程的 stdout 和 stderr 重定向到两个命名管道(然后从它们读回)

/bin/sh:如何从 &3 重定向到命名管道?

在命名管道 (FIFO) 的消费者端,有没有办法区分每个项目并将其重定向到自己的进程?

第4天文件管理管道用户及组管理用户及权限管理