最终更新:我真的不知道如何解释它,但问题不再发生了。如果我找出解决问题的方法,我会发布答案。
我有一组 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
.