Python Forum
Using subprocess to execute complex command with many arguments
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Using subprocess to execute complex command with many arguments
#1
I have a shell script that is as follows:

LOAD_RRD=sysmon.rrd
DISK_RRD=disk.rrd
DISKTEMP_RRD=disktemp.rrd

rrdtool graph load1h.png \
		-Y -u 1.1 -l 0 -L 5 -v "Load" -w 700 -h 200 -t "Load stats - `/bin/date`" \
        --start end-"1h" --x-grid MINUTE:1:MINUTE:5:MINUTE:10:0:%R \
		-c ARROW\#000000 \
		DEF:load1=$LOAD_RRD:load1:AVERAGE \
		DEF:load5=$LOAD_RRD:load5:AVERAGE \
		DEF:load15=$LOAD_RRD:load15:AVERAGE \
		LINE1:load1\#ff0000:"Load average 1 min" \
		LINE1:load5\#ff6600:"Load average 5 min" \
		LINE2:load15\#ffaa00:"Load average 15 min" \
		COMMENT:"	\j" \
		COMMENT:"\j" \
		COMMENT:"	" \
		GPRINT:load15:MIN:"Load 15 min minimum\: %lf" \
		GPRINT:load15:MAX:"Load 15 min maximum\: %lf" \
		GPRINT:load15:AVERAGE:"Load 15 min average\: %lf" \
		COMMENT:"	\j" \
		COMMENT:"	" \
		COMMENT:"	\j" >/dev/null;
I want to convert it to python using the subprocess module and run similar commands but with manipulating the internal variables and parameters.

I was thinking of copying the whole command in a single python string cmd_str then run
subprocess.run(cmd_str, shell=True)
But I'm not on the best way to escape all those internal quotes and other special symbols.
Any suggestions?
Reply
#2
(Apr-26-2023, 01:47 PM)medatib531 Wrote: Any suggestions?
Yes you just pass a list of the command's arguments as strings
subprocess.run([ "rrdtool",  "graph", "load1h.png",
      "-Y",  "-u", "1.1", "-l", "0", "-L", "5", "-v", "Load", ...])
Also I see that there is a Python API to rrdtool. Why not use that?
medatib531 likes this post
Reply
#3
But what is the correct way to escape the quotes that are originally in the shell command?
E.g. for "Load" should it be something like:
subprocess.run([ "rrdtool",  "graph", "load1h.png", "-Y",  "-u", "1.1", "-l", "0", "-L", "5", "-v", '"Load"', ...])
?
Also do I have to somehow escape the backslashes, dollar and percent symbols as well, or are they fine within double quotes in the list of strings?
Reply
#4
https://docs.python.org/3/library/shlex....hlex.split

import shlex


my_command = """
rrdtool graph load1h.png \
        -Y -u 1.1 -l 0 -L 5 -v "Load" -w 700 -h 200 -t "Load stats - `/bin/date`" \
        --start end-"1h" --x-grid MINUTE:1:MINUTE:5:MINUTE:10:0:%R \
        -c ARROW\#000000 \
        DEF:load1=$LOAD_RRD:load1:AVERAGE \
        DEF:load5=$LOAD_RRD:load5:AVERAGE \
        DEF:load15=$LOAD_RRD:load15:AVERAGE \
        LINE1:load1\#ff0000:"Load average 1 min" \
        LINE1:load5\#ff6600:"Load average 5 min" \
        LINE2:load15\#ffaa00:"Load average 15 min" \
        COMMENT:"   \j" \
        COMMENT:"\j" \
        COMMENT:"   " \
        GPRINT:load15:MIN:"Load 15 min minimum\: %lf" \
        GPRINT:load15:MAX:"Load 15 min maximum\: %lf" \
        GPRINT:load15:AVERAGE:"Load 15 min average\: %lf" \
        COMMENT:"   \j" \
        COMMENT:"   " \
        COMMENT:"   \j" >/dev/null;
""".strip().replace("\\", "")


