为什么subprocess.call(“”“scp foo”“”)坏了?

时间:2012-10-11 19:50:46

标签: python shell subprocess os.system

成功:

>>> scp_cmd = r"sudo scp -i /home/backup/.ssh/id_rsa /opt/backups/*conf backup@a-hostname.local:/opt/backups/"
>>> subprocess.call(scp_cmd, shell=True)
1eadmin1.conf                                                  100%   83KB  83.5KB/s   00:00
1stflr_1.conf                                                  100% 2904     2.8KB/s   00:00
>>> scp_cmd = """sudo scp -i /home/backup/.ssh/id_rsa /opt/backups/*conf backup@a-hostname.local:/opt/backups/"""
>>> os.system(scp_cmd)
1eadmin1.conf                                                  100%   83KB  87.3KB/s   00:00
1stflr_1.conf                                                  100% 2904     3.4KB/s   00:00

失败:

>>> scp_cmd = r"""sudo scp -i /home/backup/.ssh/id_rsa /opt/backups/*conf backup@a-hostname.local:/opt/backups/"""
>>> subprocess.call(scp_cmd, shell=True)
/opt/backups/*conf: No such file or directory
1
>>> subprocess.call(scp_cmd.split(' '))
/opt/backups/\*conf: No such file or directory
1
>>>
>>> subprocess.call(shlex.split(scp_cmd))
/opt/backups/*conf: No such file or directory
1

我很困惑为什么三重引号在我使用subprocess.call()时失败,但在我使用os.system()时通过。处理三重引用字符串时,为什么subprocess.call()os.system()之间存在差异?

2 个答案:

答案 0 :(得分:6)

我很确定你做的其他事情不同;三重引用在这里没有任何区别:

>>> a = r"sudo scp -i /home/backup/.ssh/id_rsa /opt/backups/*conf backup@a-hostname.local:/opt/backups/"
>>> b = r"""sudo scp -i /home/backup/.ssh/id_rsa /opt/backups/*conf backup@a-hostname.local:/opt/backups/"""
>>> a == b
True
>>> b
'sudo scp -i /home/backup/.ssh/id_rsa /opt/backups/*conf backup@a-hostname.local:/opt/backups/'
>>> a
'sudo scp -i /home/backup/.ssh/id_rsa /opt/backups/*conf backup@a-hostname.local:/opt/backups/'

使用三重引用只是一种方式来指定python字符串文字。如何指定该文字(使用或不使用r原始前缀,使用单引号或三引号,使用单'或双"引号)不会保留。

三重引用 会产生影响的地方是当你包含换行符时:

>>> foo = '''
... '''
>>> foo
'\n'

但您的示例根本不包含任何换行符。

答案 1 :(得分:1)

对于Martijn所说的一切都是+1,我想我可能知道发生了什么。这个输出:

>>> subprocess.call(scp_cmd.split(' '))
/opt/backups/\*conf: No such file or directory

对我来说很可疑。 为什么会出现反斜杠?

尽力匹配你的命令,我得到的东西就像[仅限用户名]:

>>> import subprocess, shlex
>>> 
>>> subprocess.call(r"scp -i /home/user/.ssh/id_rsa /tmp/*conf user@localhost:/tmp/save", shell=True)
aconf                                    100%    4     0.0KB/s   00:00    
bconf                                    100%    9     0.0KB/s   00:00    
0
>>> subprocess.call(r"""scp -i /home/user/.ssh/id_rsa /tmp/*conf user@localhost:/tmp/save""", shell=True)
aconf                                    100%    4     0.0KB/s   00:00    
bconf                                    100%    9     0.0KB/s   00:00    
0

这是有效的,因为如上所述,它们是相同的字符串。但是说你不小心在那里放了一个反斜杠?你会得到

>>> subprocess.call(r"""scp -i /home/user/.ssh/id_rsa /tmp/\*conf user@localhost:/tmp/save""", shell=True)
/tmp/*conf: No such file or directory
1
>>> subprocess.call(r"""scp -i /home/user/.ssh/id_rsa /tmp/\*conf user@localhost:/tmp/save""".split(" "))
/tmp/\*conf: No such file or directory
1
>>> subprocess.call(shlex.split(r"""scp -i /home/user/.ssh/id_rsa /tmp/\*conf user@localhost:/tmp/save"""))
/tmp/*conf: No such file or directory
1

与您的输出完全匹配 - shell=Trueshlex.split()的输出中没有反斜杠,但有.split(" ")。为了进行比较,如果没有反斜杠,则应该收到错误消息

>>> subprocess.call(r"""scp -i /home/user/.ssh/id_rsa /tmp/*conf user@localhost:/tmp/save""".split(" "))
/tmp/*conf: No such file or directory
1

所以在我看来,你发布的scp_cmd很可能不是你的输出实际对应的那个,而你真实的那个有反斜杠。