Python-将dnsmasq命令与subprocess.Popen()一起使用
我需要自动执行一系列应该输入linux终端的命令,以便为激光雷达传感器配置dhcp服务器。命令如下所示:Python-将dnsmasq命令与subprocess.Popen()一起使用,python,linux,Python,Linux,我需要自动执行一系列应该输入linux终端的命令,以便为激光雷达传感器配置dhcp服务器。命令如下所示: $ sudo -S ip addr flush dev enp3s0f1 $ ip addr show dev enp3s0f1 $ sudo -S ip addr add 10.5.5.1/24 dev enp3s0f1 $ sudo ip link set enp3s0f1 up $ ip addr show dev enp3s0f1 $ sudo dnsmasq -C /dev/nul
$ sudo -S ip addr flush dev enp3s0f1
$ ip addr show dev enp3s0f1
$ sudo -S ip addr add 10.5.5.1/24 dev enp3s0f1
$ sudo ip link set enp3s0f1 up
$ ip addr show dev enp3s0f1
$ sudo dnsmasq -C /dev/null -kd -F 10.5.5.50,10.5.5.100 -i enp3s0f1 --bind-dynamic
为此,我使用了subprocess.Popen()
类。我创建了一个名为Terminal的类,用来处理以字符串形式显示的命令:
from shlex import split
from subprocess import Popen, PIPE, STDOUT, call
class Terminal:
def __init__(self):
self.sudoPassword = "mySudoPassword"
self.ethernetPort = "enp3s0f1"
self.ipAddress = "10.5.5.1/24"
self.ipRange = "10.5.5.95,10.5.5.95"
# series of commands for connecting with the sensor
def connect_sensor(self):
if self.ping("10.5.5.95"):
print("Already connected")
else:
print(self.command("sudo -S ip addr flush dev enp3s0f1"))
print(self.command("ip addr show dev enp3s0f1"))
print(self.command("sudo -S ip addr add 10.5.5.1/24 dev enp3s0f1"))
print(self.command("sudo ip link set enp3s0f1 up"))
print(self.command("ip addr show dev enp3s0f1"))
print(self.command("sudo dnsmasq -C /dev/null -kd -F 10.5.5.50,10.5.5.100 -i enp3s0f1 --bind-dynamic"))
# excecute a command as a string
def command(self, string):
print("excecuting {}".format(string))
args = split(string)
if args[0] == "sudo":
with Popen(args, stdin=PIPE, stdout=PIPE) as proc:
outs, errs = proc.communicate('{}\n'.format(self.sudoPassword).encode("utf-8"))
print("\n")
return outs.decode('utf-8')
else:
with Popen(args, stdout=PIPE) as proc:
print("\n")
return proc.stdout.read().decode('utf-8')
# check if the sensor is connected
def ping(self, host):
param = '-c'
command = ['ping', param, '1', host]
return call(command) == 0
在我尝试使用print(self.command(“sudo dnsmasq-C/dev/null-kd-F 10.5.5.50,10.5.5.100-I enp3s0f1--bind dynamic”)运行最后一个命令之前,一切都运行得很好。
,这应该会产生以下输出:
dnsmasq: started, version 2.80 cachesize 150
dnsmasq: compile time options: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth DNSSEC loop-detect inotify dumpfile
dnsmasq-dhcp: DHCP, IP range 10.5.5.50 -- 10.5.5.100, lease time 1h
dnsmasq-dhcp: DHCP, sockets bound exclusively to interface enp3s0f1
dnsmasq: reading /etc/resolv.conf
dnsmasq: using nameserver 127.0.0.53#53
dnsmasq: read /etc/hosts - 7 addresses
一段时间后,如果传感器已连接,则应将以下线路添加到输出:
dnsmasq-dhcp: DHCPDISCOVER(enp3s0f1) 10.5.5.95 bc:0f:a7:00:1a:91
dnsmasq-dhcp: DHCPOFFER(enp3s0f1) 10.5.5.95 bc:0f:a7:00:1a:91
dnsmasq-dhcp: DHCPDISCOVER(enp3s0f1) 10.5.5.95 bc:0f:a7:00:1a:91
dnsmasq-dhcp: DHCPOFFER(enp3s0f1) 10.5.5.95 bc:0f:a7:00:1a:91
dnsmasq-dhcp: DHCPREQUEST(enp3s0f1) 10.5.5.95 bc:0f:a7:00:1a:91
dnsmasq-dhcp: DHCPACK(enp3s0f1) 10.5.5.95 bc:0f:a7:00:1a:91 os-992023000242
我需要将整个输出提取为字符串,以便以编程方式检查传感器是否已成功连接到我的计算机,但是代码在第29行被阻塞
outs, errs = proc.communicate('{}\n'.format(self.sudoPassword).encode("utf-8"))
所需的输出显示为错误
具体来说,我需要解决以下两个问题:
“DHCPACK”
。发生这种情况时,传感器已连接,因此我可以继续执行下一步outs, errs = proc.communicate('{}\n'.format(self.sudoPassword).encode("utf-8"), timeout=1)
我还尝试将stderr
输出定向到stdout
,在这种情况下,没有任何输出,函数也会阻止代码:
with Popen(args, stdin=PIPE, stdout=PIPE, stderr=STDOUT) as proc:
outs, errs = proc.communicate('{}\n'.format(self.sudoPassword).encode("utf-8"), timeout=1)
print("\n")
return outs.decode('utf-8')
我使用sudo python3 main.py
从终端运行程序,但没有成功。
我使用的是Ubuntu20.04和Python3.8.2,文档中说“从stdout和stderr读取数据,直到到达文件末尾。”这意味着是的,它是一个阻塞函数。由于dnsmasq
不会退出,communicate
将永远看不到EOF,您对communicate
的调用将永远不会返回。