my_cmd = shlex.split(my_command)
print(my_cmd)
The last field ">/dev/null" is wrong, but I guess you still want to suppress stdout:
subprocess.run(my_cmd, stdout=subprocess.DEVNULL)
Just get rid of the >/dev/null
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
(Apr-26-2023, 02:27 PM)medatib531 Wrote: But what is the correct way to escape the quotes that are originally in the shell command?
I ran a command to show the arguments received by your program and I get this list, that you can pass to the subprocess.run command (the first argument is missing, it should be the program, 'rrdtool')
[ 'graph', 'load1h.png', '-Y', '-u', '1.1', '-l', '0', '-L', '5', '-v', 'Load',
 '-w', '700', '-h', '200', '-t', 'Load stats - mer. 26 avril 2023 17:11:35 CEST', 
'--start', 'end-1h', '--x-grid', 'MINUTE:1:MINUTE:5:MINUTE:10:0:%R', '-c', 'ARROW#000000', 
'DEF:load1=sysmon.rrd:load1:AVERAGE', 'DEF:load5=sysmon.rrd:load5:AVERAGE', 
'DEF:load15=sysmon.rrd:load15:AVERAGE', 'LINE1:load1#ff0000:Load average 1 min', 
'LINE1:load5#ff6600:Load average 5 min', 'LINE2:load15#ffaa00:Load average 15 min',
 'COMMENT:   \\j', 'COMMENT:\\j', 'COMMENT:   ', 'GPRINT:load15:MIN:Load 15 min minimum\\: %lf', 
'GPRINT:load15:MAX:Load 15 min maximum\\: %lf',
 'GPRINT:load15:AVERAGE:Load 15 min average\\: %lf', 'COMMENT:   \\j', 'COMMENT:   ', 'COMMENT:   \\j']
@DeaD_EyE 's method using the shlex module is not perfect because it doesn't take into account the string interpolation of the shell, for example the variables $LOAD_RRD, etc

By the way, here is my executable "echoargs" script to show arguments
#!/usr/bin/env python3
# echoargs script
import sys
 
if __name__ == '__main__':
    print(sys.argv)
If you run your shell script by removing > /dev/null and you replace rrdtool with echoargs , it will print the arguments to the console in the same way that they are received by the invoked command after the shell actually processed them.

Note that the shell ran /bin/date and replaced it in the result by today's date (in french because it is my locals). So you may need to work a little bit on this, but Python's datetime module should be invoked instead of the /bin/date command to get a more pythonic script.
medatib531 likes this post
Reply
#6
Worked, thank you all!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  how to pass a mongdb command to a module and execute it. cspower 0 319 Feb-03-2024, 09:54 PM
Last Post: cspower
  use subprocess on linux\pi wwith a "grep " command korenron 2 8,119 Oct-19-2021, 10:52 AM
Last Post: DeaD_EyE
  Error when running mktorrent subprocess command pythonnewbie138 4 3,879 Sep-16-2020, 01:55 AM
Last Post: pythonnewbie138
  Select correct item from list for subprocess command pythonnewbie138 6 3,330 Jul-24-2020, 09:09 PM
Last Post: pythonnewbie138
  Subprocess command working for one cmd and for cmd one not wrking PythonBeginner_2020 0 4,146 Mar-25-2020, 01:52 PM
Last Post: PythonBeginner_2020
  execute linux command with arguments sivareddy 2 2,266 Feb-10-2020, 03:23 PM
Last Post: sivareddy
  How to parallel executing a command using subprocess? larkypython 0 2,156 Nov-28-2019, 03:49 PM
Last Post: larkypython
  changing the process command line arguments in python Skaperen 3 3,025 Aug-19-2019, 02:40 PM
Last Post: wavic
  A question about subprocess taking input from command line and returning output! Aurimas 8 5,219 May-15-2019, 04:02 PM
Last Post: Aurimas
  Issue with command line arguments artblinked 2 3,124 Feb-22-2019, 03:04 PM
Last Post: artblinked

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020