파이프와 함께 서브 프로세스 명령을 사용하는 방법


246

subprocess.check_output()와 함께 사용하고 싶습니다 ps -A | grep 'process_name'. 다양한 솔루션을 시도했지만 지금까지 아무것도 효과가 없었습니다. 누군가 나를 어떻게 도울 수 있습니까?



4
psutil즉 휴대용 방식으로 프로세스 정보를 얻을 수 있습니다.
jfs

답변:


439

subprocess모듈 과 함께 파이프를 사용하려면 을 통과해야 shell=True합니다.

그러나 이것이 여러 가지 이유로 실제로 권장되는 것은 아니며 그중에서도 보안은 아닙니다. 대신 psgrep프로세스를 별도로 작성하고 다음 과 같이 출력을 서로 연결하십시오.

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

그러나 특별한 경우에 간단한 해결책은 출력 을 호출 subprocess.check_output(('ps', '-A'))한 다음 str.find출력하는 것입니다.


81
사용을 피하기 위해 출력 / 입력 분리를위한 +1shell=True
Nicolas

5
잊지 마라, 실수 subprocess.CalledProcessError: Command '('grep', 'process_name')' returned non-zero exit status 1는 grep이 아무것도 발견하지 못했음을 의미하므로 정상적인 행동입니다.
Serge

2
ps.wait()출력이 이미 있는데 왜 for 가 필요한가 ? ps.wait.__doc__아이가 종료되기를 기다리지 만 아이의 내용은 이미 output변수에 배치 된 것 같습니다
Papouche Guinslyzinho

3
@MakisH 당신이보고있는 string.find찬성에서 사용되지하는 str.find(즉, 방법 findstr객체).
Taymon

4
참고 : grep조기에 사망하는 경우 ; psOS 파이프 버퍼를 채우기에 충분한 출력을 생성 ps.stdout.close()하면 부모에서 호출하지 않았기 때문에 무기한 중단 될 수 있습니다 . 시작 순서를 바꿔, 그것을 피하기 위해
JFS

54

또는 서브 프로세스 오브젝트에서 항상 통신 메소드를 사용할 수 있습니다.

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

communi 메소드는 표준 출력 및 표준 오류의 튜플을 리턴합니다.


3
사용하는 communicate것보다 낫다고 생각 wait합니다. 다음 과 같은 경고가 있습니다. "stdout = PIPE 및 / 또는 stderr = PIPE를 사용하면 교착 상태가 발생하고 자식 프로세스가 파이프에 충분한 출력을 생성하여 OS 파이프 버퍼가 더 많은 데이터를 수신 할 때까지 대기하는 것을 차단합니다. communi () to 피하십시오. "
Paolo

2
위에서 Paolo의 의견을 명확히하기 위해 경고는 의사 소통이 아닌 대기에 대한 것입니다. 즉, 의사 소통이 더 나은 이유입니다.
EnemyBagJones

23

하위 프로세스를 사용하여 파이프 라인 설정에 대한 문서를 참조하십시오. http://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline

다음 코드 예제를 테스트하지는 않았지만 대략 원하는 것이어야합니다.

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
이 실패 확인되면, 주변의 일 처리없이 작동 뭔가를 Taymon 아래 답을 참조
앨빈

2
subprocess.check_output이 파이썬 2.6.9에 존재하지 않는 것 같습니다
RightmireM

6

JKALAVIS 솔루션은 좋지만 SHELL = TRUE 대신 shlex를 사용하도록 개선했습니다. 아래는 쿼리 시간을 없애는 것입니다.

#!/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
왜 쉘이 쉘보다됩니까?
AFP_555

2
여기서 shlex는 어디에 사용됩니까?
3lokh

4

또한 'pgrep'대신에 명령 을 사용하십시오'ps -A | grep 'process_name'


2
프로세스 ID를 원한다면
Shooe

3

sh.py 에서 파이프 기능을 사용해 볼 수 있습니다 .

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

-1

Python 3.5 이후에는 다음을 사용할 수도 있습니다.

    import subprocess

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

명령 실행이 차단되고 출력이 process.stdout있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.