在执行

时间:2017-04-12 00:50:06

标签: python linux bash shell

我有一个中等大小的python脚本,可以从内部执行很多shell命令。我想在执行之前将所有这些命令打印到屏幕,以便我可以跟踪python脚本的控制流。

现在,该脚本使用多个命令来实际执行shell命令,包括来自os模块的system(),以及来自子进程模块的call(),popen()和check_output()。最简单的方法是什么?

我在考虑一个在执行它之前打印shell命令参数的包装函数,但我不知道如何编写一个可以根据用户自行决定调用正确的调用/ Popen或其他命令的泛型函数。我们还必须记住,这些调用涉及不同数量和类型的参数。

谢谢!

3 个答案:

答案 0 :(得分:1)

为您要拦截的各种电话构建并安装decorator。因为即使“内置”函数是一流的对象,您也可以用日志版本替换它们:

import os

def log_wrap(f):
    def logging_wrapper(*args, **kwargs):
        print("Calling {} with args: {!r}, kwargs: {!r}".format(f.__name__, args, kwargs))
        return f(*args, **kwargs)

    return logging_wrapper

os.system("echo 'Hello, world!'")
os.system = log_wrap(os.system)
os.system("echo 'How do you like me now?!'")

此代码在运行时(python3)打印:

$ python test.py
Hello, world!
Calling system with args: ("echo 'How do you like me now?!'",), kwargs: {}
How do you like me now?!

请注意,在对os.system的第一次和第二次调用之间,我将os.system函数替换为在将参数传递给原始函数之前打印日志消息的函数。您可以将日志消息打印到文件,或者(更好)调用logging模块,或调用pdb调试器,或任何您喜欢的...

答案 1 :(得分:0)

由于你想要启动子进程,但是记录你的行为,你需要记录子进程stdout,stderr,

import subprocess as sp
import datetime
dt=datetime.datetime.now().strftime("%Y%m%d%H%M00")
ofd = open("res.sql","w+")
efd = open("log/cmd-{}.log".format(dt),"a+")

假设您正在构建一个命令(例如,mysqldump),并且您已加载数据库,表和凭证文件名(db,tbl,cnf)。您想打印即将执行的命令,

args = ["mysqldump","--defaults-extra-file="+cnf,"--single-transaction","--quick",db,tbl]
print " ".join(args)

现在,假设您已打开上面的输出和错误文件(ofd,efd),

proc = sp.Popen(args, shell=False, stdin=sp.PIPE, stdout=ofd, stderr=efd)
stdout,stderr = proc.communicate
rc = proc.wait()
if rc>0: print "error",rc,"dbdump failed"
else: print "result",stdout,stderr

记得关闭,efd。

答案 2 :(得分:0)

import commands

commands = r'''find .'''
result = commands.getstatusoutput(command)[0]
print("Command: {}\nresult: {}".format(command,result))