Bash不认为字符串被正确引用了吗?

时间:2014-05-08 18:32:48

标签: python bash ssh paramiko

我正在尝试通过SSH执行命令,但另一端的bash并不认为它已正确转义。

此处,self._clientparamiko.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在该命令上出错?

2 个答案:

答案 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

也许你根本不需要逃避任何事情。