我正在使用Python代码在Linux(Cloudera)计算机上使用SSH运行Hadoop程序。
我在将java文件编译为类文件时遇到了一些麻烦。当我执行命令时:
来自Linux终端的javac -cp /usr/lib/hadoop/*:/usr/lib/hadoop/client-0.20/* remote_hadoop/javasrc/*
所有文件都已成功编译。
当我通过我的Python SSH客户端执行相同的命令时,我收到一个“无效标志”错误:
spur.results.RunProcessError:返回代码:2 输出:b'' stderr输出:b'javac:invalid flag:remote_hadoop / javasrc \ nUsage:javac \ nuse -help,列出可能的选项\ n'
python代码:
list_of_commands = ["javac", "-cp", r"/usr/lib/hadoop/*:/usr/lib/hadoop/client-0.20/*", input_folder + r"/*"]
print ' '.join(list_of_commands)
self.shell.run(list_of_commands)
命令正在正确呈现,因为要打印的内容是javac -cp /usr/lib/hadoop/*:/usr/lib/hadoop/client-0.20/* remote_hadoop/javasrc/*
。
更新:这很奇怪。我可以通过ssh一次编译一个文件,但不是全部。似乎在ssh上发生了“*”的事情。
答案 0 :(得分:1)
您传递的是参数列表,而不是命令列表。它甚至不是准确的参数列表。
如果你的底层工具需要一个参数列表,那么传递:
['sh', '-c', 'javac -cp /usr/lib/hadoop/*:/usr/lib/hadoop/client-0.20/* remote_hadoop/javasrc/*']
如果需要命令列表:
['javac -cp /usr/lib/hadoop/*:/usr/lib/hadoop/client-0.20/* remote_hadoop/javasrc/*']
如果它还需要其他东西 - 请阅读文档并确定其中的内容!
请注意,SSH在运行任意命令时没有提供传递文字argv数组的方法;相反,它期望 - 在协议级别 - 一个准备好由远程shell解析的字符串。如果您的self.shell.run
代码在加入给定的参数列表之前正在进行shell引用,那么它将传递最后一个参数作为文字字符串 remote_hadoop/javasrc/*
- 不扩展将它作为shell的文件名列表。
使用sh -c
表单强制远程shell在其末尾执行扩展,假设已经以不执行远程扩展的形式向其提供内容。
答案 1 :(得分:1)
问题是spur
将命令列表构建为命令字符串的方式。它接受每个命令令牌并将其用单引号括起来(["ls", "*.txt"])
变为'ls' '*.txt'
)。引号内没有*
的shell扩展,因此该命令不起作用。
你可以在323行的ssh.py中看到问题:
def escape_sh(value):
return "'" + value.replace("'", "'\\''") + "'"
我不使用spur,但看起来它只是不允许你做这样的事情。像“马刺”这样的“简化器”的问题在于,如果它们以您不想要的方式简化,则无法使用它们。