【发布时间】:2011-03-29 10:51:34
【问题描述】:
我正在尝试从我的 java 代码中执行一个脚本,如下所示:
Process p = Runtime.getRuntime().exec(cmdarray, envp, dir); // cmdarray is a String array
// consisting details of the script and its arguments
final Thread err = new Thread(...); // Start reading error stream
err.start();
final Thread out = new Thread(...); // Start reading output stream
out.start();
p.waitFor();
// Close resources
脚本的执行结束了(它的pid没有了),但是java卡在waitFor()进程的方法上!。
是的,我正在 2 个单独的线程中读取输出和错误流。是的,他们最后会加入(在waitFor() 之后)。
该脚本基本上会安装几个 RPM(比如 10 个左右)并对其进行配置。所以脚本运行了 60 多秒。
它看起来类似于以下内容:
#!/bin/sh
#exec 3>&1 >/var/log/some_log 2>&1
# If the above line is uncommented, Java recognizes that the
# process is over and terminates fine.
tar xzf a-package-having-rpms.tar.gz
cd unpacked-folder
(sh installer-script.sh) #This installs 10 odd rpms in a subshell and configures them
cd ..
rm -rf unpacked-folder
exit 0
令人震惊的是,如果我在脚本中(在顶部)添加以下行,Java 会理解脚本已经结束,它会完美地终止进程。
exec 3>&1 > /var/log/some_log 2>&1
作为记录,脚本不会生成任何输出。零字符!所以把 exec 语句放在那里是没有意义的!
但是,神奇的是,将 exec 语句放入脚本中可以使 java 工作! 为什么??
如何避免脚本中不合逻辑的 exec 语句?
如果您对 installer-script.sh 的外观感兴趣,那么:
#!/bin/sh
exec 3>&1 >>/var/log/another-log.log 2>&1
INSDIR=$PWD
RPMSDIR=$INSDIR/RPMS
cd $RPMSDIR
#
rpm -i java-3.7.5-1.x86_64.rpm
rpm -i --force perl-3.7.5-1.x86_64.rpm
rpm -i --nodeps mysql-libs-5.0.51a-1.vs.i386.rpm
rpm -i --nodeps mysql-5.0.51a-1.vs.i386.rpm
rpm -i --nodeps mysql-server-5.0.51a-1.vs.i386.rpm
rpm -i --nodeps perl-DBD-MySQL-3.0007-2.el5.i386.rpm
rpm -i --nodeps perl-XML-Parser-2.34-6.1.2.2.1.i386.rpm
.
.
.
现在,为什么 Java 需要在第一个脚本中执行 exec 命令才能知道进程已经结束? 我怎样才能避免那个执行?,尤其是。因为第一个脚本不会产生任何输出。
屏住呼吸等待答案!
【问题讨论】:
-
尝试制作一个简短的完整示例程序来展示您的问题。如果人们看到(甚至可能尝试运行)代码,他们可能会发现错误。
-
脚本真的很短吗?也许脚本终止得太快了?你能发布一些脚本的代码吗?你能发布运行脚本的Java代码吗?你能把它简化为一个带有 main 的简单可执行类吗?
-
按照@Gilles 和@Romain 的建议编辑了描述。期待最好的!