我正在Python 2.6.6
平台使用Centos 6
。
我需要在后台运行Python的bash命令,其中包含重定向操作符,需要从子进程对象中读取后台进程的pid。
我尝试了以下代码段,但它无效。
我的代码:
import subprocess
# Below code throws child_exception
myProcess = subprocess.Popen('tail -f -n 0 /home/user123/mainFile.txt >> /home/user123/tailFile.txt &', subprocess.PIPE)
#If I use the below command, terminating the process kills
#only the shell process and leaves the tail process as orphan
myProcess = subprocess.Popen('tail -f -n 0 /home/user123/mainFile.txt >> /home/user123/tailFile.txt', shell=True, subprocess.PIPE)
cmd = ['tail', '-f', '-n', '0', '/home/user123/mainFile.txt', '>>', '/home/user123/tailFile.txt', '&']
#Below line throws bash error saying: "cannot open file '>>'"
myProcess = subprocess.Popen(cmd, stdout=subprocess.PIPE)
myProcessPid = myProcess.communicate()[0]
最后,我需要获得正在后台运行的尾部进程的pid。
答案 0 :(得分:2)
在python中包装纯shell是没有用的或明智的。
subprocess.Popen
对象有自行执行重定向和类似事务的方法,而不是依赖shell。这是一个例子。
import subprocess
with open("ls.output.txt", "w") as f:
# This is the way you'd run "ls -al > ls.output.txt" in the background
p = subprocess.Popen(["ls", "-al"], stdout=f) # This will run in the background
p.wait() # Wait till process completes
with open("ls.output.txt") as f:
print (f.readline()) # Will print first line of ls -al output (total 2657828)
答案 1 :(得分:0)
除非将 shell = True 传递给 subprocess.Popen()调用,否则不会执行这些重定向。更好的方法是使用 stdout = subprocess.PIPE 选项并自己捕获输出。
shell通常会为您重定向。此命令将命令分解为命令和参数的向量(列表)是针对命令的,因为shell会将这些命令传递给 execve()系统调用。 shell重定向,管道和其他操作符不属于此。
你也不需要&运算符作为 subprocess.Popen()进程在后台自动运行。它可能在I / O上被阻止,您可以从 suprocess.PIPE 中轮询和读取它。
更重要的是,您根本不必使用运行 tail 命令的子进程。如果您只想跟随文件末尾,可以使用 file.seek(), file.tell(), file.readline( )和 os.fstat()方法。
这是一个直接在Python中实现 tail -f 语义的简单类:
#!/usr/bin/env python
from __future__ import print_function
import os, time
class Tail(object):
def __init__(self, filename):
self.fd = open(fn, 'r') # file descriptor
self.off = self.fd.seek(0, 2) # end of file: skip the previous contents
self.buff = list()
self.last_line = 0
self.sz = os.fstat(self.fd.fileno()).st_size
def sleep(self):
self.off = self.fd.tell()
while self.sz - self.off == 0:
self.sz = os.fstat(self.fd.fileno()).st_size
time.sleep(0.1)
def follow(self):
while self.sz - self.off > 0:
self.buff.append(self.fd.readline())
self.off = self.fd.tell()
self.sz = os.fstat(self.fd.fileno()).st_size
def fetch(self):
end = self.last_line
self.last_line = len(self.buff)
return '\n'.join(self.buff[end:])
...以及使用它的一些示例代码:
if __name__ == '__main__':
import sys
if len(sys.argv[1:]) < 1:
print('Must supply filename', file=sys.stderr)
sys.exit(1)
fn = sys.argv[1]
tail = Tail(fn)
while True:
print('... sleeping ...')
tail.sleep()
tail.follow()
print(tail.fetch())
...显示了使用它的一种方式。
我不会使用这门课。我将 Tail.sleep()更改为 Tail.poll(),它会立即返回一个值,指示最后是否有数据准备就绪的文件。我还使用Python Standard Library: select module进行轮询和睡眠。然后,您可以维护一个您一次拖尾的文件列表。不断增长的 Tail.buff 也是一个问题;我会在每次抓取后自动刷新它,或者我添加一个方法来刷新它。