Reputation: 514
My subprocess command is not working with quotes.
tail = subprocess.Popen('tail -f -n 1 /mnt/syslog/**/*.log | egrep -v \'^$|mnt\'',\
shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
When I execute python file.py I get a empty line:
# python main.py
^CTraceback (most recent call last):
File "main.py", line 18, in <module>
main()
File "main.py", line 12, in main
line = tail.stdout.readline()
KeyboardInterrupt
It works fine in bash as you can see:
# tail -f -n 1 /mnt/syslog/**/*.log | egrep -v '^$|mnt'
Sep 9 22:44:07 x.x.x.x : %LINK-3-UPDOWN: Interface GigabitEthernet1/0/19, changed state to down
Sep 9 18:32:56 x.x.x.x : %LINK-5-CHANGED: Interface GigabitEthernet1/0/24, changed state to administratively down
What is wrong?
Upvotes: 2
Views: 872
Reputation: 135
You need to run communicate() on Popen instance. It should look like
tail = subprocess.Popen('tail -f -n 1 /mnt/syslog/**/*.log | egrep -v \'^$|mnt\'',
shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout, stderr = tail.communicate()
print(stdout)
If you need unicode string instead of bytes use decode():
print(stdout.decode())
Update: Because of -f flag to tail you should get output live:
tail = subprocess.Popen('tail -f -n 1 /mnt/syslog/**/*.log | egrep -v \'^$|mnt\'',
shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
for line in tail.stdout:
print(line)
It's not best method, more you can find in this topic.
Upvotes: 1
Reputation: 338
I don't think the problem is the quotes at all.
The command is doing tail -f, which by definition never terminates (it keeps tailing the file(s)). When you call it at the shell, you immediately see some output (maybe, depending on whether the grep matches). But it probably doesn't return to the prompt, because the tail is still running.
If you really want to be following the file, then you shouldn't be using communicate() as that expects a terminating process. You have to keep reading from stdout (and stderr, to be safe!) until the process dies.
But I suspect that all you need to do is to remove the -f on the tail:
tail = subprocess.Popen('tail -n 1 /mnt/syslog/**/*.log | egrep -v \'^$|mnt\'',\
shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
If you remove the -f, then communicate() is exactly the right call to use.
Or, you can just use the check_output helper:
subprocess.check_output('tail...', shell=True)
Upvotes: 1