ZeroTurnaround Process Executor

Related tags

Spring Boot zt-exec
Overview

ZT Process Executor

Continuous Integration

Build Status

Quick Overview

The project was created to merge similar functionality of projects at ZeroTurnaround into a single codebase. It's designed to be powerful but still simple to use. By using a single class ProcessExecutor the user gets the functionality from both java.lang.ProcessBuilder and Apache Commons Exec.

Installation

Maven Central

The project artifacts are available in Maven Central Repository.

To include it in your maven project then you have to specify the dependency.

...
<dependency>
    <groupId>org.zeroturnaround</groupId>
    <artifactId>zt-exec</artifactId>
    <version>1.12</version>
</dependency>
...

Motivation

There are many approaches to take when running external processes from Java. There are the JRE options such as the Runtime.exec() and ProcessBuilder. Also there is the Apache Commons Exec. Nevertheless we created yet another process library (YAPL).

Some of the reasons for this crazy endeavour

  • Improved handling of streams
  • Reading/writing to streams
  • Redirecting stderr to stdout
  • Improved handling of timeouts
  • Improved checking of exit codes
  • Improved API
  • One liners for quite complex usecases
  • One liners to get process output into a String
  • Access to the Process object available
  • Support for async processes ( Future )
  • Improved logging with SLF4J API
  • Support for multiple processes

Can zt-exec also kill processes?

No. There is zt-process-killer for that.

Examples

  • Output is pumped to NullOutputStream
new ProcessExecutor().command("java", "-version").execute();

  • Returning the exit code
  • Output is pumped to NullOutputStream
int exit = new ProcessExecutor().command("java", "-version")
                  .execute().getExitValue();

  • Return output as UTF8 String
String output = new ProcessExecutor().command("java", "-version")
                  .readOutput(true).execute()
                  .outputUTF8();    

  • Pumping the output to a logger
new ProcessExecutor().command("java", "-version")
      .redirectOutput(Slf4jStream.of(LoggerFactory.getLogger(getClass().getName() + ".MyProcess")).asInfo()).execute();

  • Pumping the output to a logger (short form for previous)
new ProcessExecutor().command("java", "-version")
      .redirectOutput(Slf4jStream.of("MyProcess").asInfo()).execute();

  • Pumping the output to the logger of the caller class
new ProcessExecutor().command("java", "-version")
      .redirectOutput(Slf4jStream.ofCaller().asInfo()).execute();

  • Pumping the output to a logger
  • Returning output as UTF8 String
String output = new ProcessExecutor().command("java", "-version")
        .redirectOutput(Slf4jStream.of(getClass()).asInfo())
        .readOutput(true).execute().outputUTF8();

  • Pumping the stderr to a logger
  • Returning the output as UTF8 String
String output = new ProcessExecutor().command("java", "-version")
        .redirectError(Slf4jStream.of(getClass()).asInfo())
        .readOutput(true).execute()
        .outputUTF8();

  • Running with a timeout of 60 seconds
  • Output pumped to NullOutputStream
try {
  new ProcessExecutor().command("java", "-version")
        .timeout(60, TimeUnit.SECONDS).execute();
}
catch (TimeoutException e) {
  // process is automatically destroyed
}

  • Pumping output to another OutputStream
OutputStream out = ...;
new ProcessExecutor().command("java", "-version")
      .redirectOutput(out).execute();

  • Handling output line-by-line while process is running
new ProcessExecutor().command("java", "-version")
    .redirectOutput(new LogOutputStream() {
      @Override
      protected void processLine(String line) {
        ...
      }
    })
    .execute();

  • Destroy the running process when VM exits
  • Output pumped to NullOutputStream
new ProcessExecutor().command("java", "-version").destroyOnExit().execute();

  • Run process with a specific environment variable
  • Output pumped to NullOutputStream
new ProcessExecutor().command("java", "-version")
    .environment("foo", "bar").execute();

  • Run process with a specific environment
  • Output pumped to NullOutputStream
Map<String, String> env = ...
new ProcessExecutor().command("java", "-version")
    .environment(env).execute();

  • Throw exception when wrong exit code
  • Output is pumped to NullOutputStream
