Re: [Tutor] os.popen - using commands and input %

2015-11-17 Thread Danny Yoo
On Mon, Nov 16, 2015 at 4:17 AM, Vusa Moyo  wrote:
> Hi Guys,
>
> My code is as follows
>
> # this list contains system process ID's
> pidst=[1232, 4543, 12009]
>
> pmap_str=[]
> command="pmap -d %s | grep private |awk '{print $1}' | awk -FK '{print $1}'"
>
> for i in range(len(pids)):
> pmap_str.append(os.popen("(command) % pidlist_int[i])"))


Hi Vusa,

If you can, please try to avoid using os.popen() or subprocess.call()
with formatted strings: that's a common security risk that's known as
a "code injection" vulnerability.

https://en.wikipedia.org/wiki/Code_injection


More generally, your program is over-using strings to do things that
they aren't meant to do.  One of the habits of the beginner is to try
to do everything in terms of strings, since strings are flexible.  But
this approach often ignores features of the language that might be
more appropriate.

I brought up that constructing the command pipeline string is one
thing to try to avoid with string formatting.  But it tries to use
strings in another way that is somewhat unnatural: it is trying to
encode the idea of re-using the command pipeline so you can feed it
different pids

"(command) % pidlist_int[i])

This idea of reuse is admirable, but the execution with string
formatting can be improved.  An alternative approach can use the
language's natural construct for reusability: the function.  We can
write a function to construct a command that is parameterized on the
given pid.


The rest of this message will sketch out what this looks like.

---


What you're doing here:

pmap -d | grep private |awk '{print $1}' | awk -FK '{print $1}'

can be translated to a sequence of operations that does not use any
string formatting to construct command lines.  See:
https://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline.
If we apply this to your command, we should expect to see something
like this (untested)

#
def get_pmap(pid):
p1 = Popen(['pmap', '-d', str(pid)], stdout=PIPE)
p2 = Popen(['grep', 'private'], stdin=p1.stdout, stdout=PIPE)
p3 = Popen(['awk', '{print $1}'], stdin=p2.stdout, stdout=PIPE)
p4 = Popen(['awk', 'FK', '{print $1}'], stdin=p3.stdout, stdout=PIPE)
p1.stdout.close()
return p4.communicate()[0]
#

Here, we package up this collection of statements into a function that
takes in a pid and returns the result.  Note that we don't have to do
any string concatenation or string formatting.


After which, we can apply this function across your list directly.

pmap_str = [get_pmap(pid) for pid in pidst]
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] os.popen - using commands and input %

2015-11-16 Thread Alan Gauld

On 16/11/15 14:05, Vusa Moyo wrote:

SOLVED> the code I used was.

for i in range(len(pids)):
 final.append(subprocess.Popen(["sudo pmap -d %s | grep private |awk
'{print $1}' | awk -FK '{print $1}'" % pids[i]], shell=True,



Glad you solved it and using subprocess is fine for the pmap stuff.
But the grep and awk stuff are usually a lot faster and almost as
easy using Python.

eg.

for line in pmap_output
if private in line:
   print line.split()[0]# {print $1}

Or, to create a list instead of printing

col1 = [line.split()[0] for line in pmap_output if private in line]

I can't remember what -FK does (F is field sep but K?)
But I'm fairly sure it will be easy to replicate in Python.

--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] os.popen - using commands and input %

2015-11-16 Thread Vusa Moyo
SOLVED> the code I used was.

for i in range(len(pids)):
final.append(subprocess.Popen(["sudo pmap -d %s | grep private |awk
'{print $1}' | awk -FK '{print $1}'" % pids[i]], shell=True,
stderr=subprocess.PIPE, stdout=subprocess.PIPE).communicate()[0])

Allowed me to append the subprocess output to my list.

Thanks for the help everyone :-)

On Mon, Nov 16, 2015 at 3:07 PM, Vusa Moyo  wrote:

> The following code seems to be pointing me to the right direction, BUT, my
> list has 0's instead of the output generated.
>
> >>> for i in range(len(pids)):
> ... final.append(subprocess.call(["sudo pmap -d %s | grep private |awk
> '{print $1}' | awk -FK '{print $1}'" % pids[i]], shell=True))
> ...
> 60772
> 106112
> 3168
> 13108
> 14876
> 8028
> 3328
> 8016
> 139424
> 6037524
> 5570492
> 4128
> 144364
> 154980
> 154980
> >>> pmap_str
> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>
> I;m assuming the zero's are exit codes, which then populate the list,
> which is not what I'm after. .
>
> On Mon, Nov 16, 2015 at 2:17 PM, Vusa Moyo  wrote:
>
>> Hi Guys,
>>
>> OS = SuSE Enterprise Linux
>> Python V2.7
>>
>> My code is as follows
>>
>> # this list contains system process ID's
>> pidst=[1232, 4543, 12009]
>>
>> pmap_str=[]
>> command="pmap -d %s | grep private |awk '{print $1}' | awk -FK '{print
>> $1}'"
>>
>> for i in range(len(pids)):
>> pmap_str.append(os.popen("(command) % pidlist_int[i])")) # <--
>> this is where I need help, please
>>
>> As I'm sure you can see, I'm trying to output the os.popen output to a
>> new list.
>>
>> On the shell console I can run the pmap command as follows
>>
>> pmap -d  | grep private |awk '{print $1}' | awk -FK '{print $1}'
>>
>> Output will be a single number such as 485921.
>>
>> My error is on the line of code shown above. Please assist.
>>
>> Kind Regards
>>
>
>
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] os.popen - using commands and input %

2015-11-16 Thread Vusa Moyo
The following code seems to be pointing me to the right direction, BUT, my
list has 0's instead of the output generated.

>>> for i in range(len(pids)):
... final.append(subprocess.call(["sudo pmap -d %s | grep private |awk
'{print $1}' | awk -FK '{print $1}'" % pids[i]], shell=True))
...
60772
106112
3168
13108
14876
8028
3328
8016
139424
6037524
5570492
4128
144364
154980
154980
>>> pmap_str
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

I;m assuming the zero's are exit codes, which then populate the list, which
is not what I'm after. .

On Mon, Nov 16, 2015 at 2:17 PM, Vusa Moyo  wrote:

> Hi Guys,
>
> OS = SuSE Enterprise Linux
> Python V2.7
>
> My code is as follows
>
> # this list contains system process ID's
> pidst=[1232, 4543, 12009]
>
> pmap_str=[]
> command="pmap -d %s | grep private |awk '{print $1}' | awk -FK '{print
> $1}'"
>
> for i in range(len(pids)):
> pmap_str.append(os.popen("(command) % pidlist_int[i])")) # <--
> this is where I need help, please
>
> As I'm sure you can see, I'm trying to output the os.popen output to a new
> list.
>
> On the shell console I can run the pmap command as follows
>
> pmap -d  | grep private |awk '{print $1}' | awk -FK '{print $1}'
>
> Output will be a single number such as 485921.
>
> My error is on the line of code shown above. Please assist.
>
> Kind Regards
>
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor