java - Apache Commons Exec - 有时线程无法在 Linux 中打开本地文件

标签 java linux multithreading apache-commons-exec

警告——原因不是文件丢失——所有线程都在调用同一个脚本文件

我正在启动 5-6 个调用 Red Hat 框中的本地脚本的线程。

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

couldn't read file "/home/leo/myScript.exp": no such file or directory

显然,所有进程都在执行脚本,所以这似乎与 [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("");
}

如果错误是 [1],那么我想知道如何在 linux 操作系统中放宽此限制

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

如果错误是其他原因,至少知道原因足以让我找到一些解决方案。

更新 - 3 月 15 日

好吧,事情是这样的。

该脚本是一个使用库调用Java类的expect脚本。

我注意到的一件事是脚本运行良好,直到它调用创建数据库连接的 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 ]

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);
    }
}

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);
}

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

更新 - 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)

最佳答案

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

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

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

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

enter image description here (点击放大)

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

为@Asynchronous 方法提供服务的线程池的 TomEE 配置中的线程数(我的应用程序未使用默认值)少于所需的线程数,因此似乎有些资源不足。

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

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

由于这是客户端代码,我无法提供代码或提供所有信息。甚至包名也必须进行混淆处理。

再次,我要感谢所有花时间在这里提供帮助的人,对于没有提供所有必要的数据,我深表歉意。

关于java - Apache Commons Exec - 有时线程无法在 Linux 中打开本地文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35897752/

相关文章:

multithreading - 我应该同时使用线程和递归吗?

java - 两个工厂类生成具有相同条件的不同接口(interface)实例

java - 如何防止客户端发送文件后服务器接收到空输出(多线程java套接字)

java - 将本地 React 前端连接到本地 Spring Boot 中间件应用程序时出现 CORS 错误

linux - 我找到了一种使用 find -exec 将多个文件集中在一行中的方法,如 xargs,但我不确定它到底是如何工作的

linux - 在linux任务调度程序中,sheduler_tick()在哪里调用?

linux - 如何在 Ubuntu 10.04 LTS 中升级现有的 phpmyadmin 版本?

java - Java ThreadPoolExecutor [提交的内容超过MaxPoolSize]

Docker 容器中的 Java RMI 服务器

Java线程疑惑