try {
  new ProcessExecutor().command("java", "-version")
        .exitValues(3).execute();
}
catch (InvalidExitValueException e) {
  System.out.println("Process exited with " + e.getExitValue());
}

  • Throw exception when wrong exit code
  • Return output as UTF8 String
String output;
boolean success = false;
try {
  output = new ProcessExecutor().command("java", "-version")
                .readOutput(true).exitValues(3)
                .execute().outputUTF8();
  success = true;
}
catch (InvalidExitValueException e) {
  System.out.println("Process exited with " + e.getExitValue());
  output = e.getResult().outputUTF8();
}

  • Starting process in the background
  • Output is pumped to NullOutputStream
Future<ProcessResult> future = new ProcessExecutor()
                                    .command("java", "-version")
                                    .start().getFuture();
// do some stuff
future.get(60, TimeUnit.SECONDS);

  • Start process in the background
  • Return output as UTF8 String
Future<ProcessResult> future = new ProcessExecutor()
                                    .command("java", "-version")
                                    .readOutput(true)
                                    .start().getFuture();
// do some stuff
String output = future.get(60, TimeUnit.SECONDS).outputUTF8();
Comments
  • Question: RedirectOutput(CachingOutputStream)

    Question: RedirectOutput(CachingOutputStream)

    Hello,

    I am using zt-exec to execute a process in background and read the output line by line with the LogOutputStream.processLine() method.

    Unfortunately, when doing some complex stuff in processLine it seems to miss some output lines, can someone give me an advice how to cache/buffer the lines, to process them later?

    Thanks for your work!

    opened by defec8edc0de 15
  • Run command for change directory and then git clone using zt-exec

    Run command for change directory and then git clone using zt-exec

    I am trying the following code :

    String output = new ProcessExecutor().command("cd", "D:/myfolder")
                .readOutput(true).execute()
                .outputUTF8();  
    

    But getting an exception : Exception in thread "main" java.io.IOException: Could not execute [cd D:/myfolder]. at org.zeroturnaround.exec.ProcessExecutor.invokeStart(ProcessExecutor.java:936) at org.zeroturnaround.exec.ProcessExecutor.startInternal(ProcessExecutor.java:910) at org.zeroturnaround.exec.ProcessExecutor.execute(ProcessExecutor.java:860) at .git.zttest.main(zttest.java:16) Caused by: java.io.IOException: Cannot run program " cd D:/myfolder": CreateProcess error=2, The system cannot find the file specified at java.lang.ProcessBuilder.start(Unknown Source) at org.zeroturnaround.exec.ProcessExecutor.invokeStart(ProcessExecutor.java:931) ... 3 more Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified at java.lang.ProcessImpl.create(Native Method) at java.lang.ProcessImpl.(Unknown Source) at java.lang.ProcessImpl.start(Unknown Source) ... 5 more

    How this command can be executed using zt-exec. Also after this is done my whole command is : cd <mydirectory> && D: && <gitlocation>/git clone --depth 1 <url>

    Is this possible?

    opened by anukriti-chawla 7
  • ProcessExecutor NoSuchFieldError: NULL_OUTPUT_STREAM

    ProcessExecutor NoSuchFieldError: NULL_OUTPUT_STREAM

    When I try to call the below class, I get java.lang.NoSuchFieldError: NULL_OUTPUT_STREAM and I'm not sure why. I've tried the various versions of Slf4jStream.ofClass()/of(getClass()), etc. This is written in groovy, and it's being called from my test suite. I'd be grateful for any suggestions as to what might be going wrong.

        class ProgramRunner{
    
    	final Logger log = LoggerFactory.getLogger(getClass());
    	
    
    	public void runProcess(List<String> command, Map<String, String> environment, Long timeout){
    		new ProcessExecutor().command(job.command)
    		.redirectOutput(Slf4jStream.of(log).asInfo())
    		.redirectError(Slf4jStream.of(log).asError())
    		.timeout(command.timeout ?: Long.MAX_VALUE, TimeUnit.SECONDS)
    		.environment(command.environment ?: new HashMap<String, String>())
    		.execute();
    	}
    }
    
    opened by stevedefazio 7
  • Improved logic w/ input vs. output streams

    Improved logic w/ input vs. output streams

    For various reasons, I need to supply my own wrapped System.in inputstream. The problem I'm running into is that the ExecuteStreamHandler makes a very important decision on what kind of InputStream pump it creates IF the inputstream is System.in. In my case, the process runs and exits, but the InputStream is hanging forever on a blocking read() call.

    I'm not sure this is the right logic for input streams vs. output. In fact, if the process actually does exit, why aren't all the streams closed and their pumping threads interrupted? Or if the output streams are closed, it seems like the inputstream w/o a doubt should be closed.

    opened by jjlauer 6
  • Question: How I can pickup stderr from ProcessResult

    Question: How I can pickup stderr from ProcessResult

      ProcessResult processResult = processState.getProcessResult().get(timeout, TimeUnit.SECONDS);
      int code = processResult.getExitValue();
      String err = (code == 0) ? "" : processResult.getOutput().getString();
    

    I want to pick up from a Process class stderr using your lib.

    This piece of code is not correct since there are commands where exit status is 0 but it logs the result in stderr. E.g. java -version

    How can I pickup stderr reliably?

    Thanks guys, Catalin

    opened by dinuta 5
  • Version 1.11 contains JRebel file with Toomas' user dir :D

    Version 1.11 contains JRebel file with Toomas' user dir :D

    If you look inside zt-exec 1.11 jar, there is "rebel.xml" file (I guess it was added by mistake) with @toomasr's user dir (I assume he was releasing the library ;)): Screenshot 2019-07-19 at 3 06 00 PM

    We discovered it in @testcontainers when our shading tests started failing because of an unexpected "rebel.xml" file in the resulting JAR 😅

    opened by bsideup 5
  • Stream closed exception on Java 1.8 when piping input stream

    Stream closed exception on Java 1.8 when piping input stream

    Using zt-exec 1.8 and Java 1.8 I'm getting the following error when trying to do echo foo | /bin/true:

    2016-01-27 14:32:51,780 ERROR [Thread-0] [o.z.e.s.StreamPumper] Got exception while closing exhausted output stream
    java.io.IOException: Broken pipe
            at java.io.FileOutputStream.writeBytes(Native Method) ~[na:1.8.0_71]
            at java.io.FileOutputStream.write(FileOutputStream.java:326) ~[na:1.8.0_71]
            at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82) ~[na:1.8.0_71]
            at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140) ~[na:1.8.0_71]
            at java.io.FilterOutputStream.close(FilterOutputStream.java:158) ~[na:1.8.0_71]
            at org.zeroturnaround.exec.stream.StreamPumper.run(StreamPumper.java:137) ~[zt-exec-1.8.jar:na]
            at java.lang.Thread.run(Thread.java:745) [na:1.8.0_71]
    2016-01-27 14:32:51,783 ERROR [main] [o.z.e.c.StandardProcessCloser] Failed to close process output stream:
    java.io.IOException: Stream closed
            at java.lang.ProcessBuilder$NullOutputStream.write(ProcessBuilder.java:433) ~[na:1.8.0_71]
            at java.io.OutputStream.write(OutputStream.java:116) ~[na:1.8.0_71]
            at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82) ~[na:1.8.0_71]
            at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140) ~[na:1.8.0_71]
            at java.io.FilterOutputStream.close(FilterOutputStream.java:158) ~[na:1.8.0_71]
            at org.zeroturnaround.exec.close.StandardProcessCloser.closeStreams(StandardProcessCloser.java:53) [zt-exec-1.8.jar:na]
            at org.zeroturnaround.exec.close.StandardProcessCloser.close(StandardProcessCloser.java:43) [zt-exec-1.8.jar:na]
            at org.zeroturnaround.exec.WaitForProcess.call(WaitForProcess.java:118) [zt-exec-1.8.jar:na]
            at org.zeroturnaround.exec.ProcessExecutor.waitFor(ProcessExecutor.java:1007) [zt-exec-1.8.jar:na]
            at org.zeroturnaround.exec.ProcessExecutor.execute(ProcessExecutor.java:860) [zt-exec-1.8.jar:na]
            at TryIt.main(TryIt.java:8) [classes/:na]
    

    This same error occurs for any program that doesn't read from stdin, such as /bin/false, /bin/ls, /bin/pwd, etc -- this seems to be the difference between success and failure (i.e. no errors when using /bin/cat for example).

    This only happens on Java 1.8 -- testing on 1.7 works fine. I have only used zt-exec 1.8 during testing.

    I'm having this same error using Apache commons-exec, which is why I started looking for alternatives and come across this library.

    Code to reproduce:

    import org.zeroturnaround.exec.ProcessExecutor;
    import java.io.ByteArrayInputStream;
    
    public class TryIt {
      public static void main(String[] args) throws Exception {
        ByteArrayInputStream bais = new ByteArrayInputStream("foo".getBytes());
        ProcessExecutor exec = new ProcessExecutor().command("/bin/true");
        int exit = exec.redirectInput(bais).readOutput(true).execute().getExitValue();
        System.out.println(exit);
      }
    }
    

    Java installation:

    openjdk version "1.8.0_71"
    OpenJDK Runtime Environment (build 1.8.0_71-b15)
    OpenJDK 64-Bit Server VM (build 25.71-b15, mixed mode)
    
    opened by nwolfe 5
  • Closing a Process InputStream hangs on some processes

    Closing a Process InputStream hangs on some processes

    (1) I noticed that you have this is StandardProcessCloser and what I find is that getInputStream() can hang when Process.destroy() has already been called:

    try { process.getInputStream().close(); }catch (IOException e) { log.error("Failed to close process input stream:", e); caught = e; }

    (2) Also, I find that InputStream.close() can hang, unless process.destroy() is called first.

    So, the key for me is to make sure I obtain the inputStream before calling close() and then also make sure to call destroy before forcibly closing the streams:

    For example, here is a process that I think requires that correct sequence or it will not destroyForcibly on Windows:

    @ECHO OFF ECHO WELCOME TO HUNG :loop for /l %%n in (1,1,10000000000) do set temp= goto:loop ECHO UNREACHABLE EXIT

    Furthermore, if the Process is started as a 16-bit DOS executable, then even though Process reports that it is dead, it is still alive and well in the ntvdm.exe subsystem for running windows-on-windows 16-bit exe's in the system32 environment.

    Which is to say, that although the batch file above needs a specific order to shutdown, if it spawns a 16-but program then that program must be forcibly killed by taskkill.

    opened by ghost 5
  • Force destruction of a known PID

    Force destruction of a known PID

    For Windows... We have some processes that __ just __ won't __ die -- in particular, there are 16-bit processes that are run in the ntvdm.exe subsystem and even thought the Process.destroyForcibly() reports that they are dead, they are still alive because Java only kills the consolehost or cmd.exe not the spawned thread in ntdvm.exe.

    Also, getting the exit value fails (or throws) because the process is still alive even after Process claims it died.

    So ... I have my own library for Process that scans the process output for a self reporting PID.

    If the process exit is overdue, then I call my taskkiller ... and it goes through all the PID's found and kills them all via the windows taskkill command.

    Hence, all my processes are started via a 'cmd /c' batchfile that calls getpid.exe and then reports the errorlevel as the PID like this:

    %BATCHOME%\manage\getpid.exe echo GETPID.EXE: THE CURRENT PID IS %errorlevel% :: then call program that does what we need done. :: by running "taskkill.exe /f /t /pid {pid}" we can kill the PID and any children in the tree

    The getpid.exe program is created by running the batchfile code pasted at the bottom of this post.

    I'll throw this out there and then maybe you can integrate a way to collect PID's using some program specified magic cookie and then be able to verifiably destory them similar to this.

    The PID's are collected by my process reader. Here is the code to my process destroyer util.

    public static List<Throwable> kill(String pid, Process p) throws InterruptedException {
        List<Throwable> exceptions = new ArrayList();
                try {
                    callWindowsTaskkill(p, pid, exceptions);
                } catch (final KillException ke) {
                    exceptions.add(ke);
                }
        return exceptions;
    }
    
    private static void destroyWait(Process p) throws InterruptedException, KillException {
        p.destroyForcibly();
        logger.debug("destroyForcibly called. Will wait 100 ms for official termination.");
        if (p.waitFor(100, TimeUnit.MILLISECONDS)) {
            logger.info(">> exit code: {}", p.exitValue());
        } else {
            throw new KillException("Process will not die after calling destroyForcefully() and waiting 100ms.", p);
        }
    }
    
    private static void callWindowsTaskkill(Process p, String pid, List<Throwable> exceptions) throws InterruptedException, KillException {
        logger.info("calling kill on pid: {}", pid);
        BatchSession<LineGobbler> bs = getKillTask(pid).call();
        for (Throwable t : bs.getExceptions()) {
            exceptions.add(t);
        }
        if (bs.getGobbler().isPresent()) {
            boolean dead = false;
            for (String line : bs.getGobbler().get().getLines()) {
                logger.debug(line);
                if (StringUtils.startsWithIgnoreCase(line, "SUCCESS: The process with PID " + pid + " ")
                        && StringUtils.endsWithIgnoreCase(line, " has been terminated.")) {
                    dead = true;
                } else if (StringUtils.containsIgnoreCase(line, "ERROR: The process \"" + pid + "\" not found")) {
                    dead = true;
                }
            }
            if (!dead) {
                throw new KillException("Process with pid " + pid + " will not die after being destroyed by 'taskkill'", p);
            }
        }
    }
    
    private static BatchTask<LineGobbler> getKillTask(String pid) {
        String id = pid + "-killer";
        return BatchTask.builder()
                .setTimeout(Duration.ofSeconds(10))
                .setTimeoutAction(BatchTask.TimeoutAction.taskkill)
                .build(id, new ProcessBuilder("taskkill.exe", "/f", "/t", "/pid", pid),
                        () -> new LineGobbler(id, StandardCharsets.ISO_8859_1));
    }
    

    @Echo Off Rem Script made using BHX { consolesoft.com/p/bhx } SetLocal EnableExtensions EnableDelayedExpansion Set "bin=getpid.ex_" Set "size=643" For %%# In ( "getpid.exe" "!bin!" "!bin!.da" "!bin!.tmp" ) Do If Exist "%%#" (Del /A /F /Q "%%#" >Nul If ErrorLevel 1 Exit /B 1 ) Findstr /B /N ":+res:!bin!:" "%~f0" >"!bin!.tmp" (Set /P "inioff=" &Set /P "endoff=") <"!bin!.tmp" For /F "delims=:" %%# In ("!inioff!") Do Set "inioff=%%#" For /F "delims=:" %%# In ("!endoff!") Do Set "endoff=%%#" Set ".=set o=createobject(#scripting.filesystemobject#)" Set ".=!.!: set w=createobject(#adodb.stream#)" Set ".=!.!: set r=o.opentextfile(#%~f0#,1,0,0)" Set ".=!.!: w.charset=#windows-1252# : w.type=2 : w.open" Set ".=!.!: for i=1 to !inioff! step 1 : r.readline : next" Set ".=!.!: do while i<!endoff! : d=r.readline" Set ".=!.!: for j=1 to len(d) step 2" Set ".=!.!: w.writetext chr(cbyte(#&h#&mid(d,j,2)))" Set ".=!.!: next : i=i+1 : loop" Set ".=!.!: w.savetofile #!bin!#,2" Set ".=!.!: w.close : r.close" Set ".=!.!: set w=nothing : set r=nothing : set o=nothing" Set ".=!.:#="!" Echo !.!>"!bin!.da" Set "ret=1" Cscript.exe /B /E:vbs "!bin!.da" >Nul For %%# In ("!bin!") Do If "%%~z#"=="!size!" Set "ret=0" If "0"=="!ret!" Expand.exe -r "!bin!" -F:* . >Nul If ErrorLevel 1 Set "ret=1" Del /A /F "!bin!" "!bin!.da" "!bin!.tmp" >Nul Exit /B !ret!

    :+res:getpid.ex_: 4D5343460000000083020000000000002C000000000000000301010001000000 000000004700000001000100000800000000000000009645357D200067657470 69642E65786500DD597C9934020008434BF38D9AC0C0CCC0C0C002C4FFFF3330 EC6080000706C2A00188F9E477F1316CE13CABB883D1E7AC62484666B1424151 7E7A5162AE4272625E5E7E894252AA4251699E42669E828B7FB0426E7E4AAA1E 2F2F970AD48C005706061F466686A7A9334260E63E60E067E66664126760823A 0C0836080009010684EB406C268834234219C4E140F1E21606B0BF181814A0FA 04E0FA05903D61C0C0F08708BF920A5C80E6CAE091D72B49AD2801B9859101EE 173046020A0C01097A45298925890C0C2250AF208709C2CB060E7A9910757FA0 7E02AB63C3507700DD1DA19D4FC3C3821BDFF800D51F7751019B7C9C4505A4FB C50620D179B8F90D87E181E6DFFF4B225E2C070AF46EDDF3F7FFFFCE1215964E 1995E3AD208E0E5075E7F1171381B240C5AD074A455F5B4015BC68810996A85A EE3D02545CFA14245C0A14EE6EBD02E437BF61E94DFD121D171F7BB8B7448D01 24190194045A892AD1BB471DEADEE637122F5CFF03DDC0A2F2C21428340119FC 57F530706000D101503A044A4740691728ED03A1FF83523D28ED43E89106DC9D 9DAD14344A5272758D34154CF42CF40C4762288C5CA0618060BF3180945BD840 02503C0F88BB80780610AF03E2030684E582189C73F28B533D12F352725219F6 303817A52696A486E4E7E764A4E614181B05E725161467E4038B427146D78ACC 9280A2FCE4D4E26286FD8CEEA925CEA54545A9793031CF14864E6628DBD8C82D B3A8B8249CA11B21E2072C51C361653A36ECED1AE4E7EA636CA4979293331AF3 100000 :+res:getpid.ex_:

    opened by ghost 5
  • ProcessExecutor getPid?

    ProcessExecutor getPid?

    Hi guys,

    Is there a possibility to get the Pid somehow from ProcessExecutor? Or use some other combination?

    Sample here: https://github.com/dinuta/estuary-testrunner-java/blob/master/src/main/java/com/github/dinuta/estuary/testrunner/utils/CommandRunner.java line 205

    Cheers, Catalin

    opened by dinuta 4
  • UnixProcess getting killed

    UnixProcess getting killed

    I have a spring boot application that launches child processes using ProcessExecutor...start(). I'm expecting the child processes to continue running when I stop the spring boot application. When I run the application on LINUX the processes are killed when I stop the main application. However, when I stop the application on Windows the processes continue to run as expected. Is there a way to prevent the processes from stopping on LINUX?

    opened by bhunter-insight 4
  • What is the default execution timeout

    What is the default execution timeout

    hey, there is my question. For the code new ProcessExecutor().command(anyCommand).timeout(60, TimeUnit.SECONDS).execute(); as an example. If we use such timeout(60, TimeUnit.SECONDS) funciton, we could set the execution timeout. So, if we do not use the timeout() function, what is the default execution timeout? Will it wait until the command finish?

    opened by ljpassingby 0
  • Apple Silicon Could not initialize class org.zeroturnaround.process.unix.LibC.

    Apple Silicon Could not initialize class org.zeroturnaround.process.unix.LibC.

    at org.zeroturnaround.process.UnixProcess.kill(UnixProcess.java:46)
    at org.zeroturnaround.process.UnixProcess.destroy(UnixProcess.java:34)
    at org.zeroturnaround.process.AbstractProcess.destroyForcefully(AbstractProcess.java:113)
    
    opened by jongyu 2
  • output not redirected when launching sub-processes on windows?

    output not redirected when launching sub-processes on windows?

    I doubt this is a specific problem to zt-exec, the same behaviour is reproducible when using ProcessBuilder, but just wanted a second opinion as I'm probably doing something wrong.

    This outputs the result of the ping to the outputStream:

    val pe = ProcessExecutor().apply {
      directory(workDirFile)
      redirectOutput(outputStream)
      command("ping", "-n", "2", "google.com")
    }
    

    But if I want to see the console window whilst it is executing the ping, I try to change the command to command("cmd", "/C", "start", "ping", "-n", "2", "google.com") The command prompt is shown, I see the results in the window but nothing is written to the stream.

    My understanding is that the cmd /c start launches the ping in a sub-process but it hasn't redirected the output, is it possible to make it redirect?

    opened by JRWilding 0
  • redirectError example is confusing

    redirectError example is confusing

    In the following example, the console gets all the output, but the String output value remains empty:

    String output = new ProcessExecutor().command("java", "-version")
            .redirectError(Slf4jStream.of(getClass()).asInfo())
            .readOutput(true).execute()
            .outputUTF8();
    

    Output:

    2021-12-30 12:51:32.150 DEBUG 43928 --- [  XNIO-1 task-1] org.zeroturnaround.exec.ProcessExecutor  : Executing [java, -version].
    2021-12-30 12:51:32.177 DEBUG 43928 --- [  XNIO-1 task-1] org.zeroturnaround.exec.ProcessExecutor  : Started java.lang.UNIXProcess@56e2d396
    2021-12-30 12:51:32.296  INFO 43928 --- [      Thread-56] c.l.openmx.service.mapper.AccountMapper  : openjdk version "1.8.0_292"
    2021-12-30 12:51:32.297  INFO 43928 --- [      Thread-56] c.l.openmx.service.mapper.AccountMapper  : OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_292-b10)
    2021-12-30 12:51:32.297  INFO 43928 --- [      Thread-56] c.l.openmx.service.mapper.AccountMapper  : OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.292-b10, mixed mode)
    2021-12-30 12:51:32.300 DEBUG 43928 --- [  XNIO-1 task-1] org.zeroturnaround.exec.WaitForProcess   : java.lang.UNIXProcess@56e2d396 stopped with exit code 0
    

    Without redirectError, the String output gets the output value:

    String output = new ProcessExecutor().command("java", "-version")
            .readOutput(true).execute()
            .outputUTF8();
    

    Output:

    openjdk version "1.8.0_292"
    OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_292-b10)
    OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.292-b10, mixed mode)
    

    Questions:

    1. Does redirectError work just in case of errors?
    2. Should String output get the output value with redirectError in place?
    opened by micobarac 0
  • Executable not found in PATH directories on Windows

    Executable not found in PATH directories on Windows

    Just some background: We are trying to run testcontainers on Windows with an internal repository hosted by Google. This requires to run the"docker-credential-gcloud" (from Google Cloud SDK) to obtain credentials by using zt-exec. Eventhough the bin folder of the SDK is listed in the Path environment variables the ProcessExecutor is not able to run it and fails with the error message Cannot run program "docker-credential-gcloud": CreateProcess error=2, Das System kann die angegebene Datei nicht finden (meaning "The system could not find the specified file."). However, if we start the same command through a cmd-shell it works.

    Is this a known issue? I could not find any documentation how %Path% is interpreted by zt-exec (or the underlyin g JDK functionaliy).

    Please find below a test case to document the issue. It is the exact same call used by testcontainers:

    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.zeroturnaround.exec.ProcessExecutor;
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.TimeoutException;
    
    public class DockerCredentialsTest {
        private String credentialHelperName ="docker-credential-gcloud"; 
        private String hostName = "europe-west1-docker.pkg.dev";
    
      @Test
        public void testProcessExecutor() throws IOException, InterruptedException, TimeoutException {
    
            // Uncommenting /*"cmd", "/c",*/  makes the call successful.
            String result = new ProcessExecutor()
                    .command(/*"cmd", "/c",*/ credentialHelperName, "get")
                    .redirectInput(new ByteArrayInputStream(hostName.getBytes()))
                    .readOutput(true)
                    .exitValueNormal()
                    .timeout(30, TimeUnit.SECONDS)
                    .execute()
                    .outputUTF8()
                    .trim();
            System.out.println(result);
            Assertions.assertNotNull(result);
        }
    
    opened by fhossfel 2
Owner
ZeroTurnaround
Our products help Java teams improve productivity & efficiency – resulting in better code, happy devs, and more reliable releases.
ZeroTurnaround
Kyrestia, named after Kyrestia the Firstborne, is a process engine supporting mainstream process definition standards.

Kyrestia Kyrestia, named after Kyrestia the Firstborne, is a process engine supporting mainstream process definition standards. It is not only lightwe

Weiran Wu 32 Feb 22, 2022
A Spring Boot Camel boilerplate that aims to consume events from Apache Kafka, process it and send to a PostgreSQL database.

SPRING-BOOT CAMEL BOILERPLATE This is a Spring-Boot Camel Application model that you can use as a reference to study or even to use in your company. I

Bruno Delgado 45 Apr 4, 2022
A compact and highly efficient workflow and Business Process Management (BPM) platform for developers, system admins and business users.

Flowable (V6) Maven Central: Docker Images: License: Homepage: https://www.flowable.org/ flowable / flowəb(ə)l / a compact and highly efficient workfl

Flowable 6k Jan 7, 2023
Squadio-App is a Users-Accounts financial system. exposes Rest APIs with JWT authentication/Authorization process .

squadio-app Description Squadio-App is a Users-Accounts financial system. exposes Rest APIs with JWT authentication/Authorization process . How to Run

Bashar Othman 1 Jan 29, 2022
Deploys an agent to fix CVE-2021-44228 (Log4j RCE vulnerability) in a running JVM process

-- This repository has been archived -- Further development of this tool will continue at corretto/hotpatch-for-apache-log4j2. Thanks for sharing, com

Volker Simonis 108 Dec 23, 2021
Reindex - application for visualize, optimize and automate your Elasticsearch reindex process

Welcome to reindex application for Elasticsearch This application will help you to reindex one or more existing indices, into the local or remote Elas

DBeast 3 Jan 2, 2023
Quarkus extension for launching an in-process Wiremock server

Quarkus extension for running Wiremock in DEVELOPMENT mode This extension is currently not published in any maven repository. If you want to test this

Quarkiverse Hub 5 Dec 30, 2022
ZeroTurnaround Process Killer

ZT Process Killer Continuous Integration Quick Overview The project was created in ZeroTurnaround to have a stable base functionality of stopping runn

ZeroTurnaround 114 Dec 29, 2022
Kyrestia, named after Kyrestia the Firstborne, is a process engine supporting mainstream process definition standards.

Kyrestia Kyrestia, named after Kyrestia the Firstborne, is a process engine supporting mainstream process definition standards. It is not only lightwe

Weiran Wu 32 Feb 22, 2022
Ribbon is a Inter Process Communication (remote procedure calls) library with built in software load balancers. The primary usage model involves REST calls with various serialization scheme support.

Ribbon Ribbon is a client side IPC library that is battle-tested in cloud. It provides the following features Load balancing Fault tolerance Multiple

Netflix, Inc. 4.4k Jan 1, 2023
Logstash - transport and process your logs, events, or other data

Logstash Logstash is part of the Elastic Stack along with Beats, Elasticsearch and Kibana. Logstash is a server-side data processing pipeline that ing

elastic 13.2k Jan 5, 2023
Ribbon is a Inter Process Communication (remote procedure calls) library with built in software load balancers. The primary usage model involves REST calls with various serialization scheme support.

Ribbon Ribbon is a client side IPC library that is battle-tested in cloud. It provides the following features Load balancing Fault tolerance Multiple

Netflix, Inc. 4.4k Jan 4, 2023
a Business Process Management (BPM) Suite

Quick Links Homepage: http://jbpm.org/ Business Applications: https://start.jbpm.org/ Documentation: https://docs.jboss.org/jbpm/release/latestFinal/j

KIE (Drools, OptaPlanner and jBPM) 1.4k Jan 2, 2023
Low-overhead, non-blocking I/O, external Process implementation for Java

NuProcess NuProcess is proud to power Facebook's Buck build. A low-overhead, non-blocking I/O, external Process execution implementation for Java. It

Brett Wooldridge 644 Dec 29, 2022
Sends stacktrace-level performance data from a JVM process to Riemann.

Riemann JVM Profiler riemann-jvm-profiler is a JVM agent that you can inject into any JVM process--one written in Clojure, Java, Scala, Groovy, etc.--

Riemann 288 Sep 21, 2022
A Spring Boot Camel boilerplate that aims to consume events from Apache Kafka, process it and send to a PostgreSQL database.

SPRING-BOOT CAMEL BOILERPLATE This is a Spring-Boot Camel Application model that you can use as a reference to study or even to use in your company. I

Bruno Delgado 45 Apr 4, 2022
Flutter plugin to listen to the process text intent stream.

Flutter Process Text Plugin Show some ❤️ and ⭐ the repo Why use Flutter Process Text? Flutter Process Text Plugin is known for : Flutter Process Text

Divyanshu Shekhar 14 Jul 1, 2022
Flutter plugin to listen to the process text intent stream.

Flutter Process Text Plugin Compatibility ✅ Android ❌ iOS (active issue: iOS support) Show some ❤️ and ⭐ the repo Why use Flutter Process Text? Flutte

Devs On Flutter 14 Jul 1, 2022