从cron或rc.local运行时,捕获python子进程的stdout stderr [英] Capture stdout stderr of python subprocess, when it runs from cron or rc.local

查看:112
本文介绍了从cron或rc.local运行时,捕获python子进程的stdout stderr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我通过 cron或rc.local

做午餐时,访问命令的输出(stderr stdout)时遇到问题,它可以正常工作完美地形成常规外壳,但通过rc.local失败

  cat /root/watchdog.py 
导入子进程
cmd =('echo TEST | gnokii --config /root/.config/gnokii/config --sendsms + 123456789xx')
#p = subprocess.Popen([cmd,'2>& 1'],stdout = subprocess.PIPE,stderr = subprocess.STDOUT,shell = True)
p = subprocess.Popen([cmd,'2& 1'],stdout = subprocess.PIPE,stderr = subprocess .PIPE,shell = True)
输出= p.stdout.read()
输出+ = p.stderr.read()
logFile = open( / root / logfile,' a +')
#####
#逐行读取的想法:
#output =''
#for iter(p.stdout.readline,' '):
#打印捕获的行:%s%line.rstrip()
##logFile.write(line.rstrip())
#输出+ =行
logFil e.write(输出)
logFile.close()

从控制台运行时的输出看起来像:

  /root/watchdog.py 
GNOKII版本0.6.30
无法打开日志文件/ root / .cache / gnokii / gnokii-errors
警告:无法打开日志文件,日志将定向到stderr
发送成功,参考号为186!

在我的rc.local中

  /root/watchdog.py> /root/mywatchPY.out 2>& 1& 

这看起来很有趣:
将子进程stderr重定向到stdout
,但不能解决问题。



任何想法如何在没有完整shell的情况下捕获子进程运行的sdterr / stdout?

解决方案

您的代码中存在多个问题:




  • shell = True 时,将命令及其参数作为字符串传递,否则参数为传递给外壳本身而不是命令

  • 您应该使用 stderr = subprocess.STDOUT 而不是 2> ;& 1 如果您打算将后者应用于整个管道,而不仅仅是最后一个命令

  • 使用 p。 communication()而不是 p.stdout.read() p.stderr.read(),否则,如果任何OS管道缓冲区已满,则子进程可能会停顿

  • 如果要重载将输出提取到文件中,则无需先将其另存为字符串





 从子进程导入Plex,STPEOUT,STDOUT 

中使用open( / root / logfile,'ab' ,0)作为日志文件:
p = Popen(shlex.split('gnokii ... + 123456789xx'),
stdin = PIPE,stdout = logfile,stderr = STDOUT)
p.communicate (b'TEST')

将子进程stderr重定向到stdout 不适用,因为您明确地重定向了 stdout


I have problem accessing output (stderr stdout) of a command when I do lunch it via cron or rc.local

It works perfectly form regular shell, but fails via rc.local

cat /root/watchdog.py 
import subprocess
    cmd = ( 'echo "TEST" |gnokii --config /root/.config/gnokii/config --sendsms +123456789xx ')
    #p = subprocess.Popen([cmd, '2>&1'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
    p = subprocess.Popen([cmd, '2>&1'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    output = p.stdout.read()
    output += p.stderr.read()
    logFile = open("/root/logfile", 'a+')
    ##### 
    #Idea to read line by line:
    #output = ''
    #    for line in iter(p.stdout.readline,''):
    #       print "captured line: %s" % line.rstrip()
    #       #logFile.write(line.rstrip())
    #       output += line
    logFile.write(output)
    logFile.close()

The output when run from console looks like:

/root/watchdog.py 
GNOKII Version 0.6.30
Cannot open logfile /root/.cache/gnokii/gnokii-errors
WARNING: cannot open logfile, logs will be directed to stderr
Send succeeded with reference 186!

in my rc.local

/root/watchdog.py  > /root/mywatchPY.out 2>&1 & 

This looks interesting: Redirect subprocess stderr to stdout but it does not solve the problem.

Any idea howto capture sdterr/stdout of subprocess run without full shell?

解决方案

There are multiple issues in your code:

  • pass the command and its args as a string when shell=True otherwise the args are passed to the shell itself instead of the command
  • you should use stderr=subprocess.STDOUT instead of 2>&1 if you meant to apply the latter to the whole pipeline and not just the last command in it
  • use p.communicate() instead of p.stdout.read(), p.stderr.read() otherwise the subprocess may stall if any of OS pipe buffers fill up
  • if you want to redirect the output to a file then you do not need to save it as a string first

import shlex
from subprocess import Popen, PIPE, STDOUT

with open("/root/logfile", 'ab', 0) as logfile:
    p = Popen(shlex.split('gnokii ... +123456789xx'), 
              stdin=PIPE, stdout=logfile, stderr=STDOUT)
    p.communicate(b'TEST')

Redirect subprocess stderr to stdout doesn't apply because you redirect stdout explicitly.

这篇关于从cron或rc.local运行时,捕获python子进程的stdout stderr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