我无法让subprocess.call()正常工作:
>>> from subprocess import call
>>> call(['adduser', '--home=/var/www/myusername/', '--gecos', 'GECOS', '--disabled-login', 'myusername'], shell=True)
adduser: Only one or two names allowed.
1
但没有shell = True:
>>> call(['adduser', '--home=/var/www/myusername/', '--gecos', 'GECOS', '--disabled-login', 'myusername'])
Adding user `myusername' ...
Adding new group `myusername' (1001) ...
Adding new user `myusername' (1001) with group `myusername' ...
Creating home directory `/var/www/myusername/' ...
Copying files from `/etc/skel' ...
0
或直接在shell中使用:
root@www1:~# adduser --home=/var/www/myusername/ --gecos GECOS --disabled-login myusername
Adding user `myusername' ...
Adding new group `myusername' (1001) ...
Adding new user `myusername' (1001) with group `myusername' ...
Creating home directory `/var/www/myusername/' ...
Copying files from `/etc/skel' ...
我错过了shell = True行为中的一些逻辑。有人可以解释一下为什么吗?第一个例子有什么问题?从adduser命令错误消息看,参数似乎有些瘫痪。
谢谢!
答案 0 :(得分:2)
指定shell = True时,切换到完全不同的行为。来自文档:
在Unix上,shell = True,shell默认为/ bin / sh。如果args是 string,string指定通过shell执行的命令。 这意味着字符串必须完全按照原样进行格式化 在shell提示符下键入时。这包括,例如,引用或 反斜杠转义文件名,其中包含空格。如果args是 sequence,第一项指定命令字符串,以及任何 其他项目将被视为shell的附加参数 本身。也就是说,Popen相当于:
Popen(['/ bin / sh',' - c',args [0],args [1],...])
所以你正在运行等效的
/bin/sh -c "adduser" --home=/var/www/myusername/ --gecos GECOS --disabled-login myusername
您获得的错误消息是当您尝试运行adduser
而没有任何参数时会发生的情况,因为所有参数都传递给sh
。
如果你想设置shell = True,你需要像这样调用它:
call('adduser --home=/var/www/myusername/ --gecos GECOS --disabled-login myusername', shell=True)
或者像这样:
call(['adduser --home=/var/www/myusername/ --gecos GECOS --disabled-login myusername'], shell=True)
但大多数情况下,您只想在没有call
的情况下使用shell=True
并使用参数列表。按照你的第二个,工作,例子。
答案 1 :(得分:1)
我对此并不是100%肯定,但我认为你指定Shell=True
,你应该将命令行作为shell本身将解释的单个字符串传递:
>>> call('adduser --home=/var/www/myusername/ --gecos GECOS --disabled-login myusername', shell=True)
答案 2 :(得分:0)
似乎使用shell=True
,您需要将字符串传递给args
而不是参数列表。
一个简单的测试:
In [4]: subprocess.call(['echo', 'foo', 'bar'], shell=True)
Out[4]: 0
In [5]: subprocess.call('echo foo bar', shell=True)
foo bar
Out[5]: 0
即。 echo
只有在我使用字符串而不是列表时才能获得正确的参数。
Python版本2.7.3
答案 3 :(得分:0)
如果shell为True,则指定的命令将通过shell执行,即shell负责文件名通配符,环境变量扩展等。当你使用shell = True时,cmd是一个单独的字符串,它必须完全格式化因为它将在shell中输入。如果shell = True且cmd是一个序列,则第一个参数指定命令,其他参数被视为shell本身的参数(通过-c
开关)。
如果shell = False,并且提供了一系列参数,模块将负责正确转义和引用参数,例如~
将不会扩展为主目录等。
在subprocess文档中阅读有关它的更多信息,并注意与shell = True相关的安全隐患。