Python 在Linux中将子进程管道化到文件

Python 在Linux中将子进程管道化到文件,python,linux,bash,perl,Python,Linux,Bash,Perl,为了让我的代码正常工作,我正在拼命工作。本质上,我已经编写了一个python脚本,将由cron调用。该脚本每周运行一次以执行数据库维护。我的python脚本将调用执行实际维护的perl脚本。我不得不以这种方式构建它,因为perl脚本将总共运行9次。有3种不同类别的DB项,每个类别需要perl脚本中的3种不同操作。如果任何类别中的单个操作失败,脚本将从该类别中断并移动到下一个类别(每个操作取决于前一个操作) 我的脚本无法正确执行,我不知道为什么。我正在尝试对其进行故障排除,但我的日志逻辑也无法正常

为了让我的代码正常工作,我正在拼命工作。本质上,我已经编写了一个python脚本,将由cron调用。该脚本每周运行一次以执行数据库维护。我的python脚本将调用执行实际维护的perl脚本。我不得不以这种方式构建它,因为perl脚本将总共运行9次。有3种不同类别的DB项,每个类别需要perl脚本中的3种不同操作。如果任何类别中的单个操作失败,脚本将从该类别中断并移动到下一个类别(每个操作取决于前一个操作)

我的脚本无法正确执行,我不知道为什么。我正在尝试对其进行故障排除,但我的日志逻辑也无法正常工作。我在日志文件中得到的唯一输出是简单的“打印”命令,我已将这些命令写入脚本中用于表示和格式化

我可以直接从CLI很好地运行perl脚本,但从python脚本调用时它无法正常运行。谁能给我指一下正确的方向吗

编辑: 在回答一个问题时,我没有很好地解释perl脚本是如何失败的。我没有将perl脚本中的stdout或stderr写入日志文件,所以我还不知道它为什么会失败。 我没有创建perl脚本,它是随我正在管理的软件套件提供的

以下是日志文件输出:

------------------------------------------------------------------------------------------------------
Weekly Voyence archival, deletion, and purging of jobs, events, and revisions beginning at 14:46:11
Block failed, continuing to next block
------
Block failed, continuing to next block
------
Block failed, continuing to next block
------
Weekly Voyence archival, deletion, and purging of jobs, events, and revisions complete at 14:46:11
以下是从CLI运行perl脚本的输出(无错误):

以下是python脚本:

#! /usr/bin/python
import sys
import time
import os
import subprocess
def SubProcessCaller(PATH,CallLoad,LogObj,LOGFILE):
    try:
        # subprocess.Popen(["/usr/bin/perl", "-i", "/opt/voyence/tools/db-    utility/database-utility.pl", CallLoad], stderr=LogObj.write, stdout=LogObj.write, shell=true)
        concatvar = "/usr/bin/perl -I /opt/voyence/tools/db-utility/common /opt/voyence/tools/db-utility/database-utility.pl" + CallLoad + " >> " + LOGFILE
        subprocess.check_output(concatvar.split(), shell=True)
        return True
    except:
        LogObj.write("Block failed, continuing to next block" "\n")
        return False

if __name__ == "__main__":

    #DECLARE VARIABLES AND OBJECTS
    TIME = time.strftime("%H:%M:%S")
    PATH = "/opt/voyence/tools/db-utility/database-utility.pl"
    DATE = time.strftime("%Y%m%d")
    LOGFILE = "/var/log/voyence-archive/" + DATE + "voyence-archive.log"
    LOG = open(LOGFILE, "a+")
    #CREATE NEW LOG FILE
    LOG.write("------------------------------------------------------------------------------------------------------\n")
    LOG.write("Weekly Voyence archival, deletion, and purging of jobs, events, and revisions beginning at " + TIME + "\n")
    #JOB ARCHIVAL, DELETION, AND PURGING
    JobActionsDict = [" archive jobs 90"," delete jobs 90"," purge jobs 275"]
    #EVENT ARCHIVAL, DELETION, AND PURGING
    EventActionsDict = [" archive events all 90"," delete events all 90"," purge events all 275"]
    #REVISION ARCHIVAL, DELETION, AND PURGING
    RevisionActionsDict = [" archive revisions 40"," purge revisions 60","  delete revisions '3 months' 40"]

    ActionsTuple = (JobActionsDict, EventActionsDict, RevisionActionsDict)

    for dict in ActionsTuple:
        for item in dict:
            SPCBool = SubProcessCaller(PATH,item,LOG,LOGFILE)
            if SPCBool == False:
                break
        LOG.write("------\n")
    #CLOSE AFTER ALL LOGS HAVE BEEN WRITTEN
    LOG.write("Weekly Voyence archival, deletion, and purging of jobs, events, and revisions complete at " + TIME + "\n")
    LOG.close()
