【发布时间】:2012-07-17 01:26:19
【问题描述】:
最终更新:我真的不知道如何解释,但问题不再发生。如果我找出解决问题的方法,我会发布答案。
我有一组 perl 脚本,用于在 16 核 Fedora 17 机器上执行大量类似的命令。到目前为止,每次我需要更改命令的生成方式时,我都会使用其中一个旧脚本作为模板编写一个新脚本,而且我之前从未遇到过代码问题(嗯,自从我编写了无论如何,原始的脚本集)。重要的是要注意旧脚本仍然可以正常工作,所以我认为这不是系统问题,我主要关注我(可能)搞砸代码的地方。
这是一个工作脚本的精简版本:
use Forks::Super MAX_PROC => 24, ON_BUSY => 'block';
#...
foreach my $fi (@FILES){
#...
$runMe = 'java -Xmx2048m weka.classifiers.'. $class .' -t '. $TR .' -T '. $TE .' -c 1 > '. $OUT;
fork { cmd => $runMe};
#...
}
waitall;
print("\nDone!\n");
以下是已损坏脚本的精简版:
use Forks::Super MAX_PROC => 24, ON_BUSY => 'block';
#...
foreach my $n (@FI){
if($n =~ m/^\d+$/){
#...
foreach my $f (@files){
if($f =~ m/(\d+).arff/){
print "starting interval $1 ... \n";
#...
$runMe = 'java -Xmx2048m weka.classifiers.'. $class .' -t '. $TR .' -T '. $TE .' -c 1 > '. $OUT;
fork { cmd => $runMe );
}
}
}
}
waitall;
print("\nDone!\n");
这是脚本的输出(部分):
starting interval 12 ...
starting interval 3 ...
sh: fork: retry: No child processes
starting interval 30 ...
starting interval 6 ...
Use of uninitialized value $signal_pid in print at /usr/local/share/perl5/Forks/Super/Job.pm line 991, <DATA> line 261.
Use of uninitialized value $exec_pid in waitpid at /usr/local/share/perl5/Forks/Super/Job.pm line 918, <DATA> line 261.
错误sh: fork: retry: No child processes、uninitialized value $signal_pid 和uninitialized value $exec_pid 一遍又一遍地出现在输出中看似随机的点,并且随着程序运行时间的延长而越来越多。
更新: $ ulimit -a 返回 max user processes (-u) 1024,这比我为 Forks::Super 设置的 24 以及我在这台远程机器上运行的 4 个终端要多得多。鉴于另一个脚本工作正常并且这个返回No child processes,我认为我不能清理/等待我在第二个脚本中创建的所有进程。我只是想不通在第一个和第二个脚本之间对waitall 的调用有什么不同。
更新:
使用Forks::Super::Debug => 1 选项,这里是一些有代表性的输出:
starting interval 30 ...
14694 23:24:05.735: New job created: {pid=;state=NEW;cmd=java -Xmx2048m weka.classifiers.lazy.IBk -K 3 -t /foo/arff_files/$
14703 23:24:05.735: Signal pid for 14703 is 14708
14694 23:24:05.736: fork(): {pid=;state=NEW;style=cmd;cmd=[java -Xmx2048m weka.classifiers.lazy.IBk -K 3 -t /foo/arff_file$
14694 23:24:05.736: _can_launch(): system not busy. launch ok.
14694 23:24:05.736: fork: launch approved for job
14694 23:24:05.736: Job will use /bar/.fhfork14694/.fh_007.signal to get signal pid.
14707 23:24:05.737: Executing command [ java -Xmx2048m weka.classifiers.lazy.IBk -K 3 -t /home/share/data/arff_files/trainers_l1o_curv$
Use of uninitialized value $signal_pid in print at /usr/local/share/perl5/Forks/Super/Job.pm line 991, <DATA> line 261.
Use of uninitialized value $signal_pid in concatenation (.) or string at /usr/local/share/perl5/Forks/Super/Job.pm line 995, <DATA> lin$
14707 23:24:05.737: Signal pid for 14707 is
Use of uninitialized value $exec_pid in waitpid at /usr/local/share/perl5/Forks/Super/Job.pm line 918, <DATA> line 261.
14707 23:24:05.737: waitpid returned -1, exit code of 14707 was -1 72057594037927935
starting interval 6 ...
14694 23:24:05.739: New job created: {pid=;state=NEW;cmd=java -Xmx2048m weka.classifiers.lazy.IBk -K 3 -t /foo/arff_files/$
14694 23:24:05.739: fork(): {pid=;state=NEW;style=cmd;cmd=[java -Xmx2048m weka.classifiers.lazy.IBk -K 3 -t /foo/arff_file$
14694 23:24:05.739: _can_launch(): system not busy. launch ok.
14694 23:24:05.740: fork: launch approved for job
14694 23:24:05.740: Job will use /bar/programs/.fhfork14694/.fh_008.signal to get signal pid.
14694 23:24:05.740: launch(): CORE::fork() returned undefined!
current file is 2
我相当确定问题在于进程没有及时消亡/被清理以创建新进程。 ps -aux 同意有很多孩子在奔跑,即使他们在我杀死父母之前和之后都没有出现在 top 的前 50 行中。 waitall; 调用应该防止脚本在其孩子还活着的时候退出,MAX_PROC => 24 应该防止一次启动超过 24 个孩子,所以我不确定有太多正在运行的脚本是怎么发生的任何给定的时刻。
如果waitall 是我遇到麻烦的原因,那么每次连续调用脚本时问题会变得更糟,这就是我看到的情况。但如果是这种情况,我不应该在top 中看到我在做什么。看top的时候,一开始看到有24个孩子在跑,第一次跑完后看到孩子的数量减少到没有,然后再执行,又有24个孩子在执行.. . 这是我在其他脚本中看到的正常模式。但是稍后,或者如果我终止脚本(使用pkill perl 和pkill java 确保没有与任务相关的进程处于活动状态)并重新启动它,那么我会看到大量错误消息和少量但零星的数字top 中的儿童。
【问题讨论】: