3

I know there are posts already on how to use subprocess in python to run linux commands but I just cant get the syntax correct for this one. please help. This is the command I need to run...

/sbin/ifconfig eth1 | grep "inet addr" | awk -F: '{print $2}' | awk '{print $1}'

Ok this is what I have at the moment that gives a syntax error...

import subprocess
self.ip = subprocess.Popen([/sbin/ifconfig eth1 | grep "inet addr" | awk -F: '{print $2}' | awk '{print $1}'])

Any help greatly appreciated.

3

2 Answers 2

1

This has been gone over many, many times before; but here is a simple pure Python replacement for the inefficient postprocessing.

from subprocess import Popen, PIPE
eth1 = subprocess.Popen(['/sbin/ifconfig', 'eth1'], stdout=PIPE)
out, err = eth1.communicate()
for line in out.split('\n'):
    line = line.lstrip()
    if line.startswith('inet addr:'):
        ip = line.split()[1][5:]
Sign up to request clarification or add additional context in comments.

1 Comment

@whoopididoo: ip = re.search(br'inet addr:(\S+)', subprocess.check_output(['ifconfig', 'eth1'])).group(1)
0

Here's how to construct the pipe in Python (rather than reverting to Shell=True, which is more difficult to secure).

from subprocess import PIPE, Popen

# Do `which` to get correct paths
GREP_PATH = '/usr/bin/grep'
IFCONFIG_PATH = '/usr/bin/ifconfig'
AWK_PATH = '/usr/bin/awk'

awk2 = Popen([AWK_PATH, '{print $1}'], stdin=PIPE)
awk1 = Popen([AWK_PATH, '-F:', '{print $2}'], stdin=PIPE, stdout=awk2.stdin)
grep = Popen([GREP_PATH, 'inet addr'], stdin=PIPE, stdout=awk1.stdin)
ifconfig = Popen([IFCONFIG_PATH, 'eth1'], stdout=grep.stdin)

procs = [ifconfig, grep, awk1, awk2]

for proc in procs:
    print(proc)
    proc.wait()

It'd be better to do the string processing in Python using re. Do this to get the stdout of ifconfig.

from subprocess import check_output

stdout = check_output(['/usr/bin/ifconfig', 'eth1'])
print(stdout)

4 Comments

You are lacking the significant -F : option on awk1. It causes Awk to split the input on colons, instead of whitespace. Of course, the whole pipeline could be simply awk '/inet addr:/ { print substr($2, 6) }'
@tripleee I've added the -F: option.
you should close the pipes in the parent otherwise you may hang child processes. Or start the last command first and pass its stdin pipe to stdout of the preceding command.
@PeterSutton: you should get the output from awk2 (set stdout=PIPE, call communicate()). You still should close the pipes (call communicate() instead of wait(), to avoid relying on the garbage collection to free file descriptors in the parent).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.