我遇到了同样的问题,发现即使使用标准 irb 也可以通过键入以下命令行来重现该问题(我通过阅读 /usr/lib/hbase/bin/hbase 找到了这个命令行)。
$ java -cp \
~/.m2/repository/org/jruby/jruby-complete/1.6.5/jruby-complete-1.6.5.jar \
org.jruby.Main /usr/bin/irb
因此,根本原因不在HBase shell中,而是在JRuby中,进一步调查发现根本原因存在于JRuby 1.6.5使用的JLine中。
首先,我创建了 ~/.jlinebindings.properties 文件并将“Rubout:backward-delete-char”放在那里,希望退格键会“删除光标后面的一个字符”,但它不起作用。更糟糕的是,.jlinebindings.properties 文件的存在清除了其他键绑定(例如箭头键的绑定),所以我删除了 .jlinebindings.properties。我尝试将键绑定设置添加到 ~/.jline.rc 和 ~/.inputrc,但它们也不起作用。
我查看了 JLine2 源代码以进一步调查,发现最新版本的 JLine2 不支持 .jlinebindings.properties 文件。但是,支持 .jline.rc。所以,我编译了最新的 JLIne2 源代码,将键绑定到 .jline.rc 文件并指定 JLine2 库(target/jline-2.10-SNAPSHOT.jar)作为类路径的第一个元素,但它不起作用。使用新构建的 JLine2 库,JRuby 1.6.5 抛出了 IncompatibleClassChangeError。这意味着 JLine2 改变了它的 API 并破坏了向后兼容性。
接下来,我查看了 JRuby 源代码并编译如下。
# JRuby compilation requires ant
$ yum install ant
# Without this, compilation fails.
$ yum install ant-apache-regexp
$ git clone https://github.com/jruby/jruby.git
# Check the latest version
$ git tag
$ git checkout 1.7.1
$ mvn install
使用新的 JRuby 二进制文件,我再次调用了命令行。
$ java -cp \
~/.m2/repository/org/jruby/jruby-complete/1.7.1/jruby-complete-1.7.1.jar \
org.jruby.Main /usr/bin/irb
但是,它引发了 SyntaxError。
SyntaxError: file:/home/admin/.m2/repository/org/jruby/jruby-complete/1.7.1/jruby-complete-1.7.1.jar!/META-INF/jruby.home/lib/ruby/1.9/irb/lc/ja/encoding_aliases.rb:7: syntax error, unexpected kEND
end
^
eval at org/jruby/RubyKernel.java:1066
real_load at jar:file:/home/admin/.m2/repository/org/jruby/jruby-complete/1.7.1/jruby-complete-1.7.1.jar!/META-INF/jruby.home/lib/ruby/1.9/irb/locale.rb:134
load at jar:file:/home/admin/.m2/repository/org/jruby/jruby-complete/1.7.1/jruby-complete-1.7.1.jar!/META-INF/jruby.home/lib/ruby/1.9/irb/locale.rb:110
initialize at jar:file:/home/admin/.m2/repository/org/jruby/jruby-complete/1.7.1/jruby-complete-1.7.1.jar!/META-INF/jruby.home/lib/ruby/1.9/irb/locale.rb:32
init_config at jar:file:/home/admin/.m2/repository/org/jruby/jruby-complete/1.7.1/jruby-complete-1.7.1.jar!/META-INF/jruby.home/lib/ruby/1.9/irb/init.rb:114
setup at jar:file:/home/admin/.m2/repository/org/jruby/jruby-complete/1.7.1/jruby-complete-1.7.1.jar!/META-INF/jruby.home/lib/ruby/1.9/irb/init.rb:16
start at jar:file:/home/admin/.m2/repository/org/jruby/jruby-complete/1.7.1/jruby-complete-1.7.1.jar!/META-INF/jruby.home/lib/ruby/1.9/irb.rb:53
(root) at /usr/bin/irb:13
encoding_aliases.rb 中一定有问题(或者新的 JRuby 做了一些改变,破坏了向后兼容性),但我没有心思去调查它,所以添加了 LANG=C 作为解决方法。
$ LANG=C java -cp \
~/.m2/repository/org/jruby/jruby-complete/1.7.1/jruby-complete-1.7.1.jar \
org.jruby.Main /usr/bin/irb
这成功调用了 irb,我可以确认退格符按预期工作。maven/jruby-core/pom.xml 表示 JRuby 1.7.1 所指的 JLIne 版本是 2.7。
作为最后一步,我尝试通过执行以下操作让 HBase shell 使用新的 JRuby。
$ cd /usr/lib/hbase/lib
$ mv jruby-complete-1.6.5.jar{,.backup}
$ cp ~/.m2/repository/org/jruby/jruby-complete/1.7.1/jruby-complete-1.7.1.jar .
$ hbase shell
但是,HBase shell 没有启动。相反,发出了以下错误消息。
include_class is deprecated. Use java_import.
include_class is deprecated. Use java_import.
include_class is deprecated. Use java_import.
12/12/28 18:03:12 WARN conf.Configuration: hadoop.native.lib is deprecated. Instead, use io.native.lib.available
NoMethodError: undefined method `getTerminal' for Java::Jline::Terminal:Module
refresh_width at /usr/lib/hbase/bin/../bin/../lib/ruby/shell/formatter.rb:34
initialize at /usr/lib/hbase/bin/../bin/../lib/ruby/shell/formatter.rb:47
(root) at /usr/lib/hbase/bin/../bin/hirb.rb:108
这些错误消息表明在 /usr/lib/hbase/lib 下替换 jruby-complete-*.jar 并不能解决问题。
所以,我放弃了,并得出结论,没有简单的解决方法来解决这个问题。我的最终结论是,我们必须等待 HBase 专家使用新的 JRuby 更新 HBase shell 实现。