2

Want a Python function can run shell command, such as,

echo 'Process started'; ping 127.0.0.1 -i 2 ; echo 'Process finished'

Requirements,

  1. It can capture real time output, and when command finished, it has a return value.
  2. It can set timeout, and when timeout, the command should be killed.

Can someone help me on this?

Subprocess.run looks not work, cause command is not killed, still running,

subprocess.run(cmd, stderr=sys.stderr, stdout=sys.stdout, shell=True, timeout=timeout)
cso
  • 91
  • 9

2 Answers2

1

Actually, the timeout option from subprocess.run is supposed to kill the command. It seems that this doesn't work when shell=True is also set. If you don't need advanced shell features, you can always break your command down to arguments, and do:

subprocess.run(['ping', '127.0.0.1', '-i', '2'], timeout = 10)

This also has the advantage that it will be easy to change the arguments from within Python without causing a security problem.

Imperishable Night
  • 1,503
  • 9
  • 19
  • if I remove shel=True, I cannot input complex command such as "echo 'Process started'; ls /; echo 'Process finished'", I am using shlex.split, it will mess up the command. – cso Jun 24 '19 at 13:57
  • Think carefully if you really want the full flexibility (and complexity) of the shell language. If you really do, maybe the problem I linked will help you. – Imperishable Night Jun 24 '19 at 18:03
0

I believe os.system() will suit your needs as:-

  1. It shows real time output, as if you were running the command on a terminal
  2. When a command is successfully executed, returns a code (ex. returns 0 if command is successful)
  3. It could be interrupted, via Control + C (Keyboard Interrupt).

You given compound command could be stripped, to create each individual command, like:-

echo 'Process started'; ping 127.0.0.1 -i 2 ; echo 'Process finished'

Becomes:-

echo 'Process started'
ping 127.0.0.1 -i 2
echo 'Process finished'

no you can store each command in a separate variable/list. And then pass it to os.system().

Example:-

import os

os.system("echo 'Process started'")
os.system("ping 127.0.0.1 -i 2")
os.system("echo 'Process Finished'")

SAMPLE OUTPUT:-

'Process started'

Pinging 127.0.0.1 with 32 bytes of data:
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128

Ping statistics for 127.0.0.1:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
'Process Finished'

P.S.:- This is just a layman example of os.system() for your case. You can further extend it to failsafe versions of it.

Vasu Deo.S
  • 1,820
  • 1
  • 11
  • 23