【问题标题】:timeout limit for holding exit status from system in perl/python在 perl/python 中保持系统退出状态的超时限制
【发布时间】:2016-04-10 04:53:05
【问题描述】:

我有一个简单的 perl 脚本,它调用另一个 python 脚本在云中部署服务器。

我在 perl 中捕获部署的退出状态,以便在成功/失败设置后采取任何进一步的措施。

就像:

$cmdret = system("python script.py ARG1 ARG2");

这里的 python 脚本运行 3 小时到 7 小时。

这里的问题是,无论返回状态是成功还是失败,即使进程在后台运行并进一步中断步骤,系统也会在此步骤随机接收信号 HUP。

那么有谁知道,是否有任何时间限制来保持系统返回状态导致发送挂断信号?

在python脚本script.py内部,使用pexpect远程执行脚本:

doSsh(User,Passwd,Name,'cd '+OutputDir+';python host-bringup.py setup')
doSsh(User,Passwd,Name,'cd '+OpsHome+'/ops/hlevel;python  dshost.py start')
....

doSsh 是一个pexpect 子例程:

def doSsh(user,password,host,command):
    try:
        child =  pexpect.spawn("ssh  -o ServerAliveInterval=100 -n %s@%s '%s'" % (user,host,command),logfile=sys.stdout,timeout=None)
        i = child.expect(['password:', r'\(yes\/no\)',r'.*password for paasusr: ',r'.*[$#] ',pexpect.EOF])
        if i == 0:
                child.sendline(password)
        elif i == 1:
                child.sendline("yes")
                child.expect("password:")
                child.sendline(password)
        data = child.read()
        print data
        child.close()
        return True
    except Exception as error:
        print error
        return False

第一次doSsh 执行需要~6 小时,并且在执行几个小时后该会话被终止并显示消息:Signal HUP caught; exitingbut 执行python host-bringup.py setup 仍然在远程主机中运行。

所以在本地系统中,下一个doSsh 永远不会运行,perl 脚本中的其余步骤也永远不会继续。

【问题讨论】:

  • 系统的 perldoc 页面讨论了信号处理。从命令行执行“perldoc -f system”。另外,请注意,信号处理在不同 *nix 变体上的行为可能完全不同,因此您可能应该注意您使用的是什么操作系统。
  • 顺便说一句,不需要调用 shell。 $cmdret = system("python", "script.py", " ARG1", "ARG2");

标签: python linux perl devops nohup


【解决方案1】:

如果您的目标是让您的 perl 程序忽略 HUP 信号,您可能只需要设置 $SIG 全局信号处理程序哈希的 HUP 条目:

$SIG{ 'HUP' } = 'IGNORE';

有关血腥细节,请参阅

perldoc perlipc

【讨论】:

    【解决方案2】:

    SIGHUP 在终端断开连接时发送。当你想创建一个不绑定到终端的进程时,你daemonize它。


    请注意,nohup 不会去恶魔化。

    $ nohup perl -e'system "ps", "-o", "pid,ppid,sid,cmd"'
    nohup: ignoring input and appending output to `nohup.out'
    
    $ cat nohup.out
      PID  PPID   SID CMD
    21300 21299 21300 -bash
    21504 21300 21300 perl -esystem "ps", "-o", "pid,ppid,sid,cmd"
    21505 21504 21300 ps -o pid,ppid,sid,cmd
    

    如你所见,

    1. perl 的 PPID 是启动它的程序的 PPID。
    2. perl 的 SID 是启动它的程序的 SID。

    由于会话没有改变,终端会在正常断开连接时向perl发送SIGHUP。

    也就是说,nohup 改变了 perl 处理 SIGHUP 的方式,导致它被忽略。

    $ perl -e'system "kill", "-HUP", "$$"; print "SIGHUP was ignored\n"'
    Hangup
    
    $ echo $?
    129
    
    $ nohup perl -e'system "kill", "-HUP", "$$"; print "SIGHUP was ignored\n"'
    nohup: ignoring input and appending output to `nohup.out'
    
    $ echo $?
    0
    
    $ tail -n 1 nohup.out
    SIGHUP was ignored
    

    如果perl 被信号杀死,那是因为perl 处理 SIGHUP 的方式发生了变化。

    所以,要么守护进程,要么让perl忽略使用SIGHUP(例如,使用nohup)。但如果您使用nohup,请不要重新启用默认的 SIGHUP 行为!

    【讨论】:

    • 这就是定义所说的。但在我的情况下,perl 脚本已经被守护了,我仍然收到 SIGHUP。
    • 使用我链接的模块?
    • 不使用该模块。有一个主脚本,通过取前一个的退出状态,依次调用一系列脚本作为后端服务。
    • 我问的原因是你说脚本是守护进程,但我不确定你甚至不知道是什么意思。如果 master 收集其退出状态,显然不是守护进程,但也许您的意思是 master 脚本被守护进程?
    • 主脚本使用 nohup 运行。
    猜你喜欢
    • 2011-04-27
    • 1970-01-01
    • 2013-06-10
    • 2013-05-30
    • 2017-12-25
    • 2012-05-22
    • 2018-07-29
    • 1970-01-01
    • 2010-11-20
    相关资源
    最近更新 更多