Java执行器未转换XML传入的date命令,如何仅通过XML生成时间戳文件名?
我来帮你搞定这个问题——你遇到的核心痛点是:Java程序直接拼接XML里的参数生成命令,没有通过Shell解析,导致date +%Y%m%d_%H%M%S被当作普通文本,没法转换成实际的时间戳文件名。既然不能改Java代码,咱们可以从以下几个方向入手:
方案1:用Shell预处理XML(最靠谱)
既然Java不认识Shell语法,那咱们就在启动Java之前,先手动生成时间戳,把XML里的占位符替换成真实时间。步骤很简单:
- 先修改XML里的
LogFilename,把时间戳部分换成一个占位符,比如{{TIMESTAMP}}:
<Action id="Sendbase2Job" timeout="600" AfpDir="/data/afp/" ResourceDir="/data/afp/" LogFilename="/data/reports/{{TIMESTAMP}}_myresources.txt" JobName="myresources.afp" /> <Action id="JobMonitor" ProcessingInterval="10" pendTimeout="120" processTimeout="2200" />
- 写个启动脚本,先生成时间戳,替换XML里的占位符,再启动Java:
#!/bin/bash # 生成符合要求的时间戳 TIMESTAMP=$(date +%Y%m%d_%H%M%S) # 替换XML里的占位符(把config.xml换成你的实际XML文件名) sed -i "s/{{TIMESTAMP}}/$TIMESTAMP/g" config.xml # 启动你的Java程序(换成你实际的Java启动命令) java -jar your-app.jar config.xml
这种方法完全绕开了Java对Shell语法的支持问题,预处理阶段就把文件名生成好了,Java拿到的直接是最终路径,绝对管用。
方案2:让Java通过Shell执行命令(看Java程序的逻辑)
如果你的Java程序是直接用ProcessBuilder调用mybase,而不是通过Shell执行,那反引号肯定不会被解析。你可以试试让Java拼接后的命令通过sh -c来执行,这样Shell就会处理时间戳了。
具体来说,要让最终的命令变成:
sh -c '/data/bin/mybase -ip 192.xxx.xxx.xxx -f myresources.afp -ad /data/afp -rd /data/afp -o /data/reports/`date +%Y%m%d_%H%M%S`_myresources.txt'
如果LogFilename是直接作为-o的参数,你可以试试把XML里的LogFilename改成:
LogFilename="\`date +%Y%m%d_%H%M%S\`_myresources.txt"
不过这个方法要看Java程序怎么拼接命令,如果它是把参数作为独立的命令行参数传给mybase,而不是拼成字符串交给Shell,那这个方法就没用。
方案3:试试$()替代反引号(碰运气)
有些环境里,$()比反引号的兼容性更好,你可以把XML里的LogFilename改成:
LogFilename="/data/reports/$(date +%Y%m%d_%H%M%S)_myresources.txt"
同样,这也需要Java通过Shell执行命令才能生效,如果Java直接传参数给mybase,还是白搭。
总的来说,方案1是最稳妥的,它不依赖Java程序的内部实现,完全通过预处理XML解决问题,符合你“只能调整XML输入”的限制(严格来说是调整XML加启动脚本,但不用改Java代码)。
内容的提问来源于stack exchange,提问作者corny

