Apache Commons Exec - 有时一个Thread无法在Linux中打开本地文件

Leo*_*Leo 9 java linux multithreading apache-commons-exec

警告 - 原因不是缺少文件 - 所有线程都在呼叫相同的脚本文件

我开始5-6个线程,在Red Hat框中调用本地脚本.

我注意到有时,我收到以下错误消息

couldn't read file "/home/leo/myScript.exp": no such file or directory
Run Code Online (Sandbox Code Playgroud)

显然,所有进程都在执行脚本,因此它似乎与[1]操作系统有关,对可以运行脚本或访问文件进行读取的同时进程有一些限制,或者[2] Java正在尝试执行某些操作一些未准备好的流(我假设commons-exec会为我处理这个)

这是代码

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CommandLine commandline = CommandLine.parse("/home/leo/myScript.exp");
DefaultExecutor exec = new DefaultExecutor();
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
exec.setStreamHandler(streamHandler);
try {
   exec.execute(commandline); <<< error happens here
}catch(IOException io) {
   throw new Exception("");
}
Run Code Online (Sandbox Code Playgroud)

如果错误是[1],那么我想知道如何在linux OS中放宽这个限制

如果错误是[2],那么我想知道如何告诉commons-exec等待资源准备好(在最坏的情况下我只是添加一些重试,但我认为这不是很优雅)

如果错误是别的,至少知道原因将足以让我找到一些解决方案.

更新 - 3月15日

嗯,这就是事情.

该脚本是一个期望脚本,它使用库来调用Java类.

我注意到的一件事是脚本运行良好,直到它调用一个创建数据库连接的java方法.

因为线程数量很少(3~5)我不认为这是数据库中的问题.相反,在我看来,在调用java代码时和/或在java代码创建数据库连接时阻止调用脚本.

我仍然试图得到确切的异常,但是期望脚本看起来像这样(有点)

#!/opt/tclblend/bin/expect -f
set edfDir "/usr/local/nssa/bin/edf";
set env(LD_LIBRARY_PATH) "/opt/tclblend/lib/tcljava1.4.1"; # for tclBlend

## always use absolute paths
set env(TCL_CLASSPATH) "/home/leoks/EclipseIndigo/workspace2/xyzJavaWrapper/bin";
set env(CLASSPATH) {/home/leoks/EclipseIndigo/workspace2/xyzTomEE/lib/commons-logging-1.1.1.jar:/home/leoks/EclipseIndigo/workspace2/xyzConfiguration/lib/commons-configuration-1.9.jar:/home/leoks/EclipseIndigo/workspace2/xyzConfiguration/lib/commons-lang-2.4.jar:/home/leoks/EclipseIndigo/workspace2/xyz/3rdPartyJDBCJars/ojdbc6.jar:/home/leoks/EclipseIndigo/workspace2/xyzJavaWrapper/lib/commons-dbutils-1.5.jar:/home/leoks/EclipseIndigo/workspace2/xyzJavaWrapper/tcl/tcllib/xyzConfiguration.jar};

source $edfDir/lib/statics.tcl;
source $edfDir/lib/acclib.tcl; 

package require java

java::import com.abc.xyz.legacydriver.TCLDriverWrapper
java::import com.abc.xyz.legacydriver.LegacyDriverTaskInputData
java::import com.abc.xyz.legacydriver.LegacyDriverTaskEnum

set ticket  [ lindex $argv 0 ];
set inputData [ java::call com.abc.xyz.legacydriver.TCLDriverWrapper pullNextInputData $ticket ]
Run Code Online (Sandbox Code Playgroud)

其中pullNextInputData看起来像

public static LegacyDriverTaskInputData pullNextInputData(String token) throws Exception {

    try {
        return pullNextInputDataImpl(token);
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    }
}

