Search code examples
jenkinsjenkins-pluginsjenkins-agent

Jenkins plugin development, ProcStarter: How to write to stdin of already running process


I am trying to write to stdin of started process, which is already running. Writing to sdtin at process start time works:

External script 1.sh:

#!/bin/sh
echo "Started at $(date)" 
read a 
echo "$(date): got '$a'"

Code in plugin:

 ProcStarter proc = launcher.launch().stderr(listener.getLogger()).stdout(listener.getLogger()).cmds("/tmp/1.sh");  
 ByteArrayInputStream res = new ByteArrayInputStream(("hellooo" + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
 proc.stdin(res).join();

Output in jenkins console, same time stamp of start time and writing to sdtin:

$ /tmp/1.sh
Started at Thu Apr  2 10:52:02 CEST 2020
Thu Apr  2 10:52:02 CEST 2020: got 'hellooo'

I want to write to sdtin not at the start time, but after x seconds, something like this pseudocode :

  ProcStarter proc = launcher.launch().stderr(listener.getLogger()).stdout(listener.getLogger()).cmds("/tmp/1.sh");  
  proc.join(); //blocks

//somewhere in another Thread:
  Thread.sleep(15000);//pseudocode ;-)
  ByteArrayInputStream res = new ByteArrayInputStream(("hellooo" + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
  proc.stdin(res); // doesn't work

The usage of hudson.Launcher.ProcStarter is necessary due to execution on Jenkins agents. Are there any ideas, how I can write to stdin of already running process?


Solution

  • I got the solution, it's important to call proc.writeStdin() method which reverses the I/O direction:

    ProcStarter procStarter = launcher.launch().stderr(listener.getLogger()).stdout(listener.getLogger()).cmds("/tmp/1.sh");  
    proc.writeStdin();//important ==> Indicates that the caller will directly write to the child process stdin()
    Proc myProc = procStarter.start();
    myProc.getStdin().write(("helloooo2" + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
                myProc.getStdin().flush();