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

Redirect named pipe input to file

我想创建一个我可以写入的文件,如 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 正确打印行。

问题的答案在评论中。因此,这个问题不应该没有答案。

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

中找到

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

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