Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any way to execute a piped command in Python using subprocess module, without using shell=True?

Tags:

python

bash

I want to run a piped command line linux/bash command from Python, which first tars files, and then splits the tar file. The command would look like something this in bash:

> tar -cvf - path_to_archive/* | split -b 20m -d -a 5 - "archive.tar.split"

I know that I could execute it using subprocess, by settings shell=True, and submitting the whole command as a string, like so:

import subprocess    

subprocess.call("tar -cvf - path_to_archive/* | split -b 20m -d -a 5 - 'archive.tar.split'", shell=True)

...but for security reasons I would like to find a way to skip the "shell=True" part, (which takes a list of strings rather than a full command line string, and which can not handle the pipe char correctly). Is there any solution for this in Python? I.e., is it possible to set up linked pipes somehow, or some other solution?

like image 839
Samuel Lampa Avatar asked Dec 06 '10 16:12

Samuel Lampa


People also ask

How can we avoid shell true in subprocess?

From the docs: args is required for all calls and should be a string, or a sequence of program arguments. Providing a sequence of arguments is generally preferred, as it allows the module to take care of any required escaping and quoting of arguments (e.g. to permit spaces in file names).

Should I use shell true in subprocess?

We should avoid using 'shell=true' in subprocess call to avoid shell injection vulnerabilities. In this call you have to pass a string as a command to the shell. If call_method is user controlled then it can be used to execute any arbitrary command which can affect system.

How do you pass a pipe in subprocess Python?

To use a pipe with the subprocess module, you have to pass shell=True . In your particular case, however, the simple solution is to call subprocess. check_output(('ps', '-A')) and then str. find on the output.

Why are shells true in subprocess?

Setting the shell argument to a true value causes subprocess to spawn an intermediate shell process, and tell it to run the command. In other words, using an intermediate shell means that variables, glob patterns, and other special shell features in the command string are processed before the command is run.


1 Answers

If you want to avoid using shell=True, you can manually use subprocess pipes.

from subprocess import Popen, PIPE
p1 = Popen(["tar", "-cvf", "-", "path_to_archive"], stdout=PIPE)
p2 = Popen(["split", "-b", "20m", "-d", "-a", "5", "-", "'archive.tar.split'"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

Note that if you do not use the shell, you will not have access to expansion of globbing characters like *. Instead you can use the glob module.

like image 80
Brent Newey Avatar answered Nov 15 '22 16:11

Brent Newey