0

I want to write a python program, that invokes ipcs and uses its output to delete shared memory segments and semaphores. I have a working solution, but feel there must be a better way to do this. Here is my program:

import subprocess

def getid(ip):
    ret=''
    while (output[ip]==' '):
        ip=ip+1
    while((output[ip]).isdigit()):
        ret=ret+output[ip]
        ip=ip+1
    return ret


print 'invoking ipcs'
output = subprocess.check_output(['ipcs'])
print output

for i in range (len(output)):
    if (output[i]=='m'):
        r=getid(i+1)
        print r
        if (r):
            op = subprocess.check_output(['ipcrm','-m',r])
            print op
    elif (output[i]=='s'):
        r=getid(i+1)
        print r
        if (r):
            op = subprocess.check_output(['ipcrm','-s',r])
            print op

print 'invoking ipcs'
output = subprocess.check_output(['ipcs'])
print output

In particular, is there a better way to write "getid"? ie instead of parsing it character by character, can I parse it string by string?

This is what the output variable looks like (before parsing):

Message Queues:
T     ID               KEY        MODE       OWNER    GROUP

Shared Memory:
T     ID               KEY        MODE       OWNER    GROUP
m 262144                    0 --rw-rw-rw- xyz              None
m 262145                    0 --rw-rw-rw- xyz              None
m 262146                    0 --rw-rw-rw- xyz              None
m 196611                    0 --rw-rw-rw- xyz              None
m 196612                    0 --rw-rw-rw- xyz              None
m 262151                    0 --rw-rw-rw- xyz              None

Semaphores:
T     ID               KEY        MODE       OWNER    GROUP
s 262144                    0 --rw-rw-rw- xyz              None
s 262145                    0 --rw-rw-rw- xyz              None
s 196610                    0 --rw-rw-rw- xyz              None

Thanks!

2
  • Is this meant to be linux-specific, or to work with any POSIX-ish system with SysV ipc? Because I believe linux has non-standard ways to get this same info in a way that's meant to be machine-processed. Commented May 17, 2013 at 17:33
  • Also, instead of doing ipcs and then parsing out the types, you could use ipcs -m and ipcs -s, and then you'll know that every line (besides the header) is the appropriate type, so all you really need to do is the int(line.split()[1]) from qwwqwwq's answer to get the ID. Commented May 17, 2013 at 17:35

3 Answers 3

1

You can pipe in the output from ipcs line by line as it outputs it. Then I would use .strip().split() to parse each line, and something like a try except block to make sure the line fits your criteria. Parsing it as a stream of characters makes things more complicated, I wouldn't recommend it..

import subprocess
proc = subprocess.Popen(['ipcs'],stdout=subprocess.PIPE)
for line in iter(proc.stdout.readline,''):
    line=line.strip().split()
    try:
        r = int(line[1])
    except:
        continue
    if line[0] == "m":
        op = subprocess.check_output(['ipcrm','-m',str(r)])
    elif line[0] == "s":
        op = subprocess.check_output(['ipcrm','-s',str(r)])
    print op
proc.wait()
Sign up to request clarification or add additional context in comments.

2 Comments

You're missing a proc.wait() (or some other way to reap the process when it's finished).
You don't need the strip() call as there are no leading or trailing white spaces.
1

There is really no need to iterate over the output one char at a time.

For one, you should split the output string in lines and iterate over those, handling one at a time. That is done by using the splitlines method of strings (see the docs for details).

You could further split the lines on blanks, using split(), but given the regularity of your output, a regular expression fits the bill nicely. Basically, if the first character is either m or s, the next number of digits is your id, and whether m or s matches decides your next action.

You can use names to identify the groups of characters you identified, which makes for an easier reading of the regular expression and more comfortable handling of the result due to groupdict.

import re
pattern = re.compile('^((?P<mem>m)|(?P<sem>s))\s+(?P<id>\d+)')

for line in output.splitlines():
    m = pattern.match(line)
    if m:
        groups = m.groupdict()
        _id = groups['id']
        if groups['mem']:
            print 'handling a memory line' 
            pass #  handle memory case
        else:
            print ' handling a semaphore line' 
            pass #  handle semaphore case

1 Comment

You can also use splitlines() in place of split('\n'). For something as obviously Unix-specific as this problem, there's no real advantage, but it's still worth getting into the habit of thinking of lines generally.
-1

You could use the string split method to split the string based on the spaces in it.

So you could use,

for line in output:
   if (line.split(" ")[0] == 'm')):
      id = line.split(" ")[2]
      print id

1 Comment

Please use the "answer" box only to answer the question, not to ask for more information.

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.