这会将程序名(
database utility.pl
)与
CallLoad
变量的内容连接起来,而不会在它们之间留空格。因此,除非
CallLoad
中的值以空格开头,否则实际上您将查找名为
database utility.plWhateverIsInCallLoad
的程序


这会将程序名(
database utility.pl
)与
CallLoad
变量的内容连接起来,而不会在它们之间留空格。因此,除非
CallLoad
中的值以空格开头,否则实际上您将寻找一个名为
database utility.plWhateverIsInCallLoad
的程序,该程序未经测试,但更惯用的是Python。主要的更改是在调用Perl脚本时完全绕过shell,并记录
subprocess.call可能引发的任何错误,以帮助调试问题。(考虑改用
日志记录
模块,但这已经有足够的更改。)


未经测试但更惯用的Python。主要的更改是在调用Perl脚本时完全绕过shell,并记录
subprocess.call可能引发的任何错误,以帮助调试问题。(考虑改用
日志记录
模块,但这已经有足够的更改。)


它怎么会失败?发生了什么事?有输出吗?你需要包括更多的细节。你可以回答你的问题。您不是自己编写Perl程序的,是吗?它要么已经存在,要么随您使用的任何软件一起出现。
check\u output
返回命令的输出,但是对于已经将其输出写入文件的命令来说,这没有多大意义。您可能可以使用
子流程。调用
。@simbabque-谢谢您的反馈。我已经添加了一些额外的细节来回答您的问题。@chepner-我最初使用subprocess.call,我认为我没有注释它,但显然我从脚本中删除了它。使用.call的结果与我从中得到的结果相同。请检查\u outputAlso,不要捕获任何异常或忽略实际异常。使用exc:
Exception作为exc:
,然后至少将异常写入日志文件(或直接写入标准错误),这样您就可以看到实际问题所在。它是如何失败的?发生了什么事?有输出吗?你需要包括更多的细节。你可以回答你的问题。您不是自己编写Perl程序的,是吗?它要么已经存在,要么随您使用的任何软件一起出现。
check\u output
返回命令的输出,但是对于已经将其输出写入文件的命令来说,这没有多大意义。您可能可以使用
子流程。调用
。@simbabque-谢谢您的反馈。我已经添加了一些额外的细节来回答您的问题。@chepner-我最初使用subprocess.call,我认为我没有注释它,但显然我从脚本中删除了它。使用.call的结果与我从中得到的结果相同。请检查\u outputAlso,不要捕获任何异常或忽略实际异常。使用exc:
Exception作为exc:
,然后至少将异常写入日志文件(或直接写入标准错误),这样您就可以看到实际问题所在。是的,我考虑了间隔。在操作中,每个作为调用加载传递的参数前面都有一个空格。是的,我现在看到了。我知道这不是你的问题所在。但是把空间放在我上面引用的那一行(它的存在是有意义的)而不是放在每个单独的论点(它的存在是一个谜)中不是更好吗?是的,我同意你的思考过程。你的改变很有意义。我想我现在要合并了。是的,我考虑了间距。在操作中,每个作为调用加载传递的参数前面都有一个空格。是的,我现在看到了。我知道这不是你的问题所在。但是把空间放在我上面引用的那一行(它的存在是有意义的)而不是放在每个单独的论点(它的存在是一个谜)中不是更好吗?是的,我同意你的思考过程。你的改变很有意义。我想我现在就把它合并起来。谢谢
#! /usr/bin/python
import sys
import time
import os
import subprocess
def SubProcessCaller(PATH,CallLoad,LogObj,LOGFILE):
    try:
        # subprocess.Popen(["/usr/bin/perl", "-i", "/opt/voyence/tools/db-    utility/database-utility.pl", CallLoad], stderr=LogObj.write, stdout=LogObj.write, shell=true)
        concatvar = "/usr/bin/perl -I /opt/voyence/tools/db-utility/common /opt/voyence/tools/db-utility/database-utility.pl" + CallLoad + " >> " + LOGFILE
        subprocess.check_output(concatvar.split(), shell=True)
        return True
    except:
        LogObj.write("Block failed, continuing to next block" "\n")
        return False

