【问题标题】:using python script with nohup使用带有 nohup 的 python 脚本
【发布时间】:2015-07-21 09:47:54
【问题描述】:

我遇到了一个奇怪的问题(这是我第一次使用 python 练习)。

我有一个名为 run_class 的 python 脚本。我想将输出(到 stdout 和 stderr)存储在 run-class.out 中。

所以我做了以下事情(在网上看了一些例子之后)

nohup ./run_class > run-class.out &

我明白了:

[1] 13553 ~$ nohup: 忽略输入并将标准错误重定向到标准输出

所以,现在一切都很好。在我从远程注销之前,该程序确实运行良好。然后程序崩溃了。注销正是导致程序崩溃的原因。不注销会使程序运行完成。

run-class.out 出现如下错误:

Traceback (most recent call last):                                              
  File "./run_class", line 84, in <module>                                      
    wait_til_free(checkseconds)                                                 
  File "./run_class", line 53, in wait_til_free                                 
    while busy():                                                               
  File "./run_class", line 40, in busy                                          
    kmns_procs = subprocess.check_output(['ps', '-a', '-ocomm=']).splitlines()  
  File "/usr/lib64/python2.7/subprocess.py", line 573, in check_output          
    raise CalledProcessError(retcode, cmd, output=output)                       
subprocess.CalledProcessError: Command '['ps', '-a', '-ocomm=']' returned non-zero exit status 1                                                               

我的 nohup 出了什么问题?

非常感谢!

请注意,我的命令在没有退出的情况下运行,所以我不太明白这个问题。

顺便说一句:这是程序:

#!/usr/bin/python

import os
import os.path
import sys

ncpus = 8
datadir = "data" # double quotes preferred to allow for apostrophe's
ndatasets = 100
checkseconds = 1
basetries = 100

gs = [0.001, 0.005, 0.01, 0.05, 0.1]
trueks = [4, 7, 10]
ps = [4, 10, 100]
ns = [10, 100]  # times k left 1000 out, would be too much
shapes = ["HomSp"]
methods = ["Ma67"]


def busy(): 
    import subprocess
    output = subprocess.check_output("uptime", shell=False)
    words = output.split()
    sys.stderr.write("%s\n"%(output)) 
    try:
        kmns_procs = subprocess.check_output(['ps', '-a', '-ocomm=']).splitlines()
    except subprocess.CalledProcessError as x:
        print('ps returned {}, time to quit'.format(x))
        return
    kmns_wrds = 0
    procs = ["run_kmeans", "AdjRand", "BHI", "Diag", "ProAgree", "VarInf", "R"]
    for i in procs:
        kmns_wrds += kmns_procs.count(i)

    wrds=words[9]
    ldavg=float(wrds.strip(','))+0.8
    sys.stderr.write("%s %s\n"%(ldavg,kmns_wrds))
    return max(ldavg, kmns_wrds) >= ncpus


def wait_til_free(myseconds):
    while busy():
        import time
        import sys
        time.sleep(myseconds)

if True:
    for method in methods:
        for shape in shapes:
            for truek in trueks:
                for p in ps:
                    for n in ns:
                        actualn = n*truek
                for g in gs:
                            fnmprfix = "%sK%sp%sn%sg%s"%(shape,truek,p,n,g)
                            fname = "%sx.dat"%(fnmprfix)
                            for k in range(2*truek+2)[2:(2*truek+2)]:
                                ofprfix = "%sk%s"%(fnmprfix,k)
                                ntries =  actualn*p*k*basetries
                                ofname = "%s/estk/class/%s.dat"%(datadir,ofprfix,)
                                if os.path.isfile(ofname):
                                    continue
                                else :
                                    wait_til_free(checkseconds)
                                    mycmd = "nice ../kmeans/run_kmeans -# %s -N %s -n %s -p %s -K %s -D %s -X %s -i estk/class/%s.dat -t estk/time/%s_time.dat -z estk/time/%s_itime.dat -w estk/wss/%s_wss.dat  -e estk/error/%s_error.dat -c estk/mu/%s_Mu.dat -m %s &"%(ndatasets,ntries,actualn,p,k,datadir,fname,ofprfix,ofprfix,ofprfix,ofprfix,ofprfix,ofprfix,method)
                                    sys.stderr.write("%s\n"%(mycmd))
                                    from subprocess import call
                                    call(mycmd, shell=True)

【问题讨论】:

标签: python subprocess nohup


【解决方案1】:

ps 命令返回错误(非零退出状态)。可能只是因为您尝试注销而被信号打断。甚至可能是您不想要的SIGHUP。 (请注意,如果bash 获得SIGHUP'd,则bash 将显式将SIGHUP 发送到作业控制表中的每个作业,并且如果设置了huponexit 选项,它会为any 退出原因。)

您正在使用check_output。名称的check 部分表示“检查退出状态,如果它不为零,则引发异常”。所以,当然会引发异常。

如果要处理异常,可以使用try 语句。例如:

try:
    kmns_procs = subprocess.check_output(['ps', '-a', '-ocomm=']).splitlines()
except subprocess.CalledProcessError as x:
    print('ps returned {}, time to quit'.format(x))
    return
do_stuff(output)

但您也可以直接使用Popen。像check_output 这样的高级包装函数非常简单;基本上,他们所做的只是创建一个Popen,在上面调用communicate,然后检查退出状态。例如,这里是the source to the 3.4 version of check_output。您可以手动执行相同的操作(并且无需处理您无法使用的不同边缘情况、创建和引发您实际上不想要的异常等所有复杂性)。例如:

ps = subprocess.Popen(['ps', '-a', '-ocomm='], stdout=subprocess.PIPE)
output, _ = ps.communicate()
if ps.poll():
    print('ps returned {}, time to quit'.format(ps.poll()))
    return
do_stuff(output)

同时,如果您只是想知道如何确保您永远不会得到SIGHUP'd,请不要只是nohup 过程,也不要disown it

【讨论】:

  • 好的,因为这是在一个函数内部(如果使用的 cpu 数量大于 cpus 的总数,它实际上返回 True,那么在异常或 ps.poll 中有返回是否重要?它是函数的一部分。
  • @user3236841:我只是将return 放在那里,以防止它尝试运行所有do_stuff 代码,其输出要么不存在,要么不代表您的期望到。如何在真实代码中处理这种情况取决于您自己。当您无法计算使用的 CPU 数量时,您希望发生什么?如果一切正常,可能会处理它,我猜我们没有使用太多 CPU?
  • 我不希望它失败,我猜 :-) 基本上,我正在运行大约 300 个作业,一次 8 个。我不希望它在失败(我退出)时放弃,因为那会阻塞我的机器。
  • @user3236841:听起来你想跳过其余的检查,只需要return False,这意味着我们并没有过度使用 CPU,对吧?
  • 我猜,但这是否意味着添加进程只会在退出时停止?
猜你喜欢
  • 1970-01-01
  • 2013-08-10
  • 2021-01-11
  • 2022-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-30
  • 2011-01-12
相关资源
最近更新 更多