这很奇怪,我不确定真正的罪魁祸首是谁。

我正在 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)

概括:需要更多信息。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top