[英]Python: Run bash command with redirection in background and get the process id
我正在使用來自Centos 6
平台的Python 2.6.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]
最后,我需要獲取在后台運行的tail進程的pid。
將純殼包裝在python中是沒有用或明智的。
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)
除非將shell = True傳遞給subprocess.Popen()調用,否則不會執行這些重定向。 更好的方法是使用stdout = subprocess.PIPE選項並自己捕獲輸出。
Shell通常為您執行重定向。 這是將命令分解為命令和參數的向量(列表)的過程,因為shell會將那些命令傳遞給了execve()系統調用。 Shell重定向,管道和其他運算符不屬於其中。
另外,您不需要&運算符,因為您的子進程.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標准庫:用於輪詢和睡眠的select模塊 。 然后,您可以維護一次拖尾的文件列表。 不斷增長的Tail.buff也將是一個問題; 我要么在每次獲取后自動刷新它,要么添加一個方法來刷新它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.