2

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

我正在编写一些脚本,在 FreeBSD (6.2) 上?它广泛使用了以下***bash***ism:

do_something <(mysql --skip-column-names -B -e 'select ... from ... where ...;')

...其中“do_something 是一个有点笨拙的实用程序(在 Perl 中),它不会从管道中读取。如果我使用常规文件,它工作正常。我的bash脚本使用诸如此类exec 4< <(...)查询之类的东西(接下来是表格while read x y z <&4; do ...似乎从来没有任何问题。

但是,Perl (5.8.x) 似乎会定期阻塞(显然是永远阻塞)。我尝试chomp(my $data = <MYDATA>);用一​​个使用sysread的例程来改变它,并用 Python 编写了一些测试用例进行比较。这些似乎比惯用的 Perl 代码阻塞的频率要低得多,但有时它们仍然会这样做。(使用f.read()or的 Python 代码os.read(f.fileno()...)似乎在这个问题上表现得差不多)。

我已经尝试使用... <(cat ...)(我在cat常规文件的地方)重现该问题,但这似乎永远不会重现该停顿。

我浏览了一些ktrace/kdump数据……但我对 Linux strace甚至 Solaris truss更加熟悉……所以我还没有弄清楚那里发生了什么。

我想我们基本上可以排除 Perl,因为我已经使用 Python 重现了同样的问题......我看不出bash在这里做错了什么(它只是在/var/tmp/sh中创建了一个命名管道-np-xxx并将进程连接到那个)。

mysql shell/utility 正在做什么可能会导致这种情况?我认为我没有从其他任何东西(例如catdd)中看到它。我还没有在 Linux 下测试过这个场景……但我已经在 Linux 下使用<(...)了(进程替换)多年,并且不记得曾经见过这个。

是 FreeBSD 的问题吗?

当然我可以使用临时文件解决这个问题......但我肯定更愿意理解它为什么这样做(并避免临时文件带来的一些竞争和清理混乱)。

有什么建议么?

4

1 回答 1

4

对 mysql 的输出进行操作和直接对文件进行操作的最大区别在于时间。当 perl 进程停滞时,最大的问题是:“为什么它没有向前推进”?可以使用ps的“l”选项查看perl进程的等待通道;这样您就可以查看它是否在读取时被阻止,或者是否正在发生其他事情。如果它真的在管道输入上被阻塞,我希望 perl 的 MWCHAN 条目是“piperd”。

对于 mysql 进程,相同的信息会很有趣。

你的 Python 测试代码是什么样的?

在避免 bashism 的同时写这个的另一种方式是这样;这将允许您排除 bash:

mysql --skip-column-names -B -e 'select ... from ... where ...;' | do_something /dev/stdin

其他有趣的问题:

  • mysql 的 --unbuffered 选项会改变什么吗?

  • 通过 dd 管道化 mysql 输出会改变什么吗?(例如。“perlscript <(mysql ... | dd)

摘要:需要更多信息。

于 2009-10-31T06:01:29.713 回答