Почему не удается выполнить команду ping в подпроцессе? - PullRequest
1 голос
/ 04 августа 2020

Я получаю сообщение об ошибке из subprocess.Popen() для команды, которая отлично работает в командной строке.

Команда проста:

pax> ping -c2 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1:icmp_seq=1 ttl=64 time=0.022 ms
64 bytes from 127.0.0.1:icmp_seq=2 ttl=64 time=0.060 ms

Однако, когда я попробуйте сделать это из Python (интерактивно), он действует так, как будто я пропустил адрес:

>>> import shlex
>>> import subprocess
>>> args = shlex.split("ping -c2 127.0.0.1") ; print(args)
['ping', '-c2', '127.0.0.1']
>>> proc = subprocess.Popen(args, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> print(proc.stdout.read()) ; print(proc.stderr.read())
b''
b'ping: usage error: Destination address required\n'

Это сообщение об ошибке точно то, что я получаю, когда пытаюсь выполнить:

ping -c2

из оболочки без адреса.

Что могло быть причиной этого?

Ответы [ 2 ]

2 голосов
/ 04 августа 2020
#!/bin/env python

import shlex
import subprocess

args = shlex.split("ping -c2 127.0.0.1")
cmdproc = subprocess.Popen(args, stdout=subprocess.PIPE)
print(cmdproc.stdout.read())

Это то, что вы могли бы сделать. Удалите shell=True и stdin=subprocess.PIPE

. Это дает следующее:

b'PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.\n64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.026 ms\n64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.043 ms\n\n--- 127.0.0.1 ping statistics ---\n2 packets transmitted, 2 received, 0% packet loss, time 999ms\nrtt min/avg/max/mdev = 0.026/0.034/0.043/0.010 ms\n'

Дальнейшее объяснение, как если бы вы использовали аргумент shell=True, согласно [1] вам необходимо указать аргументы в виде строки, т.е. "ping -c2 127.0.0.1"

И поскольку вам не нужно вводить что-либо из стандартного ввода, вам не нужен стандартный ввод.

[1] - https://docs.python.org/3/library/subprocess.html

1 голос
/ 04 августа 2020

shell=True используется при передаче команды в виде строки

proc = subprocess.Popen("ping -c2 127.0.0.1", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

при передаче аргументов в виде списка, это должно быть shell=False

proc = subprocess.Popen(shlex.split("ping -c2 127.0.0.1"), shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

From docs

При передаче одной строки либо оболочка должна иметь значение True (см. ниже), либо строка должна просто называть программу, которая будет выполняться, без указания каких-либо аргументов.

...