如何在Bash中向外部Java程序传递交互式输入参数
自动化交互式Java程序的参数传递问题
问题背景
我需要自动化一个需要用户输入两个参数的外部Java程序,参数值已经存在shell变量中,但无法直接传递给程序。目前只能通过手动复制粘贴参数的方式让程序正常运行,但这不符合自动化需求。
当前手动操作方案
printf "param-1: \"%s\"\n" "$param1" printf "param-2: \"%s\"\n" "$param2" printf "请在程序提示时复制粘贴上述值" result=$(java -jar external-app.jar decrypt -keyFormat b64) printf "result: \"%s\"\n"
尝试过的无效方法
# 管道传参,触发空指针异常 ( echo "$param1"; echo "$param2" ) | java -jar external-app.jar decrypt # 语法错误,缺少管道符号 ( echo "$param1"; echo "$param2" ) java -jar external-app.jar decrypt # 重定向写法错误,< 后不能直接接命令 java -jar external-app.jar decrypt < echo "$param1" # 错误地将变量值当作文件名 java -jar external-app.jar decrypt < "$param1"
更新信息
程序正常运行的交互式示例
$ java -jar external-app.jar decrypt encryptionKey: xxx value: yyy
尝试1:管道传参的错误输出
( echo "aaaa"; echo "bbbb" ) | java -jar external-app.jar decrypt encryptionKey: value: Exception in thread "main" java.lang.NullPointerException
尝试2:错误重定向的错误输出
$ java -jar external-app.jar decrypt < echo "aaa" bash: echo: No such file or directory
尝试3:临时文件后台写入的错误输出
$ echo "aaa" > temp.out & echo "bbb" >> temp.out & java -jar external-app.jar decrypt < temp.out [1] 13350 [2] 13351 encryptionKey: value: Exception in thread "main" Failed to obtain encryption key from the passed input Caused by: org.apache.commons.codec.DecoderException: Odd number of characters.
可行解决方案
方法1:使用expect模拟交互式输入
expect是专门用于自动化交互式程序的工具,能精准匹配提示符并发送输入:
- 编写expect脚本(保存为
auto_decrypt.exp):
#!/usr/bin/expect set param1 [lindex $argv 0] set param2 [lindex $argv 1] # 启动Java程序 spawn java -jar external-app.jar decrypt -keyFormat b64 # 匹配"encryptionKey:"提示符后发送第一个参数 expect "encryptionKey:" send "$param1\r" # 匹配"value:"提示符后发送第二个参数 expect "value:" send "$param2\r" # 等待程序执行完成并获取输出 expect eof set result [exp_output] puts "result: $result"
- 给脚本添加执行权限:
chmod +x auto_decrypt.exp
- 在shell中传入变量调用:
./auto_decrypt.exp "$param1" "$param2"
方法2:用script模拟终端环境
如果无法安装expect,可以用script命令创建伪终端,让Java程序认为处于交互式环境(解决System.console()返回null的问题):
script -q -c 'java -jar external-app.jar decrypt -keyFormat b64' /dev/null <<EOF $param1 $param2 EOF
-q参数用于静默输出,/dev/null指定日志输出到空设备,避免生成多余日志文件。
失败原因分析
- 空指针异常:Java程序大概率使用
System.console()读取输入,而管道/重定向属于非交互式环境,System.console()会返回null,调用其方法时触发NPE。 - 重定向语法错误:尝试2中
<后面必须接文件路径,不能直接接命令,正确写法应为java ... < <(echo "aaa")或使用管道。 - 临时文件写入时序问题:尝试3中后台写入文件,Java程序可能在文件未写完时就读取,导致输入不完整;同时同样存在非交互式环境的问题。
内容的提问来源于stack exchange,提问作者zappee
相关产品推荐
相关产品推荐

