标签: apache-commons-exec

来自apache-commons exec的进程输出

我在这里结束了我的智慧.我确信这很简单,我很可能在理解java和流时遇到很大漏洞.我认为有这么多课程,我试图通过API来弄清楚我何时以及如何使用大量的输入/输出流,我有点不知所措.

我刚刚了解了apache commons库的存在(自学java失败),我正在尝试将我的一些Runtime.getRuntime().exec转换为使用commons - exec.已经修复了一些每6个月一次这个问题,然后消除了exec的风格问题.

代码执行perl脚本,并在GUI运行时从GUI中显示stdout.

调用代码在swingworker内部.

我迷路了如何使用pumpStreamHandler ...无论如何这里是旧代码:

String pl_cmd = "perl script.pl"
Process p_pl = Runtime.getRuntime().exec( pl_cmd );

BufferedReader br_pl = new BufferedReader( new InputStreamReader( p_pl.getInputStream() ) );

stdout = br_pl.readLine();
while ( stdout != null )
{
    output.displayln( stdout );
    stdout = br_pl.readLine();
}
Run Code Online (Sandbox Code Playgroud)

我想这是我得到的复制粘贴代码,我很久以前还不完全理解.上面我假设正在执行该过程,然后抓取输出流(通过"getInputStream"?),将其放入缓冲读取器,然后将循环,直到缓冲区为空.

我没有得到的是为什么这里不需要'waitfor'样式命令?是否可能有一段时间缓冲区将为空,退出循环,并在进程仍在进行时继续?当我运行它时,情况似乎并非如此.

无论如何,我试图使用commons exec获得相同的行为,基本上再次从谷歌找到的代码:

DefaultExecuteResultHandler rh = new DefaultExecuteResultHandler();
ExecuteWatchdog wd  = new ExecuteWatchdog( ExecuteWatchdog.INFINITE_TIMEOUT );
Executor exec = new DefaultExecutor();

ByteArrayOutputStream out = new ByteArrayOutputStream();
PumpStreamHandler psh = new PumpStreamHandler( out ); …
Run Code Online (Sandbox Code Playgroud)

java apache-commons apache-commons-exec

26
推荐指数
1
解决办法
2万
查看次数

在Apache Commons exec或ProcessBuilder之间做出决定

我试图决定是否使用ProcessBuilder或Commons exec,

我的要求是我只是想创建一个守护进程,其stdout/stdin/stderr我并不关心.另外,我希望在时机成熟时执行kill来销毁这个进程.

我在Linux上使用Java.

我知道两者都有他们的痛苦和陷阱(例如确保使用单独的线程吞下流可能导致阻塞或死锁,并关闭流,以免留下打开的文件)并想知道是否有人有建议方式或其他方式以及任何良好的资源.

java process apache-commons-exec

21
推荐指数
2
解决办法
7144
查看次数

如何将字符串参数传递给使用Apache Commons Exec启动的可执行文件?

