如何在 Perl 中为长 运行 Sybase sp 设置超时
How to set timeout for a long running Sybase sp in Perl
我正在调用一个存储过程,它在 Perl 中从 Sybase 数据库中删除数据。但是sp需要几个小时才能完成。
我只希望 sp 运行 1 小时,然后无论它是否完成我都希望之后的代码是 运行ning。我该如何实施?
sub DelRef {
print "starting defRefData\n";
$db = new Sybapi($user, $password, $server, $margin_database);
#the following sql will take hours
$db->exec_sql("exec CPN_Margins..clean_up_refData_db '$XrefCode'");
}
&DelRef();
print "process is done\n";
$db->close();
你可以使用 'alarm' 这个 https://perldoc.perl.org/functions/alarm.html
my $timeout = 3600; # 1hr = 3600 sec
eval {
local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
alarm $timeout;
$db = new Sybapi($user, $password, $server, $margin_database);
$db->exec_sql("exec CPN_Margins..clean_up_refData_db '$XrefCode'");
alarm 0;
};
if ($@) {
die unless $@ eq "alarm\n"; # propagate unexpected errors
# timed out
}
else {
# didn't timed out
}
还有'Sybapi'是什么?过去,我使用 'DBD::Sybase' 连接到 Sybase ASE(或旧遗留代码中的 'sybperl'),并使用 'DBD::SQLAnywhere' 连接到 Sybase IQ。
我总是对使用 alarm
中断系统调用持谨慎态度,因为我发现很难预测信号何时会被忽略 or worse。
另一种方法是 运行 后台进程中的长 运行ning 代码,并在主进程中监视其进度。
# DelRef() might take a while ...
my $start_time = time;
my $pid = fork();
if ($pid == 0) {
# child process
DelRef();
exit 0;
}
# parent process
while (1) {
use POSIX qw( WNOHANG );
my $waitpid = waitpid $pid, WNOHANG;
if ($pid == $waitpid) {
print STDERR "DelRef() finished successfully\n";
last;
}
if (time - $start_time > 3600) {
print STDERR "DelRef() didn't finish in an hour\n";
kill 'TERM',$pid; # optional
last;
}
print STDERR "DelRef() is still running ...\n";
sleep 60;
}
print STDERR "... the rest of the script ...\n";
我正在调用一个存储过程,它在 Perl 中从 Sybase 数据库中删除数据。但是sp需要几个小时才能完成。 我只希望 sp 运行 1 小时,然后无论它是否完成我都希望之后的代码是 运行ning。我该如何实施?
sub DelRef {
print "starting defRefData\n";
$db = new Sybapi($user, $password, $server, $margin_database);
#the following sql will take hours
$db->exec_sql("exec CPN_Margins..clean_up_refData_db '$XrefCode'");
}
&DelRef();
print "process is done\n";
$db->close();
你可以使用 'alarm' 这个 https://perldoc.perl.org/functions/alarm.html
my $timeout = 3600; # 1hr = 3600 sec
eval {
local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
alarm $timeout;
$db = new Sybapi($user, $password, $server, $margin_database);
$db->exec_sql("exec CPN_Margins..clean_up_refData_db '$XrefCode'");
alarm 0;
};
if ($@) {
die unless $@ eq "alarm\n"; # propagate unexpected errors
# timed out
}
else {
# didn't timed out
}
还有'Sybapi'是什么?过去,我使用 'DBD::Sybase' 连接到 Sybase ASE(或旧遗留代码中的 'sybperl'),并使用 'DBD::SQLAnywhere' 连接到 Sybase IQ。
我总是对使用 alarm
中断系统调用持谨慎态度,因为我发现很难预测信号何时会被忽略 or worse。
另一种方法是 运行 后台进程中的长 运行ning 代码,并在主进程中监视其进度。
# DelRef() might take a while ...
my $start_time = time;
my $pid = fork();
if ($pid == 0) {
# child process
DelRef();
exit 0;
}
# parent process
while (1) {
use POSIX qw( WNOHANG );
my $waitpid = waitpid $pid, WNOHANG;
if ($pid == $waitpid) {
print STDERR "DelRef() finished successfully\n";
last;
}
if (time - $start_time > 3600) {
print STDERR "DelRef() didn't finish in an hour\n";
kill 'TERM',$pid; # optional
last;
}
print STDERR "DelRef() is still running ...\n";
sleep 60;
}
print STDERR "... the rest of the script ...\n";