如果您打印测试字符串,您会注意到它的结果如下:
su -c "lftp -c 'open -u user,password ftp://127.0.0.1; get ivan's\ filename.pdf' " someuser
问题在于您需要转义用于转义单引号的斜杠,以防止Python将其解释为字符。
command = "su -c \"lftp -c 'open -u user,password ftp://127.0.0.1; get ivan\\'s\\ filename.pdf' \" someuser"
当你使用反斜杠时,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
看到su -c“lftp -c'open -u user,password ftp://127.0.0.1; get ivan's\ filename.pdf'” someuser
(对于原始代码)。 它会对此进行转义序列处理,并看到未关闭的单引号(最初由ivan'
关闭),从而导致错误。 修复后,sh
调用su,su又启动另一个实例sh
进行更多的转义处理,从而导致lftp的错误(因为sh
不处理单引号中的转义序列)
subprocess.call()
或curl
是更好的实现方式 - curl
需要更少的转义,您可以在命令行上使用curl“ftp://user:password@127.0.0.1/ivan's filename.pdf”
,通过su -c
和python需要更多的转义。使用sudo
而不是su
也需要更少的转义....
如果要使用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"])
这将导致最终的
lftp
ARGV。
["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"])
subprocess.call()
函数,将你的单独参数作为一个列表传递,无需加任何引号 - Python将为您正确转义您的shell。 - zwercurl
而不是lftp
... 你可以通过pycURL或调用命令来实现。 - Gert van den Bergsu -c
,这会导致由su
启动的shell进行不可避免的shell转义处理。 - Gert van den Bergsu
命令?脚本是以普通用户还是以 root 用户运行?获取当前用户的文件,然后移动并更改所有权可能更加优雅... - Gert van den Berg