Cách sử dụng lệnh `sub process` với ống dẫn


246

Tôi muốn sử dụng subprocess.check_output()với ps -A | grep 'process_name'. Tôi đã thử các giải pháp khác nhau nhưng cho đến nay không có gì hiệu quả. Ai đó có thể hướng dẫn tôi làm thế nào để làm điều đó?



4
psutilcho phép để có được thông tin quá trình một cách di động.
jfs

Câu trả lời:


438

Để sử dụng một đường ống với subprocessmô-đun, bạn phải vượt qua shell=True.

Tuy nhiên, điều này không thực sự được khuyến khích vì nhiều lý do, không ít trong số đó là bảo mật. Thay vào đó, hãy tạo psgrepxử lý riêng rẽ và chuyển đầu ra từ cái này sang cái khác, như vậy:

ps = subprocess.Popen(('ps', '-A'), stdout=subprocess.PIPE)
output = subprocess.check_output(('grep', 'process_name'), stdin=ps.stdout)
ps.wait()

Tuy nhiên, trong trường hợp cụ thể của bạn, giải pháp đơn giản là gọi subprocess.check_output(('ps', '-A'))và sau đó str.findlà đầu ra.


81
+1 để tách đầu ra / đầu vào để tránh sử dụngshell=True
Nicolas

5
Đừng quên, lỗi subprocess.CalledProcessError: Command '('grep', 'process_name')' returned non-zero exit status 1chỉ có nghĩa là không tìm thấy gì bởi grep, vì vậy đó là hành vi bình thường.
Serge

2
Tại sao chúng ta cần ps.wait()cho khi chúng ta đã có đầu ra. ps.wait.__doc__Chờ đứa trẻ chấm dứt nhưng nội dung của đứa trẻ dường như đã được đặt vào outputbiến
Papouche Guinslyzinho

3
@MakisH Bạn đang xem xét string.find, điều này không được ủng hộ str.find(nghĩa là phương thức findtrên strcác đối tượng).
Taymon

4
lưu ý: nếu grepchết sớm; pscó thể bị treo vô thời hạn nếu nó tạo ra đầu ra đủ để lấp đầy bộ đệm ống hệ điều hành của nó (vì bạn chưa gọi ps.stdout.close()cha mẹ). Hoán đổi thứ tự bắt đầu, để tránh nó
jfs

54

Hoặc bạn luôn có thể sử dụng phương thức giao tiếp trên các đối tượng của quy trình con.

cmd = "ps -A|grep 'process_name'"
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = ps.communicate()[0]
print(output)

Phương thức giao tiếp trả về một tuple của đầu ra tiêu chuẩn và lỗi tiêu chuẩn.


3
Tôi nghĩ rằng sử dụng communicatelà tốt hơn wait. Có một cảnh báo như sau: "Điều này sẽ bế tắc khi sử dụng stdout = PIPE và / hoặc stderr = PIPE và tiến trình con tạo ra đầu ra đủ cho một đường ống sao cho nó chặn bộ đệm của hệ điều hành để chấp nhận nhiều dữ liệu hơn. tránh điều đó
Paolo

2
Để làm rõ nhận xét của Paolo ở trên, cảnh báo là chờ đợi, không phải để giao tiếp - tức là lý do anh ta nói giao tiếp là tốt hơn.
EnemyBagJones

23

Xem tài liệu về cách thiết lập một đường ống bằng cách sử dụng quy trình con: http : //docs.python.org/2/l Library / sub process.html # report-shell-pipeline

Tôi đã không kiểm tra ví dụ mã sau đây nhưng nó sẽ gần như là những gì bạn muốn:

query = "process_name"
ps_process = Popen(["ps", "-A"], stdout=PIPE)
grep_process = Popen(["grep", query], stdin=ps_process.stdout, stdout=PIPE)
ps_process.stdout.close()  # Allow ps_process to receive a SIGPIPE if grep_process exits.
output = grep_process.communicate()[0]

2
Khi kiểm tra điều này không thành công, hãy xem câu trả lời dưới đây của Taymon để biết thứ gì đó hoạt động mà không cần phải rình mò
Alvin

2
sub process.checkDefput dường như không tồn tại trong Python 2.6.9
RightmireM

6

Giải pháp JKALAVIS là tốt, tuy nhiên tôi sẽ thêm một cải tiến để sử dụng shlex thay vì SHELL = TRUE. bên dưới tôi đang rút ra thời gian truy vấn

#!/bin/python
import subprocess
import shlex

cmd = "dig @8.8.4.4 +notcp www.google.com|grep 'Query'"
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = ps.communicate()[0]
print(output)

1
Tại sao shellx hơn vỏ?
AFP_555

2
shlex được sử dụng ở đâu?
3lokh

4

Ngoài ra, hãy thử sử dụng 'pgrep'lệnh thay vì'ps -A | grep 'process_name'


2
nếu bạn muốn nhận id quá trình, rõ ràng
Shooe

3

Bạn có thể thử chức năng đường ống trong sh.py :

import sh
print sh.grep(sh.ps("-ax"), "process_name")

0

Sau Python 3.5, bạn cũng có thể sử dụng:

    import subprocess

    f = open('test.txt', 'w')
    process = subprocess.run(['ls', '-la'], stdout=subprocess.PIPE, universal_newlines=True)
    f.write(process.stdout)
    f.close()

Việc thực thi lệnh đang bị chặn và đầu ra sẽ ở trong process.stdout .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.