如何摆脱命令中多个单引号引起的语法错误
How to get rid of syntax error that arises with multiple single quotation marks in the command
我有一个命令来获取某个 ubuntu 用户的最后登录时间,我需要将输出存储在其他地方所以当我 运行 在我的 python脚本,我得到一个语法错误,但是当我 ssh
进入远程服务器并执行命令时,没有问题。
# last logged in time of ubuntu user
user_login = os.popen('ssh -i /Users/abcxyz/keypair ubuntu@1#.###.##.# lastlog -u 'ubuntu' | grep -v Latest | awk '{="";="";="";print [=10=] }'').read()
print(user_output)
当我在我的终端中 运行 时,它工作正常并给我输出:
ssh -i /Users/abcxyz/keypair ubuntu@1#.###.##.# lastlog -u 'ubuntu' | grep -v Latest | awk '{="";="";="";print [=11=] }'
输出:Sat Nov 17 16:32:10 +0000 2018
因为你的字符串里面既有单引号也有双引号,我会用三重引号将整个字符串引号
user_login = os.popen("""ssh -i /Users/abcxyz/keypair ubuntu@1#.###.##.# lastlog -u 'ubuntu' | grep -v Latest | awk '{="";="";="";print [=10=] }'""").read()
否则如所写,您的字符串中的一些单引号将在中间终止全长字符串
理想情况下,您应该以一种完全不会让您遇到问题的方式来构造它——也就是说,让 Python 解释器完成生成正确 shell 引用字符串的工作(然后重新引用它以安全地传递给 ssh)。
try:
from shlex import quote # Python 3
except ImportError:
from pipes import quote # Python 2
import subprocess
# specify your commands the way they're actually seen by the operating system -- with
# lists of strings as argument vectors.
rmt_pipeline = [[ 'lastlog', '-u', 'ubuntu' ],
[ 'grep', '-v', 'Latest' ],
[ 'awk', '{="";="";="";print [=10=] }' ]]
# ...then, let shlex.quote() or pipes.quote() determine how to make those lists be valid
# shell syntax, as expected by the remote copy of sh -c '...' invoked by ssh
rmt_pipeline_str = ' | '.join(' '.join(quote(word) for word in piece)
for piece in rmt_pipeline)
# ...finally, generate the argument vector for our local copy of ssh...
ssh_cmd = [ 'ssh', '-i', '/Users/abcxyz/keypair', rmt_pipeline_str ]
# and actually invoke it.
user_output = subprocess.Popen(ssh_cmd, stdout=subprocess.PIPE).stdout
如果您真的想要使用os.popen()
——您不应该使用Python文档explicitly suggests using subprocess
instead——您可以将最后一行替换为:
ssh_cmd_str = ' '.join(quote(word) for word in ssh_cmd)
user_output = os.popen(ssh_cmd_str)
在 UNIX 系列操作系统上,所有程序的执行都是通过 execve()
系统调用进行的,它会传递一个 C 字符串列表。自己指定该列表可以让您最大程度地控制执行方式,并防止 shell 注入攻击(授权用户向您 运行 的其中一个程序提供参数的用户传递的内容是被 shell 解释为语法而不是数据,因此运行完全不同的程序或间接操作)。
我有一个命令来获取某个 ubuntu 用户的最后登录时间,我需要将输出存储在其他地方所以当我 运行 在我的 python脚本,我得到一个语法错误,但是当我 ssh
进入远程服务器并执行命令时,没有问题。
# last logged in time of ubuntu user
user_login = os.popen('ssh -i /Users/abcxyz/keypair ubuntu@1#.###.##.# lastlog -u 'ubuntu' | grep -v Latest | awk '{="";="";="";print [=10=] }'').read()
print(user_output)
当我在我的终端中 运行 时,它工作正常并给我输出:
ssh -i /Users/abcxyz/keypair ubuntu@1#.###.##.# lastlog -u 'ubuntu' | grep -v Latest | awk '{="";="";="";print [=11=] }'
输出:Sat Nov 17 16:32:10 +0000 2018
因为你的字符串里面既有单引号也有双引号,我会用三重引号将整个字符串引号
user_login = os.popen("""ssh -i /Users/abcxyz/keypair ubuntu@1#.###.##.# lastlog -u 'ubuntu' | grep -v Latest | awk '{="";="";="";print [=10=] }'""").read()
否则如所写,您的字符串中的一些单引号将在中间终止全长字符串
理想情况下,您应该以一种完全不会让您遇到问题的方式来构造它——也就是说,让 Python 解释器完成生成正确 shell 引用字符串的工作(然后重新引用它以安全地传递给 ssh)。
try:
from shlex import quote # Python 3
except ImportError:
from pipes import quote # Python 2
import subprocess
# specify your commands the way they're actually seen by the operating system -- with
# lists of strings as argument vectors.
rmt_pipeline = [[ 'lastlog', '-u', 'ubuntu' ],
[ 'grep', '-v', 'Latest' ],
[ 'awk', '{="";="";="";print [=10=] }' ]]
# ...then, let shlex.quote() or pipes.quote() determine how to make those lists be valid
# shell syntax, as expected by the remote copy of sh -c '...' invoked by ssh
rmt_pipeline_str = ' | '.join(' '.join(quote(word) for word in piece)
for piece in rmt_pipeline)
# ...finally, generate the argument vector for our local copy of ssh...
ssh_cmd = [ 'ssh', '-i', '/Users/abcxyz/keypair', rmt_pipeline_str ]
# and actually invoke it.
user_output = subprocess.Popen(ssh_cmd, stdout=subprocess.PIPE).stdout
如果您真的想要使用os.popen()
——您不应该使用Python文档explicitly suggests using subprocess
instead——您可以将最后一行替换为:
ssh_cmd_str = ' '.join(quote(word) for word in ssh_cmd)
user_output = os.popen(ssh_cmd_str)
在 UNIX 系列操作系统上,所有程序的执行都是通过 execve()
系统调用进行的,它会传递一个 C 字符串列表。自己指定该列表可以让您最大程度地控制执行方式,并防止 shell 注入攻击(授权用户向您 运行 的其中一个程序提供参数的用户传递的内容是被 shell 解释为语法而不是数据,因此运行完全不同的程序或间接操作)。