0

我正在对以前从未挂起的 Perl 脚本进行故障排除。我不知道 Perl。我终于将问题追溯到文件路径字符串。此代码有效:

$eng_morph = "~/datafile.en.db";
tie %eng_morph, "DB_File", $eng_morph, O_CREAT|O_RDWR, 0664|| die "Cannot open dbmfile $eng_morph";

当我将文件名更改为包含下划线时,第二行将永远挂起:

$eng_morph = "~/datafile.en_us.db";
tie %eng_morph, "DB_File", $eng_morph, O_CREAT|O_RDWR, 0664|| die "Cannot open dbmfile $eng_morph";

语法有问题吗?有没有办法允许下划线?

我正在使用 Ubuntu 14.04。这是 uname 输出:

Linux asus-notebook 3.13.0-43-generic #72-Ubuntu SMP Mon Dec 8 19:35:06 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

此外,我还在发行版中使用默认的 Perl。它的版本输出是:

这是为 x86_64-linux-gnu-thread-multi 构建的 perl 5,版本 18,subversion 2 (v5.18.2)(有 41 个已注册补丁,有关更多详细信息,请参见 perl -V)

4

3 回答 3

1

几乎可以肯定该特定数据库文件有问题,而不是文件名。

数据库文件已以某种方式损坏,或者服务器上的现有进程已打开该文件并将其锁定。

查看是否有任何其他进程打开了文件(使用lsof),并检查名称与数据库类似但以“。”开头的文件。在同一目录中。(即做ls -a ~ | grep -i en_us

于 2015-01-11T06:50:12.857 回答
1
tie %eng_morph, "DB_File", $eng_morph, O_CREAT|O_RDWR, 0664|| die "Cannot open dbmfile $eng_morph";

需要是:

tie %eng_morph, "DB_File", $eng_morph, O_CREAT|O_RDWR, 0664 or die "Cannot open dbmfile $eng_morph";

或者

tie( %eng_morph, "DB_File", $eng_morph, O_CREAT|O_RDWR, 0664 ) || die "Cannot open dbmfile $eng_morph";

因为||是高优先级运算符。否则它被解释为:

tie %eng_morph, "DB_File", $eng_morph, O_CREAT|O_RDWR, ( 0664 || die "Cannot open dbmfile $eng_morph" );

||旨在自然地用于返回结果的表达式中;or旨在用于本质上不同的表达式之间的流控制(尽管两者仅在优先级上有所不同)。

由于这个错误,当 tie 失败时,你不会死,代码会继续运行,但会将 %eng_morph 保留为正常的、未绑定的哈希。

于 2015-01-12T09:01:01.497 回答
0

这个问题是间歇性的。结果证明这是一个线程问题——就像许多间歇性问题一样。线索是输出文件夹中存在一个奇怪的文件:"~/_db_datafile.en.db"...或任何以 . 为前缀的已定义输出文件名"~/_db_"。当所需的输出文件应为 2 或 3 兆字节时,此输出文件的范围为 0 到 14K 字节。看起来 Perl tie() 函数在创建数据库文件时被中断了。

有问题的代码是从使用带有 subprocess.Popen() 管道的非阻塞线程的 Python 脚本调用的。Python 脚本产生了 Perl 脚本并继续其流程。当 Perl 脚本仍在创建 DB 文件时,Python 的非阻塞线程开始管道数据。这停止了​​ Perl 脚本的文件创建并导致锁定。

文件名中的下划线只是此错误的第一个间歇性实例,最终与问题无关。

解决方案是简单地在 Python 代码中创建一个while not os.path.exists(eng_morph):循环以暂停,直到存在正确的数据库文件。

于 2015-01-14T02:37:58.687 回答