【发布时间】:2016-10-13 13:16:58
【问题描述】:
我有一个在 shell 中运行进程的 tomcat webapp,因为一些实用程序在 java 中不可用。 这段代码在其他机器上完美运行,但是我的公共服务器上出现了一个神秘问题。
String[] textAnalysisPipeline = {
"/bin/sh",
"-c",
"/bin/cat " + inputfileLoc +
" | tee /tmp/debug1 | " + loadJar + " " + jarOptLookupLoc + " " + optHfstLoc +
" 2>/dev/null | " + "tail -n+5" + // get rid of the header that hfst-ol.jar produces
" | tee /tmp/debug2 | cut -f 1-2" + // get rid of the "0.0" weights
" | tee /tmp/debug3 | " + cgConvLoc +
" | tee /tmp/debug4 | " + vislcg3Loc + " -g " + vislcg3DisGrammarLoc + // disambiguate with the constraint grammar
" | tee /tmp/debug5 > " + outputfileLoc};
log.debug("Text analysis pipeline: "+textAnalysisPipeline[2]);
Process process = Runtime.getRuntime().exec(textAnalysisPipeline);
process.waitFor();
我将字符串打印到日志中,它看起来像这样:(path/to/ 不是实际路径)
/bin/cat /path/to/inputFile | tee /tmp/debug1 | java -jar /path/to/hfst-ol.jar /path/to/analyser.ohfst 2>/dev/null | tail -n+5 | tee /tmp/debug2 | cut -f 1-2 | tee /tmp/debug3 | /usr/local/bin/cg-conv | tee /tmp/debug4 | /path/to/vislcg3 -g /path/to/grammar.rlx | tee /tmp/debug5 > /path/to/outputFile
如果我从日志中复制此管道并从 bash 命令行运行它,我会一直得到所需的输出,直到管道结束。但是,当 tomcat 服务器运行该命令时,它会生成一个空文件。调试文件debug1 和debug2 符合预期,但debug3 及之后为空,这表明管道在cut -f 1-2 处失败(请参阅下面的更新1)。
操作系统 - Fedora 22
java - openjdk 1.8.0_77
tomcat - 7.0.39
sh --> bash - 4.3.42(1)-release
================================================ =================
更新 1:
这似乎不是cut 的问题。我写了一个简短的python脚本cut.py来实现与cut -f 1-2相同的功能(从每一行的末尾删除'\t0.0')
import re, sys
myRE = re.compile( r'\s+0\.0$' )
for line in sys.stdin :
sys.stdout.write( myRE.sub( '', line ) )
使用cut.py 代替cut,我遇到了同样的问题。服务器 debug3 及以后是空的,但如果我从日志复制粘贴到交互式 shell,一切正常。
================================================ =================
更新 2:
我还编写了一个简单的 bash 脚本来运行管道,以便 tomcat/java 只运行带有一个输入/输出文件名参数的 bash 脚本。如果我从交互式 shell 运行脚本,它可以工作,但结果在 tomcat 中没有什么不同,在 shell 脚本中使用 cut 或 cut.py。
【问题讨论】:
-
我建议实际上回显从字符串连接构建的命令行。验证打印的确切命令在终端中是否有效。很多时候,我们在通过字符串 concat 生成命令行时会遗漏一些引号。问这个,因为没有逻辑原因
cut应该在脚本中失败并通过命令行传递。 -
@anishsane 这实际上是我所做的。它将字符串打印到日志中,
log.debug("Text analysis pipeline: "+textAnalysisPipeline[2]);,然后我将其复制粘贴到命令行。 -
您是否尝试过直接从 bash 命令行运行命令
/bin/sh -c "/bin/cat ..."(而不仅仅是/bin/cat ...)? -
对于调试,使用
"/bin/sh", "-xc", ...可能会产生有用的提示。 -
waitFor 返回一个整数,它是您的进程的退出值
标签: java linux bash shell tomcat