代码之家  ›  专栏  ›  技术社区  ›  HalfBrian

查找Perl内存泄漏

  •  7
  • HalfBrian  · 技术社区  · 15 年前

    解决了的 参见编辑2

    你好,

    我一直在编写一个Perl程序来处理本地(专有)程序的自动升级(为我工作的公司)。

    基本上,它是通过cron运行的,不幸的是内存泄漏(或类似的东西)。问题是只有当我不看的时候才会发生泄漏(也就是说,当通过cron运行时,而不是通过命令行)。

    我的代码不包含任何循环(或其他)引用,因此常用的引用工具不会帮助我( Devel::Cycle , Devel::Peek )

    我该怎么弄清楚是什么在使用如此多的内存 内核杀死它 ?

    基本上,代码sftps进入一个服务器(使用``sftp…````),调用openssl来验证文件,然后如果需要更多的文件,sftps会更多,并安装它们(将它们解开)。

    在第一次sftp会话之前,我看到了延迟(约15秒),但它从未使用过太多的内存,以至于(在我面前)被杀死。

    如果我不能解决这个问题,我需要用另一种语言重新写作,这需要宝贵的时间。

    编辑: 内核打印出以下消息,这让我相信这是内存泄漏:

    [100023.123] Out of memory: kill process 9568 (update.pl) score 325406 or a child
    [100023.123] Killed Process 9568 (update.pl)
    

    我不认为这是cron的问题,因为当通过命令行运行它时,会出现延迟(有时长达15秒)。此外,没有使用环境变量(至少根据我写的内容,可能是潜在的事情?)

    编辑2: 我自己发现了这个问题,在下面的MobRule评论的帮助下(针对这个问题)。事实证明,脚本是从用户(非根用户)的crontab中调用的,而(非根用户)导致了一种特殊的无限循环情况。

    对不起,伙计们,我以前没找到这个感觉有点傻,不过谢谢。

    MobRule,如果你提交你的评论作为答案,我会接受它,因为它会导致我发现问题。

    结束编辑

    谢谢, 布瑞恩

    P.S.I可能会发布一些代码片段,但由于公司的政策,这不是全部内容。

    3 回复  |  直到 15 年前
        1
  •  1
  •   David Harris    15 年前

    你怎么知道是内存泄露?我可以想到许多其他的原因,为什么操作系统会杀死一个程序。

    我要问的第一个问题是,“这个程序总是在命令行中正常工作吗?”如果答案是“否”,那么我会先解决这些问题。

    另一方面,如果答案是“是”,我将调查在cron下执行程序和从命令行执行程序之间的所有差异,以找出其行为不正常的原因。

        2
  •  5
  •   Ether    15 年前

    你可以尝试使用 Devel::Size 来分析一些对象。例如,在 main:: 作用域(.pl文件本身)执行如下操作:

    use Devel::Size qw(total_size);
    
    foreach my $varname (qw(varname1 varname2 ))
    {
        print "size used for variable $varname: " . total_size($$varname) . "\n";
    }
    

    将实际大小与您认为每个对象的合理值进行比较。一些可疑的东西可能会立即冒出来(例如,一个超负荷的缓存)。

    其他尝试:

    • 一次一个地删除一些功能,看看事情是否突然变得更好;我将从使用任何外部库开始。
    • 不良行为是否只局限于一台特定的机器或一个特定的操作系统?将程序移动到其他系统以查看其行为如何变化。
    • (在单独的安装中)尝试升级到最新的Perl(5.10.1),并升级所有CPAN模块
        3
  •  1
  •   Kyle Brandt    15 年前

    如果它是由cron运行的,那么它不应该在迭代后死亡吗?如果是这样的话,我很难看出内存泄漏会有多大影响…

    您确定是脚本本身,而不是使用内存的子进程吗?也许它最终会创建大量的ssh会话,而不是在一个会话中做大量的事情?