我有一个Perl脚本,读取命令文件并且通过这样做,如果必要重新启动本身:

myscript.pl:

exec '/home/foo/bin/myscript.pl';
exit(0);

现在,这个工程除了一个问题很好。读取命令文件中的线程没有访问我使用DBI句柄。并在重新启动次数我似乎建立开放式的MySQL连接数,直到我得到了可怕的“太多的连接”的错误。在DBI规范说:

“正因为如此(可能是暂时的)的限制,新创建线程必须使自己连接到数据库中。把手不能在线程间共享。”

任何方式关闭连接或可能以不同的方式来重新启动脚本?

有帮助吗?

解决方案

使用被线程之间共享的标记变量。有命令行读线程设置标志退出,该线程持有DB手柄释放它,实际上做的重新执行中:

#!/usr/bin/perl

use threads;
use threads::shared;

use strict; use warnings;
my $EXIT_FLAG :shared;

my $db_thread = threads->create('do_the_db_thing');
$db_thread->detach;

while ( 1 ) {
    sleep rand 10;
    $EXIT_FLAG = 1 if 0.05 > rand or time - $^T > 20;
}

sub do_the_db_thing {
    until ( $EXIT_FLAG ) {
        warn sprintf "%d: Working with the db\n", time - $^T;
        sleep rand 5;
    }
    # $dbh->disconnect; # here
    warn "Exit flag is set ... restarting\n";
    exec 'j.pl';
}

其他提示

您可以尝试注册一个atexit对功能在其被打开点,关闭DBI句柄,然后用叉子和exec来重新启动脚本,而并非只是高管。然后,父母会调用exit,调用atexit对回调关闭DBI句柄。子可以正常重新exec的本身。

编辑:想了一对夫妇分钟后,我相信你可以跳过完全是因为把手会在父母的退出自动关闭的atexit。除非,当然,你需要在关闭DB手柄不仅仅是一个简单的文件句柄接近做更复杂的操作。

my $pid = fork();
if (not defined $pid) {
    #Could not fork, so handle the error somehow
} elsif ($pid == 0) {
    #Child re-execs itself
    exec '/home/foo/bin/myscript.pl';
} else {
    #Parent exits
    exit(0);
}

如果您希望很多连接,你可能想 DBI :: GOFER 行动为你DBI代理。你在尽可能多的脚本创造尽可能多的连接,只要你喜欢,和DBI :: GOFER分享他们的时候就可以了。

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