我需要将一个文本参数传递给使用Apache Commons Exec启动的命令的stdin(对于好奇,命令是gpg,参数是密钥库的密码; gpg没有明确提供密码的参数,仅从stdin接受它.

另外,我需要它来支持Linux和Windows.

在shell脚本中,我会这样做

cat mypassphrase|gpg --passphrase-fd
Run Code Online (Sandbox Code Playgroud)

要么

type mypassphrase|gpg --passphrase-fd
Run Code Online (Sandbox Code Playgroud)

但是类型在Windows上不起作用,因为它不是可执行文件,而是命令内置的命令(cmd.exe).

代码不工作(由于上述原因)低于.为此产生一个完整的外壳太难看了,我一直在寻找更优雅的解决方案.不幸的是,BouncyCastle库和PGP之间存在一些不兼容的问题,因此我无法在(非常短的)时间内使用完全编程的解决方案.

提前致谢.

CommandLine cmdLine = new CommandLine("type");
cmdLine.addArgument(passphrase);
cmdLine.addArgument("|");
cmdLine.addArgument("gpg");
cmdLine.addArgument("--passphrase-fd");
cmdLine.addArgument("0");
cmdLine.addArgument("--no-default-keyring");
cmdLine.addArgument("--keyring");
cmdLine.addArgument("${publicRingPath}");
cmdLine.addArgument("--secret-keyring");
cmdLine.addArgument("${secretRingPath}");
cmdLine.addArgument("--sign");
cmdLine.addArgument("--encrypt");
cmdLine.addArgument("-r");
cmdLine.addArgument("recipientName");
cmdLine.setSubstitutionMap(map);
DefaultExecutor executor = new DefaultExecutor();
int exitValue = executor.execute(cmdLine);
Run Code Online (Sandbox Code Playgroud)

java apache-commons apache-commons-exec

11
推荐指数
1
解决办法
5774
查看次数

Apache Commons Exec为包含空格的参数生成了太多引号?

要么Apache Commons Exec中存在错误,要么我错误地使用API​​,但是当我使用CommandLine类添加包含空格的参数时,会添加一些引号,然后是给定参数的一部分.

例如:当我打电话java "what version",我得到java.lang.NoClassDefFoundError: what version了,当我打电话java "\"what version\""(其中包含转义引号,是命令行参数本身的一部分),我得到java.lang.NoClassDefFoundError: "what version".

因此,以下测试失败,因为正如您在最后一行中所看到的,Apache Exec正在生成后者版本,它应该生成第一个版本:

@Test
public void testArgumentQuoting() throws Exception {
    DefaultExecutor executor = new DefaultExecutor();
    DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    PumpStreamHandler streamHandler = new PumpStreamHandler(out, out);
    executor.setStreamHandler(streamHandler);
    CommandLine cmdLine = new CommandLine("java");
    cmdLine.addArgument("what version");
    executor.execute(cmdLine, resultHandler);
    resultHandler.waitFor();
    String resultPattern = "Exception in thread \"main\" java\\.lang\\.NoClassDefFoundError: ([\\w \"]+)";
    Pattern pattern = Pattern.compile(resultPattern);
    Matcher matcher = …
Run Code Online (Sandbox Code Playgroud)

java apache-commons-exec

10
推荐指数
2
解决办法
3619
查看次数

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

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

我开始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 …
Run Code Online (Sandbox Code Playgroud)

java linux multithreading apache-commons-exec

9
推荐指数
1
解决办法
2894
查看次数

使用PumpStreamHandler将输出和错误写入日志文件

我一直在寻找一个很好的例子,用于将Process输出和错误流写入日志文件.我使用apache-commons exec库来执行我的进程.下面的代码示例来演示

public static int executeCommand(CommandLine command, Logger log) throws ExecuteException, IOException {
    DefaultExecutor executor = new DefaultExecutor();
    executor.setExitValue(0);

    PumpStreamHandler psh = new PumpStreamHandler();
    executor.setStreamHandler(psh);

    return executor.execute(command);
}
Run Code Online (Sandbox Code Playgroud)

java runtime exec apache-commons apache-commons-exec

8
推荐指数
1
解决办法
5848
查看次数

无法使用Apache Commons Exec为命令提供多个输入并提取输出

我正在编写一个Java应用程序,需要使用Apache Commons Exec库来使用外部命令行应用程序.我需要运行的应用程序具有相当长的加载时间,因此最好保持一个实例处于活动状态而不是每次都创建一个新进程.应用程序的工作方式非常简单.一旦启动,它会等待一些新输入并生成一些数据作为输出,这两个数据都使用应用程序的标准I/O.

因此,我们的想法是执行CommandLine,然后将PumpStreamHandler与三个独立的流(输出,错误和输入)一起使用,并使用这些流与应用程序进行交互.到目前为止,我已经在基本场景中完成了这项工作,我有一个输入,一个输出,然后应用程序关闭.但是一旦我试图进行第二次交易,就会出现问题.

在创建了我的CommandLine之后,我创建了我的Executor并像这样启动它:

this.executor = new DefaultExecutor();

PipedOutputStream stdout = new PipedOutputStream();
PipedOutputStream stderr = new PipedOutputStream();
PipedInputStream stdin = new PipedInputStream();
PumpStreamHandler streamHandler = new PumpStreamHandler(stdout, stderr, stdin);

this.executor.setStreamHandler(streamHandler);

this.processOutput = new BufferedInputStream(new PipedInputStream(stdout));
this.processError = new BufferedInputStream(new PipedInputStream(stderr));
this.processInput = new BufferedOutputStream(new PipedOutputStream(stdin));

this.resultHandler = new DefaultExecuteResultHandler();
this.executor.execute(cmdLine, resultHandler);
Run Code Online (Sandbox Code Playgroud)

然后我继续启动三个不同的线程,每个线程处理一个不同的流.我还有三个处理输入和输出的SynchronousQueues(一个用作输入流的输入,一个用于通知outputQueue已启动新命令而另一个用于输出).例如,输入流线程如下所示:

while (!killThreads) {
    String input = inputQueue.take();

    processInput.write(input.getBytes());
    processInput.flush();

    IOQueue.put(input);
}
Run Code Online (Sandbox Code Playgroud)

如果我删除while循环并执行一次,一切似乎都完美无缺.显然,如果我再次尝试执行它,PumpStreamHandler会抛出异常,因为它已被两个不同的线程访问.

这里的问题是,在线程结束之前,似乎没有真正刷新processInput.调试时,命令行应用程序仅在线程结束时才真正接收其输入,但如果保留while循环则永远不会获得它.我已经尝试了许多不同的东西来使processInput刷新,但似乎没有任何工作.

以前有人尝试过类似的东西吗?有什么我想念的吗?任何帮助将不胜感激!

java command-line multithreading inputstream apache-commons-exec

8
推荐指数
1
解决办法
2986
查看次数

优雅地杀死了Apache Commons Exec进程

我在我的Java程序中启动了一个外部进程(在Linux上),我需要能够发送一个SIGTERM信号,而不是exec.getWatchdog().destroyProcess()发送的SIGKILL .有没有办法可以更优雅地停止使用commons-exec启动的unix进程?或者我可以获得PID,以便我可以自己运行相应的kill命令吗?

java unix apache-commons apache-commons-exec

6
推荐指数
2
解决办法
7214
查看次数

commons-exec:在系统PATH上执行程序?

我正在尝试执行一个程序(从ImageMagick转换为具体),其父文件夹存在于路径上.因此,当我从命令行运行时convert,它会运行命令.但是,以下内容失败:

String command = "convert"
CommandLine commandLine = CommandLine.parse(command);
commandLine.addArgument(...)
...
int exitValue = executor.execute(commandLine);
Run Code Online (Sandbox Code Playgroud)

如果我指定convert executable(C:\Program files\...)的完整路径,则此代码有效.如果我不这样做,我会抛出一个带退出值的异常4.

如何让commons-exec识别系统路径?

java path environment-variables system-calls apache-commons-exec

5
推荐指数
1
解决办法
3114
查看次数

apache commons CommandLine 对象是否可以防止命令行注入?

我想使用org.apache.commons.execJava 库来调用可执行文件。该CommandLine对象是否可以防止命令行注入?例如,如果我打电话:

String singleStringArgument = "-whatever;rm -rf ~/*"; // evil looking argument!
CommandLine cl = new CommandLine(new File(pathToExe,exeName)); 

cl.addArgument(singleStringArgument);  // oh no!

Executor exe = new DefaultExecutor();
exe.execute(cl);
Run Code Online (Sandbox Code Playgroud)

rm -rf ~/*除了预期的命令之外还会运行吗?如果确实如此,防止这种情况的最佳方法是什么?

API 说addArgument()“处理引用”,但我不确定这在这种情况下意味着什么。我可以编写一个测试用例来看看我的 Linux 机器上会发生什么,但我想确保它在其他平台上也是安全的。

java command-line apache-commons apache-commons-exec

5
推荐指数
1
解决办法
1206
查看次数