0

I was trying to run the next command in my python code:

iostat -d 7 7 -p sda | awk '!/^Device/' | awk '!/^Linux/'

The way I tried it so far was this:

command = ["iostat", "-d", "7", "7", "-p", "sda", "|", "awk", "'!/^Device/'", "|", "awk", "'!/^Linux/'"]
device = subprocess.Popen(command, stdout=subprocess.PIPE)
devicetr = device.stdout.read()

It seems that the code won't handle the quotes marks in "'!/^Device/'" and in "'!/^Linux/'" like '!/^Device/' and '!/^Linux/' as intended.

When there is no USB connected, instead of blank I get this:

Linux 4.14.98-v7+   01/28/2020  _armv7l_    (4 CPU)

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn

Tried already adding '\' and this: Passing double quote shell commands in python to subprocess.Popen()?

karolch
  • 184
  • 4
  • 19
JhonDoe
  • 3
  • 2
  • This will not work since the `|` and other characters are interpreted by the shell and `Popen` by default runs with `shell=False`. Shell pipelines are not easy to execute from Python especially with complex quoting. – Noufal Ibrahim Feb 13 '20 at 11:00

1 Answers1

0
  1. You don't need to add additional quotes because subprocess will automatically add them when needed.
command = ["iostat", "-d", "7", "7", "-p", "sda", "|", "awk", "!/^Device/", "|", "awk", "!/^Linux/"]
device = subprocess.Popen(command, stdout=subprocess.PIPE)
devicetr = device.stdout.read()  # also here was a typo red -> read
  1. As @noufal-ibrahim pointer out | doesn't work this way. You need to pipe your commands:
ps1 = subprocess.Popen(["iostat"], stdout=subprocess.PIPE)
ps2 = subprocess.Popen(["awk",  "!/^ *KB/"], stdin=ps1.stdout, stdout=subprocess.PIPE)  # filter out line with KB and extra space
print(ps2.stdout.read().decode())

^ This code works on my machine, you can adjust it to your use case.

Appendix. And instead of manually creating command list you can use shlex lib (from standard python lib):

>>> import shlex
>>> shlex.split("python foo.py 'multi word arg'")
['python', 'foo.py', 'multi word arg']
aiven
  • 3,775
  • 3
  • 27
  • 52