我正在尝试通过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
在该命令上出错?
答案 0 :(得分:0)
输入包含一个嵌入的空字符,bash似乎被视为字符串的结尾。 (我不确定是否有任何方式无法做到!)。这在我的问题中可见,我输出command
:
About to run command:
"python -c 'import os, sys [SNIP…] + b'\\''\x00'\\'' for [SNIP…]"
' sa repr
输出,但请注意x
中\x00
之前的单斜杠:它是实现\x00
的实际_LS_CODE = """\
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'\x00' for e in entries)
sys.stdout.write(out)
"""
。我的原始代码将此Python嵌入为片段,我没有包含(我不相信它是相关的):
"""
在这里,Python \
仍在处理r"""
作为转义字符。我需要加倍,或查看原始字符串({{1}})
答案 1 :(得分:-1)
您还需要转义换行符。更好的选择是将程序文本放在这里的文档中。
输出"关于运行命令:"看起来像
python -c << EOF
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)
.
EOF
也许你根本不需要逃避任何事情。