private static LegacyDriverTaskInputData pullNextInputDataImpl(String token) throws Exception {
    Connection conn = null;
    try{
        conn = new TCLDriverWrapper().getConnection();
        QueryRunner run = new QueryRunner();
        ResultSetHandler<LegacyDriverTaskInputData> rsh = new BeanHandler<LegacyDriverTaskInputData>(LegacyDriverTaskInputData.class);
        LegacyDriverTaskInputData inputData = run.query(conn,"select * from LegacyDriverTask where id = ?",rsh,Long.valueOf(token));
        return inputData;
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
        throw e;
    } catch (SQLException e) {
        e.printStackTrace();
        throw e;
    } finally {
        DbUtils.close(conn);
    }
}
Run Code Online (Sandbox Code Playgroud)

和getConnection()只是一个常规的驱动实例化代码(它使用apache dbutils)

private Connection getConnectionImpl() throws Exception{    
    Class.forName("driver name");
    Properties props = new Properties();
    props.put("user", UtilConf.getProperty("javawrapper.user"));
    props.put("password", UtilConf.getProperty("javawrapper.password"));
    return DriverManager.getConnection(UtilConf.getProperty("javawrapper.jdbc"), props);
}
Run Code Online (Sandbox Code Playgroud)

一旦我得到一个堆栈跟踪,我会把它放在这里

更新 - 3月16日

堆栈跟踪并没有多说:-(

2016-03-17 01:49:10,034 INFO   [QProcessor] Threads started (ok=0 nok=0 wait=0) org.apache.commons.exec.ExecuteException: Process exited with an error: 1 (Exit value: 1)
at org.apache.commons.exec.DefaultExecutor.executeInternal(DefaultExecutor.java:404)
at org.apache.commons.exec.DefaultExecutor.execute(DefaultExecutor.java:166)
at org.apache.commons.exec.DefaultExecutor.execute(DefaultExecutor.java:153)
at com.ericsson.xyz.tomee.q.QWorker.onMessageImpl(QWorker.java:776)
at com.ericsson.xyz.tomee.q.QWorker.onMessage(QWorker.java:303)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:182)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:164)
at org.apache.openejb.monitoring.StatsInterceptor.record(StatsInterceptor.java:180)
at org.apache.openejb.monitoring.StatsInterceptor.invoke(StatsInterceptor.java:99)
at sun.reflect.GeneratedMethodAccessor106.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:182)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:164)
at org.apache.openejb.core.interceptor.InterceptorStack.invoke(InterceptorStack.java:80)
at org.apache.openejb.core.stateless.StatelessContainer._invoke(StatelessContainer.java:212)
at org.apache.openejb.core.stateless.StatelessContainer.invoke(StatelessContainer.java:181)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.synchronizedBusinessMethod(EjbObjectProxyHandler.java:268)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler$1.call(EjbObjectProxyHandler.java:253)
at org.apache.openejb.async.AsynchronousPool$AsynchronousCall.call(AsynchronousPool.java:110)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Run Code Online (Sandbox Code Playgroud)

Leo*_*Leo 1

我要感谢所有在此案中提供帮助的人。

我想删除这个问题,但因为我已经悬赏了它,所以我不能。(也许当赏金到期时,如果允许的话,我会这样做)

我终于找到了一种没有问题的方法,它似乎与应用程序为线程分配资源的方式有关,因此鉴于问题中提供的信息,我认为不可能找出问题所在根本原因。

无论如何,我会尝试在这里描述发生的事情。

在此输入图像描述 (点击放大)

问题是我注意到在(5)(6)(7)中。但原因在于(3)。

为 @Asynchronous 方法提供服务的线程池的 TomEE 配置的线程数少于必要的线程数(我的应用程序未使用默认值),因此似乎某些资源正在匮乏。

另外,错误消息似乎有一些我尚未识别的错误,因此在这种情况下,即使错误消息也可能无效。

因为这个问题没有解决其所需的所有变量,所以我在这里提供有关该问题的完整解释。

由于这是客户端代码,因此我无法提供该代码或提供所有信息。甚至包名也必须被混淆。

再次,我要感谢所有花时间试图提供帮助的人,并且我想为没有提供所有必要的数据而道歉。