Problem executing script using Python and subprocces.call yet works in Bash
For the first time, I am asking a little bit of help over here as I am more of a ServerFault person.
I am doing some scripting in Python and I've been loving the language so far yet I have this little problem which is keeping my script from working.
Here is the code line in question :
subprocess.call('xen-create-image --hostname '+nom+' --memory '+memory+' --partitions=/root/scripts/part.tmp --ip '+ip+' --netmask '+netmask+' --gateway '+gateway+' --passwd',shell=True)
I have tried the same thing with os.popen. All the variables are correctly set.
When I execute the command in question in my regular Linux shell, it works perfectly fine but when I execute it using my Python scripts, I get bizarre errors. I even replaced subprocess.call() by the print function to make sure I am using the exact output of the command.
I went looking into environment variables of my shell but they are pretty much the same... I'll post the error I am getting but I'm not sure it's relevant to my problem.
Use of uninitialized value $lines[0] in substitution (s///) at /usr/share/perl5/Config/IniFiles.pm line 614. Use of uninitialized value $_ in pattern match (m//) at /usr/share/perl5/Config/IniFiles.pm line 628.
I am not a Python expert so I'm most likely missing something here.
Thank you in advance for your help,
Antoine
EDIT
Following miax's advice, I stopped using shell=True. Instead I took a look at the Python documentation for subprocess and used the following piece of code :
cmd = 'xen-create-image --hostname '+nom+' --memory '+memory+' --partitions=/root/scripts/part.tmp --ip '+ip+' --netmask '+netmask+' --gateway '+gateway+' --passwd'
args = shlex.split(cmd)
subprocess.call(args)
Sadly, it doesn't change anything...
EDIT2
I have used the tip given by miax but I still get the above error... Here is the code that I have used.
cmd = ['xen-create-image', '--hostname', nom, '--memory', memory, '--partitions=开发者_运维知识库/root/scripts/part.tmp', '--ip', ip, '--netmask', netmask, '--gateway', gateway, '--passwd']
subprocess.call(cmd)
This is really strange... The exact command works fine when I run it in the regular shell...
You (in most cases) don't want to use subprocess with shell=True
.
Pass it a list of arguments to the command. That is
- more secure: Imagine a user manages to pass
foo; rm -rf /; echo
as some of the values. - more reliable: Imagine one of the strings contains a
$
or something – it will be expanded by the shell and replaced by the content of that environment variable.
Without knowing your code and xen-create-image
, I assume that is the cause of your problem.
PS: Be sure to look if the exit code of the command is zero, and act appropriately if not. (If you are certain that it will always be zero, use check_call
, which raises if it does not; that way you'll at least have a defined behavior if it fails.)
Does the xen-create-image
script start with a hashbang? That is, is the first line something like
#!/bin/sh
? That is one thing to check. Another is that you can try to call your command as:
cmd = ['/bin/sh', '-c', 'xen-create-image --hostname %s --memory %s --partitions=/root/scripts/part.tmp --ip %s --netmask %s --gateway %s --passwd' % (nom, memory, ip, netmask, gateway)]
subprocess.call(cmd, shell=False)
You might want to print cmd
to verify this is the command you intend to run (i.e. check the substitutions).
In your Edit2 example which is failing, you think you are giving the following options to xen-create-image
:
--hostname
--memory
--partitions=...
- etc
... but you are actually specifying the following options:
--hostname
space- space
--memory
space - space
--partitions=...
- etc
You have this line:
cmd = ['xen-create-image', '--hostname ', nom, ' --memory ', memory, ' --partitions=/root/scripts/part.tmp', ' --ip ', ip, ' --netmask ', netmask, ' --gateway ', gateway, ' --passwd']
But you need to take out the extra spaces:
cmd = ['xen-create-image', '--hostname', nom, '--memory', memory, '--partitions=/root/scripts/part.tmp', '--ip', ip, '--netmask', netmask, '--gateway', gateway, '--passwd']
You need to print
the command you are using:
cmd = 'xen-create-image --hostname '+nom+' --memory '+memory+' --partitions=/root/scripts/part.tmp --ip '+ip+' --netmask '+netmask+' --gateway '+gateway+' --passwd'
print "COMMAND:", cmd
And then paste the command into your shell to make sure it is exactly the same.
精彩评论