最终更新:我真的不知道如何解释它,但问题不再发生了。如果我弄清楚改变了什么来解决它,我会发一个答案。
我有一组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
中有少量但零星的儿童。
答案 0 :(得分:1)
我只是分享我发现的相关内容。
工作脚本只包含一个循环,而破坏的循环包含一个嵌套循环,假设它将拥有比工作循环更多的进程。
sh: fork: retry: No child processes
没有子进程是系统错误,表示无法进行更多分支。因此,在执行时,代码可能会分叉更多进程,从而导致此错误。
MAX_PROC => 24
你只给了24个进程来执行一个时间,如果它尝试分叉超过这个24,按照ON_BUSY => 'block'
,它将等待并且将重试创建子进程直到成功。在模块文档Forks::Super中,它表示如果系统fork调用失败,它将失败。从错误中你清楚地知道系统无法分叉。只需添加一个$count++
变量,即可找到分叉的进程数。另请尝试Forks::Super::DEBUG,以便获得更多线索。
$ ulimit -a
不返回进程的最大数量,实际上它返回用户可以运行的最大线程数。试试ps aux
,这样您就可以更清楚地了解正在运行的流程。
答案 1 :(得分:0)
由于没有提供答案,我认为自从我刚刚经历过这个问题后,我就会加入这个较老的线程。我的Fedora 20机箱已经运行了好几个星期,周五离开办公室没有任何问题,在周一早上来了,发现我无法解锁我的xscreensaver会话。任何键或鼠标移动只会导致屏幕闪烁。按Ctrl-Alt-F2获取文本控制台,我登录并获得您列出的相同消息。我发出的每个命令(首先是sudo su - )给了我&#34; bash:fork:retry:没有子进程&#34;,最后命令将完成。
我终于能够看到一个进程列表,并没有什么似乎与众不同,因为我的ulimit设置是正常的,但我在maxuprc和open文件的限制之下。内存使用率也很好。我注意到的一件事是我的firefox进程(以及firefox插件容器进程)都消耗了过多的CPU,大约是上周以来的数百小时。我杀死了这两个进程,然后我的系统很好,之后没有任何问题。
我无法回想起我打开的标签,即使任何标签都有问题,但不管怎样,这些过程(或至少其中一个)绝对是原因。
希望有所帮助。