2

Hi I am trying to execute shell script from python using following command.

os.system("sh myscript.sh")

in my shell script I have written some SOP's, now how do I get the SOP's in my Python so that I can log them into some file?

I know using subprocess.Popen I can do it, for some reason I can not use it.

p=subprocess.Popen(
        'DMEARAntRunner \"'+mount_path+'\"',
         shell=True,
         stdout=subprocess.PIPE,
         stderr=subprocess.STDOUT
)
while 1:
    line=p.stdout.readline()[:-1]
    if not line:
        break
    write_to_log('INFO',line)
    p.communicate()
2
  • You really do not want to use a shell for that kind of command... Commented Apr 16, 2012 at 16:02
  • Why don't you set stdout=some_file_like_object instead of PIPE? Do you need to see the output of the command on the standard stream ? Commented Apr 16, 2012 at 16:06

3 Answers 3

3

If I understand your question correctly, you want something like this:

import subprocess
find_txt_command = ['find', '-maxdepth', '2', '-name', '*.txt']
with open('mylog.log', 'w') as logfile:
    subprocess.call(find_txt_command, stdout=logfile, shell=False)

You can use Popen instead of call if you need to, the syntax is very similar. Notice that command is a list with the process you want to run and the arguments. In general you want to use Popen/call with shell=False, it prevents unexpected behavior that can be hard to debug and it is more portable.

Sign up to request clarification or add additional context in comments.

Comments

2

Kindly check this official documentation which uses the subprocess module in python. It is currently the recommended way over os.system calls to execute system functions and retrieve the results. The link above gives examples very close to what you need.

Comments

2

I personally would advise you to leave the shell argument at its default value of False. In that case, the first argument isn't a string as you'd type into a terminal, but a list of "words", the first being the program, the ones after that being arguments. This means that there is no need to quote arguments, making your program more resilient to whitespace arguments and injection attacks.

This should do the trick:

p = subsprocess.Popen(['DMEARAntRunner', mount_path], 
    stdout=subprocess.PIPE,stderr=subprocess.STDOUT)

As always with executing shell commands the question remains whether it's the easiest/best way to solve a problem, but that's another discussion altogether.

4 Comments

That said, the shell=False method is notably superior, in terms of security, performance, and correctness. This is why the default value is False.
Ah, I missed that. Good point. I do agree that the no shell form is superior, and much easier to use (no ugly quoting and whatnot).
You're right, leaving broken code around isn't going to benefit anyone. Fixed.
Thanks for being responsive. I've edited the answer as I'd like to see it. Feel free to roll it back if you don't like it.

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.