FreeBSD、MySQL、Perl、bash:命名管道上的间歇性阻塞?
-
11-09-2019 - |
题
这很奇怪,我不确定真正的罪魁祸首是谁。
我正在 FreeBSD (6.2) 上编写一些脚本?它广泛使用了以下 ***bash*** 主义:
do_something <(mysql --skip-column-names -B -e 'select ... from ... where ...;')
...其中“do_something 是一个有点粗糙的实用程序(在 Perl 中),它不会从管道中读取。如果我使用常规文件,它工作正常。我的 巴什 脚本使用类似的东西 exec 4< <(...)
与这些类型的查询(后面是形式的循环 while read x y z <&4; do ...
似乎从来没有任何问题。
然而,Perl (5.8.x) 似乎会周期性地阻塞(显然是永远的)。我尝试改变 chomp(my $data = <MYDATA>);
与使用的例程 系统读取 我用Python写了一些测试用例来进行比较。这些似乎比惯用的 Perl 代码阻塞的频率要低得多,但有时它们仍然会阻塞。(Python 代码使用 f.read()
或者 os.read(f.fileno()...)
在这个问题上似乎表现得差不多)。
我尝试使用重现该问题 ... <(cat ...)
(我在哪里 猫ing 常规文件)并且似乎永远不会重现该停顿。
我看过一些 ktrace/kdump 数据 ...但我对 Linux 更熟悉 斯特雷斯 甚至是Solaris 桁架 ...所以我也还没弄清楚接下来会发生什么。
我想我们基本上可以排除 Perl,因为我已经使用 Python 重现了同样的问题......我不明白如何 巴什 可能在这里做错了什么(它只是在中创建一个命名管道 /var/tmp/sh-np-xxx 并将流程连接到此)。
可以做什么 mysql shell/实用程序正在做的事情可能会导致这种情况?我认为我没有从其他地方看到过它(例如 猫 或者 DD)。我还没有在Linux下测试过这种情况......但我用过 <(...)
(进程替换)在 Linux 下已经很多年了,但不记得曾经见过这个。
是 FreeBSD 的问题吗?
当然我可以使用临时文件解决这个问题......但我肯定更了解它为什么这样做(并避免临时文件带来的一些竞争和清理混乱)。
有什么建议么?
解决方案
对 mysql 的输出进行操作和直接对文件进行操作之间的最大区别在于时间。当 Perl 进程停止时,最大的问题是:“为什么没有取得进展”?您可以使用 ps 的“l”选项来查看 perl 进程的等待通道;这样你就可以看到它是否在读取时被阻塞,或者是否发生了其他事情。如果它确实在管道输入上被阻止,我希望 perl 的 MWCHAN 条目为“pird”。
相同的信息对于 mysql 进程来说会很有趣。
你的 Python 测试代码是什么样的?
在避免羞辱的同时,另一种写法是这样的;这将允许你排除 bash:
mysql --skip-column-names -B -e 'select ... from ... where ...;' | do_something /dev/stdin
其他有趣的问题:
mysql 的 --unbuffered 选项会改变什么吗?
通过 dd 管道传输 mysql 输出会改变什么吗?(例如。“perlscript <(mysql ...| DD)
概括:需要更多信息。