neorg
neorg

Reputation: 526

Python execute complex shell command

Hi I have to execute a shell command :diff <(ssh -n [email protected] cat /vms/cloudburst.qcow2.*) <(ssh -n [email protected] cat /vms/cloudburst.qcow2) I tried

cmd="diff <(ssh -n [email protected] cat /vms/cloudburst.qcow2.*) <(ssh -n [email protected] cat /vms/cloudburst.qcow2)"
args = shlex.split(cmd)
output,error = subprocess.Popen(args,stdout = subprocess.PIPE, stderr= subprocess.PIPE).communicate()

However I am getting an error diff: extra operand cat

I am pretty new to python. Any help would be appreciated

Upvotes: 1

Views: 4840

Answers (2)

Ned Batchelder
Ned Batchelder

Reputation: 375932

You are using <(...) (process substitution) syntax, which is interpreted by the shell. Provide shell=True to Popen to get it to use a shell:

cmd = "diff <(ssh -n [email protected] cat /vms/cloudburst.qcow2.*) <(ssh -n [email protected] cat /vms/cloudburst.qcow2)"
output,error = subprocess.Popen(cmd, shell=True, executable="/bin/bash", stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()

Since you don't want the Bourne shell (/bin/sh), use the executable argument to determine the shell to use.

Upvotes: 8

niko
niko

Reputation: 1866

You are using a special syntax called process substitiution in your command line. This is supported by most modern shells (bash, zsh), but not by /bin/sh. Therefore, the method suggested by Ned might not work. (It could, if another shell provides /bin/sh and does not "correctly emulate" sh's behaviour, but it is not guaranteed to). try this instead:

cmd = "diff <(ssh -n [email protected] cat /vms/cloudburst.qcow2.*) <(ssh -n [email protected] cat /vms/cloudburst.qcow2)"
output,error = subprocess.Popen(['/bin/bash', '-c', cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()

This is basically what the shell=True parameter does, but with /bin/bash instead of /bin/sh (as described in the subprocess docs).

Upvotes: 3

Related Questions