【发布时间】:2014-06-26 07:42:46
【问题描述】:
我正在尝试通过 SSH 执行命令,但另一端的 bash 认为它没有正确转义。
这里,self._client 是一个 paramiko.SSHClient 对象; args 是参数列表,即要执行的命令。
def run(self, args, stdin=None, capture_stdout=False):
"""Runs a command.
On success, returns the output, if requested, or None.
On failure, raises CommandError, with stderr and, if captured, stdout,
as well as the exit code.
"""
command = ' '.join(_shell_escape(arg) for arg in args)
print('About to run command:\n {}'.format(command))
print('About to run command:\n {!r}'.format(command))
channel = self._client.get_transport().open_session()
channel.exec_command(command)
_shell_escape:
_SHELL_SAFE = _re.compile(r'^[-A-Za-z0-9_./]+$')
def _shell_escape(s):
if _SHELL_SAFE.match(s):
return s
return '\'{}\''.format(s.replace('\'', '\'\\\'\''))
我试图通过这个运行一些 Python。在stderr,我回来了:
bash: -c: line 5: unexpected EOF while looking for matching `''
bash: -c: line 6: syntax error: unexpected end of file
两个打印语句的输出:
About to run command:
python -c 'import os, sys
path = sys.argv[1]
if sys.version_info.major == 2:
path = path.decode('\''utf-8'\'')
entries = os.listdir(path)
out = b'\'''\''.join(e.encode('\''utf-8'\'') + b'\'''\'' for e in entries)
sys.stdout.write(out)
' .
About to run command:
"python -c 'import os, sys\npath = sys.argv[1]\nif sys.version_info.major == 2:\n path = path.decode('\\''utf-8'\\'')\nentries = os.listdir(path)\nout = b'\\'''\\''.join(e.encode('\\''utf-8'\\'') + b'\\''\x00'\\'' for e in entries)\nsys.stdout.write(out)\n' ."
如果我复制并粘贴command 的输出并将其粘贴到bash 中,它就会执行,所以它确实似乎被正确转义了。我目前的理解是,SSH 在另一端将接受命令并运行 [my_shell, '-c', command]。
为什么bash 在该命令上出错?
【问题讨论】:
-
您是否考虑过使用
shlex.quote()(Python 3.x) 或pipes.quote()(Python 2.x) 而不是自己滚动? -
(不是说你做错了,我还没有仔细查看你的代码。但在处理转义和引用自己之前,我可能会先尝试一下)。
-
很好的问题,但考虑添加一个净化版本的命令,你复制(ied)并粘贴(d)
command的输出,然后将其粘贴(d)到bash,它执行'。祝你好运。 -
@shellter:我不确定你要什么。我复制/粘贴到 bash 中的是问题。 (“即将运行命令”下的位,即
command的输出。) -
@LukasGraf:这个功能非常相似。我会补充一点,是的。 (我给了它一个快速测试,可悲的是,它并没有修复错误。)