Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
bash命令在tomcat/java Runtime.getRuntime.exec()中失败,但可以从命令行运行_Java_Linux_Bash_Shell_Tomcat - Fatal编程技术网

bash命令在tomcat/java Runtime.getRuntime.exec()中失败,但可以从命令行运行

bash命令在tomcat/java Runtime.getRuntime.exec()中失败,但可以从命令行运行,java,linux,bash,shell,tomcat,Java,Linux,Bash,Shell,Tomcat,我有一个TomcatWebApp,它在shell中运行一个进程,因为java中没有几个实用程序此代码在其他机器上运行良好,但在我的公共服务器上有一个神秘的问题 String[] textAnalysisPipeline = { "/bin/sh", "-c", "/bin/cat " + inputfileLoc + " | tee /tmp/debug1 | " + loadJar + " " + jarOptLookupLoc + " " + optHfstL

我有一个TomcatWebApp,它在shell中运行一个进程,因为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/
不是实际的路径)

如果我从日志中复制这个管道,并从bash命令行运行它,我将得到所需的输出,一直到管道的末尾。但是,当tomcat服务器运行该命令时,它会生成一个空文件。调试文件
debug1
debug2
与预期一样,但
debug3
及其后为空,这表明管道在
cut-f 1-2
时失败(请参阅下面的更新1)

OS-Fedora 22
java-openjdk 1.8.077
tomcat-7.0.39
sh-->bash-4.3.42(1)-发布

===============================================================================
更新1:

这似乎不是
cut
的问题。我编写了一个简短的python脚本,
cut.py
,以实现与
cut-f1-2
相同的功能(从每行末尾删除
'\t0.0'

使用
cut.py
代替
cut
,我得到了同样的问题。对于服务器
debug3
和更高版本,它是空的,但是如果我将粘贴从日志复制到交互式shell,一切都会正常工作

===============================================================================
更新2:


我还编写了一个简单的bash脚本来运行管道,以便tomcat/java只运行带有一个输入/输出文件名参数的bash脚本。如果我从一个交互式shell运行脚本,它会工作,但是在tomcat中结果没有什么不同,在shell脚本中使用
cut
cut.py

您可以使用
ProcessBuilder
。使用单字符串形式的
Runtime.exec
不是一种好的样式。更好的选择是使用
ProcessBuilder
,自己分割参数,而不是依靠Java来分割参数,这是非常幼稚的

ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", /*...*/);
pb.redirectErrorStream(true);
Process p = pb.start();

这主要是一种旁白,或者是一种变通方法,但您的管道可以大大简化。可以用单个Awk脚本替换
cat
tail
cut

tee /tmp/debug1 <path/to/inputFile |
java -jar path/to/hfst-ol.jar path/to/analyser.ohfst 2>/dev/null |
tee /tmp/debug2 |
awk -F '\t' 'NR>5 { print $1 FS $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
tee/tmp/debug1/dev/null|
三通/tmp/debug2|
awk-F'\t''NR>5{print$1 FS$2}'|
三通/tmp/debug3|
/usr/local/bin/cg conv|
三通/tmp/debug4|
path/to/vislcg3-g path/to/grammar.rlx|
tee/tmp/debug5>path/to/outputFile

脚本和(有时尤其是)crontab中有一种模式,用于脚本的
$PATH
变量与用于交互式shell的变量不同。这导致命令在一个环境中神秘地失败,但在其他环境中工作


我强烈建议将您正在使用的所有工具的完整路径嵌入到您正在构建的调用中。运行该进程时,
cut
可能位于未拾取的目录中。输入完整路径,如
/usr/bin/cut
,将确保两件事:没有人会在您的路径中潜入意外版本的
cut
,而且,如果您所在的环境中没有
/usr/bin
$PATH

中,这也无关紧要。当您从日志中复制命令并从命令行运行它时,您是否以与运行Tomcat的用户相同的用户身份执行它

Tomcat用户可能没有足够的权限读取命令中的一个文件

在我的Ubuntu系统上,默认的tomcat7用户称为tomcat7。可以使用以下命令以其他用户的身份运行命令:

sudo -u tomcat7 /bin/sh -c 'myCommand'

来源:。

默认情况下,在大多数系统上,Tomcat与您的用户没有相同的环境。例如,它不会运行.bashrc.profile或登录脚本中的任何内容,因此用户shell环境中设置的所有变量都是不同的

您可以通过将
env
命令与两个用户(您的用户)进行比较,并让java程序调用它来检查这一点,例如:

String[] textAnalysisPipeline = {"/bin/sh","-c","/usr/bin/env > /tmp/env.txt"}; //or wherever the 'env' command is in your system
Process process = Runtime.getRuntime().exec(textAnalysisPipeline);
...
并将
/tmp/env.txt
的内容与用户执行的
env
进行比较。。。他们可能非常不同

查找以下变量:

  • 路径
  • 类路径
  • 爪哇之家酒店
我以前也有过同样的问题。我建议采取以下办法:

  • 对所有内容使用绝对路径,包括对“java”、“tee”、“tail”和libs(jar文件)的调用。。。你有你的指挥权

  • 更改Tomcat运行时的环境配置,以访问您在命令中调用的所有应用程序(通常通过调用配置所有必要的
    PATH
    变量的脚本(不要忘记jar文件中的
    JAVA\u HOME
    CLASSPATH
    ).检查Startup.sh和Catalina.sh,寻找合适的位置放置您的物品

  • 更改命令以将错误输出重定向到系统中某个应用程序可以写入的日志文件(通常
    /tmp/exec.log
    ),而不是消息中的
    /dev/null
    )因此,您可以确定shell执行问题。我打赌它将类似于:
    sh:***:command not found
    错误:无法访问jarfile
    或应用程序无法定位对象的某些消息,因此您可以确定脚本中调用的应用程序不在
    路径中变量或其中没有的LIB…通常两者都有

  • 有关此项的更多信息,请检查


    希望这能有所帮助……

    我建议实际响应命令行
    sudo -u tomcat7 /bin/sh -c 'myCommand'
    
    String[] textAnalysisPipeline = {"/bin/sh","-c","/usr/bin/env > /tmp/env.txt"}; //or wherever the 'env' command is in your system
    Process process = Runtime.getRuntime().exec(textAnalysisPipeline);
    ...