如果您打印测试字符串,您会注意到它会产生以下结果:su -c "lftp -c 'open -u user,password ftp://127.0.0.1; get ivan's\ filename.pdf' " someuser
问题是您需要转义用来转义单引号的斜杠,以防止Python吃掉它。在
^{pr2}$
将得到反斜杠,你将得到一个错误,从lftp代替。。。在
这是有效的:command = "su -c \"lftp -c \\\"open -u user,password ftp://127.0.0.1; get ivan\\'s\\ filename.pdf\\\" \" someuser"
(它改用(转义)双引号,以确保su启动的shell仍然解释转义序列)
(os.system(a)有效地执行subprocess.call(["sh","-c",a]),这意味着sh看到{}(对于原始版本)。它对此执行转义序列处理,并看到一个未结束的单引号(它最初由ivan'结束),从而导致错误)。一旦解决了这个问题,sh调用su,su又会启动sh的另一个实例,进行更多的转义处理,从而导致lftp的错误(因为sh不处理单引号中的转义序列)
subprocess.call()或curl是实现这一点的更好方法-curl将需要更少的转义,可以使用curl "ftp://user:password@127.0.0.1/ivan's filename.pdf" on the command line, some more escaping is needed for going viasu-cand for python.sudoinstead ofsu`也可以减少所需的转义。。。。在
如果您想使用subprocess.call()(它删除了一层shell),可以使用subprocess.call(["su","-c","lftp -c \\\"open -u user,password ftp://127.0.0.1; get ivan\\'s\\ filename.pdf\\\"", "someuser"])
(问题是python处理一个级别的转义,而从su调用的sh -c与下一层。。。这会导致一个相当难看的命令…(不同的引号可能会稍微减少…)
使用r""可以省去python级别的转义处理:(只需要shell级转义符)(使用三重引号允许在字符串中使用引号)subprocess.call(["su","-c",r"""lftp -c \"open -u user,password ftp://127.0.0.1; get ivan\'s\ filename.pdf\"""", "someuser"])
添加空格可以剥离shell转义符,因为lftp似乎不需要空格和单引号的转义文件名。在subprocess.call(["su","-c",r"""lftp -c "open -u user,password ftp://127.0.0.1; get ivan's filename.pdf" """, "someuser"])
这导致最终的lftpARGV是["lftp","-c","open -u user,password ftp://127.0.0.1; get ivan's filename.pdf"]
而不是curl(由于涉及su,它仍然是糟糕的):subprocess.call(["su","-c",r"""curl "ftp://user:password@127.0.0.1/ivan's filename.pdf" """, "someuser"])