if __name__ == "__main__":

    #DECLARE VARIABLES AND OBJECTS
    TIME = time.strftime("%H:%M:%S")
    PATH = "/opt/voyence/tools/db-utility/database-utility.pl"
    DATE = time.strftime("%Y%m%d")
    LOGFILE = "/var/log/voyence-archive/" + DATE + "voyence-archive.log"
    LOG = open(LOGFILE, "a+")
    #CREATE NEW LOG FILE
    LOG.write("------------------------------------------------------------------------------------------------------\n")
    LOG.write("Weekly Voyence archival, deletion, and purging of jobs, events, and revisions beginning at " + TIME + "\n")
    #JOB ARCHIVAL, DELETION, AND PURGING
    JobActionsDict = [" archive jobs 90"," delete jobs 90"," purge jobs 275"]
    #EVENT ARCHIVAL, DELETION, AND PURGING
    EventActionsDict = [" archive events all 90"," delete events all 90"," purge events all 275"]
    #REVISION ARCHIVAL, DELETION, AND PURGING
    RevisionActionsDict = [" archive revisions 40"," purge revisions 60","  delete revisions '3 months' 40"]

    ActionsTuple = (JobActionsDict, EventActionsDict, RevisionActionsDict)

    for dict in ActionsTuple:
        for item in dict:
            SPCBool = SubProcessCaller(PATH,item,LOG,LOGFILE)
            if SPCBool == False:
                break
        LOG.write("------\n")
    #CLOSE AFTER ALL LOGS HAVE BEEN WRITTEN
    LOG.write("Weekly Voyence archival, deletion, and purging of jobs, events, and revisions complete at " + TIME + "\n")
    LOG.close()
concatvar = "/usr/bin/perl -I /opt/voyence/tools/db-utility/common /opt/voyence/tools/db-utility/database-utility.pl" + CallLoad + " >> " + LOGFILE
#! /usr/bin/python
import sys
import time
import os
import subprocess

def subprocess_caller(path, call_load, log_obj):
    subprocess.call(["/usr/bin/perl",
                     "-I",
                     "/opt/voyence/tools/db-utility/common",
                     path,
                     call_load],
                     stdout=log_obj)

log_header = """\
------------------------------------------------------------------------------------------------------
Weekly Voyence archival, deletion, and purging of jobs, events, and revisions beginning at %s
""" %(time.strftime("%H:%M:%S"),)

if __name__ == "__main__":

    #declare variables and objects
    path = "/opt/voyence/tools/db-utility/database-utility.pl"
    logfile = time.strftime("/var/log/voyence-archive/%Y%m%dvoyence-archive.log")

    #create new log file
    with open(logfile, "a+") as log:
        log.write(hog_header)
        #job archival, deletion, and purging
        job_actions = [" archive jobs 90"," delete jobs 90"," purge jobs 275"]
        #event archival, deletion, and purging
        event_actions = [" archive events all 90"," delete events all 90"," purge events all 275"]
        #revision archival, deletion, and purging
        revision_actions = [" archive revisions 40"," purge revisions 60","  delete revisions '3 months' 40"]

        actions = job_actions + event_actions + revision_action:

        for action_type in actions:
            for item in action_type:
                try:
                    subprocess_caller(path, item, log)
                except Exception as exc:
                    log_obj.write(exc + "\n")
                    log_obj.write("Block failed, continuing to next block\n")
                    break
                log.write("------\n")

        log.write("Weekly Voyence archival, deletion, and purging of jobs, events, and revisions complete at %s\n" %
                  (time.strftime("%H:%M:%S"),))