eclipse pipe stdout to another project - java

I have two projects in eclipse;
Project A is constantly streaming (currently to STDOUT) output (each new value streamed is newline delimited)
Project B I want to take in this, and do some stuff with it etc,
The only way I have found to do this is by writing to a file; I would prefer to avoid this as there is a ridiculous amount of data (at least for my resources), and most of it will end up being tossed.
Any advice appreciated, thanks!

There are several methods of approaching this:
Using TCP socket - not that difficult to achieve and gives you the ability to work remotely (run each program on a different computer).
Create a segmented file by program A and consume them with program B - The nuances are a bit tricky but overall a robust technique if it suits your needs
Use OS pipes - the easiest method given your current situation
I'll demonstrate option 3.
ProgramA.java:
for (int i=0; i<10; i++) {
System.out.println(i);
}
ProgramB.java:
java.io.BufferedReader br = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
String input;
while((input=br.readLine())!=null){
System.out.println("----" + input);
}
After which you can do this at the command line:
java -cp <program_A_classpath> ProgramA | java -cp <program_B_classpath> ProgramB
Output will be:
----0
----1
----2
----3
----4
----5
----6
----7
----8
----9

Related

ProcessBuilder's inputstream empty depending of OS

I made this simple piece of code to test ProcessBuilder:
#SpringBootApplication
public class TerminalDemoApplication {
public static void main(String[] args) {
SpringApplication.run(TerminalDemoApplication.class, args);
try {
System.out.println("hello");
Process process = new ProcessBuilder("python", "--version").start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
It works in Windows (returns python version of my system) but the same code in my macbook returns end of line, so basically empty. ¿This needs further configuration according to the OS? ¿why is this happening?
What error code are you getting?
There are (at least) two explanations; that error code would indicate which one it is.
You're not running python, or running 'the wrong' python
This would mean you are getting an error code of some sort, or an exception.
The likely reason for this is a path issue.
Running python, just like that - as in, no path information at all, is nominally neccessarily broken: That's just not how your OS works, it has no idea what to do with this path.
It's a bashism (as in, the shell does it, not the OS) to interpret such a command as 'oh, actually, go through each listed entry in the $PATH environment variable, and stick that path in front of this name, see if you find an executable there. If you do, run that and stop).
Java mostly doesn't engage in any bashisms. But, in a few bizarre places, it does - it tries to do basic space splitting when you use the single-string version of new ProcessBuilder), which is a shellism, and it does attempt to do basic PATH lookup, but that's about where it ends. It won't do * unpacking, which on windows is an OS-level thing but on posix systems is a shellism.
I strongly, strongly advise you to avoid java's basic shellisms. It's unreliable and highly OS-specific.
So: Always pass arguments explicitly (good, you're doing that), always use ProcessBuilder (good, you're doing that), never use relative paths (that's where you're going wrong).
It's going to the error stream instead
processes on OSes are generally hooked up to 3 pipes, not 2. There's the 'standard in', the 'standard out' and the 'standard err'. Your own java process exposes these as System.out, in, and err.
In linux in particular, it is common to redirect standard out of some process to a file or another process.
This means that standard err naturally has the property that it tends to emit to the console, even if you are redirecting things. In other words, the terms 'standard out' and 'standard err' are really stupid names on posix. The much better naming would be 'standard process output' and 'standard process messages'.
Asking python to print its version is in a bit of a limbo scenario. The string "Python v3.0.1" or whatnot is certainly not an error, but it's a bit dubious if one should consider this as 'the output of the process'. It's likely that the authors of the python tool consider it more 'some information I should print to you, even if you are redirecting things.
Thus, my guess is that this version is heading out to standard err instead.
You can solve this in two ways: Either read from standard err as well, or, use process builder's features: You can ask it to bundle up standard out and standard err into a single stream (.redirectErrorStream(true)).
I would expect the exit code to be 0 if this explanation is the correct one.

Java jar execution stuck when launched in a process by another java program

This is a very unusual problem I've come across and I'm hoping someone might have some insight on it. I'm on macOS Mojave (10.14.6), using Amazon's JRE Corretto-11.0.9.12.1 (build 11.0.9.1+12-LTS)
I have a program I've written that is something of a scripting engine that we use to do our routine bulk data processing. It takes an xml "script" file which contains the processing directions to execute and a list of input files as arguments. I'll refer to this as the "engine" from this point on. This engine is the backbone of a large portion of our automation. It shows a progress bar while processing to let users know that it is working.
There are 2 programs that use this engine:
One is a thin UI written in Swing, which we use to manually process data; it generates an xml file from the user input and passes it along with the input files and launches the engine in a separate process; the UI itself doesn't process any data.
The other watches a folder on our file server and processes incoming data from our clients daily when a folder is created inside of it so we can rip the data into our database. I'll call this the "importer".
Recently, a problem has come up where the engine becomes stuck while processing. Older versions of the engine did not have this problem, and I'm trying to figure out what exactly changed that caused this to happen, but while I've been trying to do this, our UI and importer programs have been using and older version of the engine. There are new features that we need to use in the new version of the engine, but we can't use it until this problem is solved.
The programs that uses the engine launch it in a process then waits for the result before continuing:
// example command generated from external program
String commandString = "java -jar engine.jar script.xml input_file1.txt input_file2.txt input_file3.txt";
String[] command = {"bash", "-c", commandString};
// I can grab the command from here for debugging
System.out.println(Arrays.toString(command));
ProcessBuilder pb = new ProcessBuilder(command);
// wait for the process to complete before continuing
Process p = pb.start();
p.waitFor();
int result = p.exitValue();
try (BufferedReader e = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
BufferedReader i = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
String line;
while ((line = e.readLine()) != null) {
System.out.println(line);
}
while ((line = i.readLine()) != null) {
System.out.println(line);
}
}
p.destroy();
// do other stuff
When launched in this way, there is a specific operation that causes the engine to hang. But if I take the command and launch it directly from the command line, the engine runs just fine! This is making it difficult to pin down where exactly the problem is; is it in the engine, or in the other programs? I've spent a couple of days looking for answers and come up with nothing. It's even more frustrating that this problem has appeared seemingly out of nowhere when it was working perfectly before, using the exact code above, for a quite a long time.
The operation where the engine hangs sorts files into folders based on their file names. When I watch my activity monitor while it runs, it's not taxing my resources at all, and disk space isn't an issue. It isn't a file permission issue, as the engine is creating files and folders all the time and in every step leading up to the step where it hangs. And as I said, if I run the command directly from the command line, it creates the folders and sorts the files without issue, to my extreme confusion.
The importer and UI run locally on a station, but the engine jar file lives on our file server, so that it is accessible to every station without individually downloading it everywhere each time there is an update. I thought at first that the issue might lie in the fact that it is being accessed over the network, but the problem occurs even when I use a local copy of the engine on my dev machine, so I have ruled that out. I've also ruled out that it's the JRE, even though we switched to it recently, since the older version of the engine still perform as expected.
There might of course be any reason why your 'engine' program may hang ;-) but certainly it will hang you don't read the its output, and in the right way:
The parent process needs to read the standard output and standard error streams of the child process, given that the child process does generate any substantial amount of output on any of these two channels. This must be done in two separate background threads. If the parent does not read the child's output, then the child process will block as soon as the (small) buffer between the processes is filled up.
The threads should be started as soon as the child process is started, and before the parent calls process.waitFor().
The simplest way to do this is the following:
Process process = processBuilder.start();
InputStream stdout = process.getInputStream();
InputStream stderr = process.getErrorStream();
Thread stdoutThread = new Thread() {
#Override
public void run() {
// read stdout here, e.g.
try {
int c;
while (-1 != (c = stdout.read())) {
// do whatever with c
}
} catch (IOException ioex) {
// ...
}
}
};
Thread stderrThread = new Thread() {
// ... same as for stdout
};
stdoutThread.start();
stderrThread.start();
}
Only after both threads have been started you may wait for the child process and join the threads:
int exitValue = process.waitFor();
stdoutThread.join();
stderrThread.join();
There might be more sophisticated ways to work with background threads using the Concurrency Framework introduced in Java 5, but this basic code gives the idea.

How to execute a python script from a Java program using jython? [duplicate]

What's the easiest way to execute a Python script from Java, and receive the output of that script? I've looked for different libraries like Jepp or Jython, but most appear out of date. Another problem with the libraries is that I need to be able to easily include a library with the source code (though I don't need to source for the library itself) if I use a library.
Because of this, would the easiest/most effective way be to simply do something like call the script with runtime.exec, and then somehow capture printed output? Or, even though it would be very painful for me, I could also just have the Python script output to a temporary text file, then read the file in Java.
Note: the actual communication between Java and Python is not a requirement of the problem I am trying to solve. This is, however, the only way I can think of to easily perform what needs to be done.
Not sure if I understand your question correctly, but provided that you can call the Python executable from the console and just want to capture its output in Java, you can use the exec() method in the Java Runtime class.
Process p = Runtime.getRuntime().exec("python yourapp.py");
You can read up on how to actually read the output from this resource:
http://www.devdaily.com/java/edu/pj/pj010016
import java.io.*;
public class JavaRunCommand {
public static void main(String args[]) {
String s = null;
try {
// run the Unix "ps -ef" command
// using the Runtime exec method:
Process p = Runtime.getRuntime().exec("ps -ef");
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
System.exit(0);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
}
}
There is also an Apache library (the Apache exec project) that can help you with this. You can read more about it here:
http://www.devdaily.com/java/java-exec-processbuilder-process-1
http://commons.apache.org/exec/
You can include the Jython library in your Java Project. You can download the source code from the Jython project itself.
Jython does offers support for JSR-223 which basically lets you run a Python script from Java.
You can use a ScriptContext to configure where you want to send your output of the execution.
For instance, let's suppose you have the following Python script in a file named numbers.py:
for i in range(1,10):
print(i)
So, you can run it from Java as follows:
public static void main(String[] args) throws ScriptException, IOException {
StringWriter writer = new StringWriter(); //ouput will be stored here
ScriptEngineManager manager = new ScriptEngineManager();
ScriptContext context = new SimpleScriptContext();
context.setWriter(writer); //configures output redirection
ScriptEngine engine = manager.getEngineByName("python");
engine.eval(new FileReader("numbers.py"), context);
System.out.println(writer.toString());
}
And the output will be:
1
2
3
4
5
6
7
8
9
As long as your Python script is compatible with Python 2.5 you will not have any problems running this with Jython.
I met the same problem before, also read the answers here, but doesn't found any satisfy solution can balance the compatibility, performance and well format output, the Jython can't work with extend C packages and slower than CPython. So finally I decided to invent the wheel myself, it took my 5 nights, I hope it can help you too: jpserve(https://github.com/johnhuang-cn/jpserve).
JPserve provides a simple way to call Python and exchange the result by well format JSON, few performance loss. The following is the sample code.
At first, start jpserve on Python side
>>> from jpserve.jpserve import JPServe
>>> serve = JPServe(("localhost", 8888))
>>> serve.start()
INFO:JPServe:JPServe starting...
INFO:JPServe:JPServe listening in localhost 8888
Then call Python from JAVA side:
PyServeContext.init("localhost", 8888);
PyExecutor executor = PyServeContext.getExecutor();
script = "a = 2\n"
+ "b = 3\n"
+ "_result_ = a * b";
PyResult rs = executor.exec(script);
System.out.println("Result: " + rs.getResult());
---
Result: 6
Jep is anther option. It embeds CPython in Java through JNI.
import jep.Jep;
//...
try(Jep jep = new Jep(false)) {
jep.eval("s = 'hello world'");
jep.eval("print(s)");
jep.eval("a = 1 + 2");
Long a = (Long) jep.getValue("a");
}
I've looked for different libraries like Jepp or Jython, but most seem to be very out of date.
Jython is not "a library"; it's an implementation of the Python language on top of the Java Virtual Machine. It is definitely not out of date; the most recent release was Feb. 24 of this year. It implements Python 2.5, which means you will be missing a couple of more recent features, but it is honestly not much different from 2.7.
Note: the actual communication between Java and Python is not a requirement of the aforementioned assignment, so this isn't doing my homework for me. This is, however, the only way I can think of to easily perform what needs to be done.
This seems extremely unlikely for a school assignment. Please tell us more about what you're really trying to do. Usually, school assignments specify exactly what languages you'll be using for what, and I've never heard of one that involved more than one language at all. If it did, they'd tell you if you needed to set up this kind of communication, and how they intended you to do it.
Jython approach
Java is supposed to be platform independent, and to call a native application (like python) isn't very platform independent.
There is a version of Python (Jython) which is written in Java, which allow us to embed Python in our Java programs. As usually, when you are going to use external libraries, one hurdle is to compile and to run it correctly, therefore we go through the process of building and running a simple Java program with Jython.
We start by getting hold of jython jar file:
https://www.jython.org/download.html
I copied jython-2.5.3.jar to the directory where my Java program was going to be. Then I typed in the following program, which do the same as the previous two; take two numbers, sends them to python, which adds them, then python returns it back to our Java program, where the number is outputted to the screen:
import org.python.util.PythonInterpreter;
import org.python.core.*;
class test3{
public static void main(String a[]){
PythonInterpreter python = new PythonInterpreter();
int number1 = 10;
int number2 = 32;
python.set("number1", new PyInteger(number1));
python.set("number2", new PyInteger(number2));
python.exec("number3 = number1+number2");
PyObject number3 = python.get("number3");
System.out.println("val : "+number3.toString());
}
}
I call this file "test3.java", save it, and do the following to compile it:
javac -classpath jython-2.5.3.jar test3.java
The next step is to try to run it, which I do the following way:
java -classpath jython-2.5.3.jar:. test3
Now, this allows us to use Python from Java, in a platform independent manner. It is kind of slow. Still, it's kind of cool, that it is a Python interpreter written in Java.
ProcessBuilder is very easy to use.
ProcessBuilder pb = new ProcessBuilder("python","Your python file",""+Command line arguments if any);
Process p = pb.start();
This should call python. Refer to the process approach here for full example!
https://bytes.com/topic/python/insights/949995-three-ways-run-python-programs-java
You can try using groovy. It runs on the JVM and it comes with great support for running external processes and extracting the output:
http://groovy.codehaus.org/Executing+External+Processes+From+Groovy
You can see in this code taken from the same link how groovy makes it easy to get the status of the process:
println "return code: ${ proc.exitValue()}"
println "stderr: ${proc.err.text}"
println "stdout: ${proc.in.text}" // *out* from the external program is *in* for groovy
First I would recommend to use ProcessBuilder ( since 1.5 )
Simple usage is described here
https://stackoverflow.com/a/14483787
For more complex example refer to
http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html
I've encountered problem when launching Python script from Java, script
was producing too much output to standard out and everything went bad.
The best way to achieve would be to use Apache Commons Exec as I use it for production without problems even for Java 8 environment because of the fact that it lets you execute any external process (including python, bash etc) in synchronous and asynchronous way by using watchdogs.
CommandLine cmdLine = new CommandLine("python");
cmdLine.addArgument("/my/python/script/script.py");
DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000);
Executor executor = new DefaultExecutor();
executor.setExitValue(1);
executor.setWatchdog(watchdog);
executor.execute(cmdLine, resultHandler);
// some time later the result handler callback was invoked so we
// can safely request the exit value
resultHandler.waitFor();
Complete source code for a small but complete POC is shared here that addresses another concern in this post;
https://github.com/raohammad/externalprocessfromjava.git

Unbuffered subprocess stdout on windows

Is there an easy way to read output from subprocess unbuffered? I'm trying to call a C program from Java, but apparently it's stdout block-buffered when connected to pipe and line-buffered only when connected to console. I cannot modify C program.
Maybe there is a way to fool the program into thinking it is connected to console? Bonus points for a solution that works on linux as well.
It's not a great solution, but the runtime library probably doesn't buffer serial ports so if you're desperate enough you could use a null-modem emulator such as com0com or a derivative thereof.
Have you tried using environment variable BUF_1_=0?
OK -
1) "Line buffered input" is a common idiom for console-mode programs, dating back to the original Unix and serial-mode VTxx terminals.
2) You can read "raw, unbuffered" I/O (a keystroke at a time, instead of a line at a time), but the details are OS specific. Whatever you need to do on a specific OS, you almost certainly can do from Java.
3) It sounds like you want to be able to intercept an "arrow up" key or "page down" key, as it happens, on a Windows keyboard. Perhaps for playing a game, or for interacting with a console-mode user interface.
4) There are several options. One you might wish to consider is the "robot" API, used for testing:
http://www.java-tips.org/java-se-tips/java.awt/how-to-use-robot-class-in-java.html
If that's not sufficient, please give more details about exactly how you're trying to get your Java program to interact with the C program (and clarify if the platform is indeed Windows and a DOS prompt).
You could redirect the c output to a file and then tail the file from another thread in java using
org.apache.commons.io.input.Tailer
The best way to do it is using Threads to read the output
What I would do is: using a Callable (a Runnable will also work) where I give the input from the process (process.getInputStream ()) and the output where I want to store the output. The same should be done for the StdErr. The resulting output can be read using whatever you like.
public Object call () throws IOException {
int bytesRead;
byte[] b = new byte [ this.maxBlockSize ];
try {
while ( ( bytesRead = this.input.read ( b ) ) != -1 ) {
this.output.write ( b, 0, bytesRead );
}
} finally {
if ( this.output != null ) {
this.output.close ();
}
}
return null;
}

Program output lost when passed through PsExec

(This is a question my coworker posted elsewhere, but I thought I'd post it here to see if I could hit a different audience.)
Hello all,
I'm testing the possibility of writing a small java application the will use Psexec to kick off remote jobs. In the course of testing binding the stdin and stdout of a java program to psexec I came across an odd bug.
My test program is a basic echo program. It starts a thread to read from stdin and then pipes the read output directly back to stdout. When run on the local machine, not from psexec, it works beautifully. Exactly as it should.
However, when I call it from PsExec the first time the input is piped directly into stdout it is lost. What makes the bug really bizzare is that it is only the first time the input is piped directly into stdout that it is lost. If the input String is appended to another string it works fine. Either a String literal or a String variable. However, if the input String is sent directly to stdout it doesn't go through. The second time it is sent to stdout it goes through fine - and everytime there after.
I'm at a complete loss as to what's going on here. I've tried to test for every possible bug I can think of. I'm out of ideas. Did I miss one or is this just something inside psexec?
Here is the code in question, it's in three classes (one of which implements an interface which is a single function interace).
The Main class:
public class Main {
public static void main(String[] args) {
System.out.println("Starting up.");
CReader input = new CReader(new BufferedReader(
new InputStreamReader(System.in)));
CEcho echo = new CEcho();
input.addInputStreamListener(echo);
input.start();
System.out.println("Successfully started up. Awaiting input.");
}
}
The CReader class which is the thread that reads from stdin:
public class CReader extends Thread {
private ArrayList<InputStreamListener> listeners =
new ArrayList<InputStreamListener>();
private boolean exit = false;
private Reader in;
public CReader(Reader in) {
this.in = in;
}
public void addInputStreamListener(InputStreamListener listener) {
listeners.add(listener);
}
public void fireInputRecieved(String input) {
if(input.equals("quit"))
exit = true;
System.out.println("Input string has made it to fireInputRecieved: "
+ input);
for(int index = 0; index < listeners.size(); index++)
listeners.get(index).inputRecieved(input);
}
#Override
public void run() {
StringBuilder sb = new StringBuilder();
int current = 0, last = 0;
while (!exit) {
try {
current = in.read();
}
catch (IOException e) {
System.out.println("Encountered IOException.");
}
if (current == -1) {
break;
}
else if (current == (int) '\r') {
if(sb.toString().length() == 0) {
// Extra \r, don't return empty string.
continue;
}
fireInputRecieved(new String(sb.toString()));
sb = new StringBuilder();
}
else if(current == (int) '\n') {
if(sb.toString().length() == 0) {
// Extra \n, don't return empty string.
continue;
}
fireInputRecieved(new String(sb.toString()));
sb = new StringBuilder();
}
else {
System.out.println("Recieved character: " + (char)current);
sb.append((char) current);
last = current;
}
}
}
}
The CEcho class, which is the class that pipes it back to stdout:
public class CEcho implements InputStreamListener {
public void inputRecieved(String input) {
System.out.println("\n\nSTART INPUT RECIEVED");
System.out.println("The input that has been recieved is: "+input);
System.out.println("It is a String, that has been copied from a " +
"StringBuilder's toString().");
System.out.println("Outputting it cleanly to standard out: ");
System.out.println(input);
System.out.println("Outputting it cleanly to standard out again: ");
System.out.println(input);
System.out.println("Finished example outputs of input: "+input);
System.out.println("END INPUT RECIEVED\n\n");
}
}
And finally, here is the program output:
>psexec \\remotecomputer "C:\Program Files\Java\jre1.6.0_05\bin\java.exe" -jar "C:\Documents and Settings\testProram.jar"
PsExec v1.96 - Execute processes remotely
Copyright (C) 2001-2009 Mark Russinovich
Sysinternals - www.sysinternals.com
Starting up.
Successfully started up. Awaiting input.
Test
Recieved character: T
Recieved character: e
Recieved character: s
Recieved character: t
Input string has made it to fireInputRecieved: Test
START INPUT RECIEVED
The input that has been recieved is: Test
It is a String, that has been copied from a StringBuilder's toString().
Outputting it cleanly to standard out:
Outputting it cleanly to standard out again:
Test
Finished example outputs of input: Test
END INPUT RECIEVED
have you tried redirecting the output into a file ( java... >c:\output.txt )? this way you could doublecheck if everything is going into stdout and maybe just getting eaten by psexec
PsExec is eating the output. Next interesting thing might be where it's eating the output. You could check this by getting a copy of Wireshark and checking whether the output in question is traversing the network or not. If it's not, then it's being eaten on the remote side. If it is, it's being eaten locally.
Not that I'm really sure where to go from there, but collecting more information certainly seems like a good path to be following...
I was having the same issue and tried multiple combinations of redirects.
This is what worked:
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(Redirect.PIPE);
processBuilder.redirectInput(Redirect.INHERIT);
final Process process = processBuilder.start();
// Using Apache Commons IOUtils to get output in String
StringWriter writer = new StringWriter();
IOUtils.copy(process.getInputStream(), writer, StandardCharsets.UTF_8);
String result = writer.toString();
logger.info(result);
final int exitStatus = process.waitFor();
The Redirect.INHERIT for processBuilder.redirectInput got me the missing remote command output.
Is System.out not configured for autoflush? After the first print try System.out.flush() and see if the first line appears without more lines being printed.
(oh yeah, seriously, it is "RECEIVED", not "RECIEVED".)
OK, I've been thinking about this over the weekend and I since you are jumping from machine to machine I wonder if maybe there is a CharSet issue? Maybe it is eating the string the first time and dealing with a different code page or character set issue? Java is 16bit characters normally and windows is either 8bit with code pages or utf-8 these days.
Any chance the local and remote machines have different default character sets? If you are sending localized data over the net it might misbehave.
What I see when running psexec is that it spawns a child window to do the work but doesnt return that program's output to it's console window. I would suggest using WMI or some form of windows process API framework to gain a level of control you appear to lack with psexec. Surely java has an equivalent to .Net's System.Diagnotics.Process class.
Maybe you could try passing a copy of input to your listeners:
public void fireInputRecieved(String input) {
if(input.equals("quit"))
exit = true;
String inputCopy = new String(input);
System.out.println("Input string has made it to fireInputRecieved: "
+ input);
for(int index = 0; index < listeners.size(); index++)
listeners.get(index).inputRecieved(inputCopy);
}
I had similar problems with listeners where a passed variable would end up empty unless I did pass an explicit copy of it.
I don't necessarily have an answer, but some comments may prove helpful.
The "pass a copy" idea shouldn't matter, since your output successfully prints the string twice before the failure, then succeeds again afterward.
auto-flush shouldn't matter either, as you've already mentioned
Niko's suggestion has some merit, for diagnostic purposes. Mixed with Mark's suggestion, it makes me wonder if there aren't some invisible control characters getting involved somewhere. What if you printed the characters byte values as a diagnostic step?
You know that the value is "Test" (at least in the output you gave us). What happens if you pass "Test" directly to the failing printLn statement?
In situations like this, you want to gain as much information as possible. Insert breakpoints and analyze characters. Send the bytes to files and open them in hex editors. Do whatever you can to trace things as accurately and as precisely as possible.
Come up with weird test scenarios and try them, even if they shouldn't possibly help. You never know what good idea you might have while analyzing the results of the hopeless idea.
I'd guess that there is a bogus byte in there prefacing the T. According to JavaDocs, an InputStreamReader will read one or more bytes, and decode them into characters.
You could have an escape sequence or spurious byte in there, masquerading as a multibyte character.
Quick check - see if "current" is ever > 128 or < 33.
What if you used a CharArrayReader to get individual bytes, without any charset translation?
The theory is that during the first attempt to output the String using println, it's sending an escape character of some sort, eating the rest of the string. During later prints, either Java or the network pipe are handling or removing it, since it previously got that escape sequence, perhaps changing the handling in some way.
As an unrelated nit, sb.toString() returns a new String, so it's unnecessary to call "new String(sb.toString())"
Same issue here, I'm going through this post again and again these days, hoping I can find some solution. Then I decide I should give up psexec and find some alternative. So this is the thing: PAExec. Works perfect for getting command output.
How are you executing PsExec? My suspicion is that this is some code within PsExec which is actually doing echo suppression, possibly for the purposes of protecting a password. One way to test this hypothesis would be to change this code:
System.out.println("Outputting it cleanly to standard out: ");
System.out.println(input);
System.out.println("Outputting it cleanly to standard out again: ");
System.out.println(input);
to this:
System.out.println("Outputting it cleanly to standard out: ");
System.out.print(' ');
System.out.println(input);
System.out.println("Outputting it cleanly to standard out again: ");
System.out.println(input);
...thereby causing the output to be (if I'm right):
Outputting it cleanly to standard out:
Test
Outputting it cleanly to standard out again:
Test
Finished example outputs of input: Test
In particular, it's noticeable that the apparently-suppressed line is the first line which consists solely of Test - which is exactly the text you've just sent to the remote system. This sounds like PsExec attempting to suppress a remote system which is echoing its input in addition to producing its own output.
Is the password of the user on the remote machine perhaps Test? Are you using PsExec's -p parameter? Are you specifying -i?
I am dealing with this same issue and I am wondering if it has to do with how the cmd window and pipes in windows work while you don't have a true windowed session. The suppressed output happens when any new process is spawned. You would think that if you spawn a process that the stdout/stderr/stdin would be inherited from the process that spawned it; after all that is what happens if you spawn the process from a normal cmd window and the output from the new process is piped back to your own console. However if somewhere in the inheritance of the pipes something were to go wrong, like say not passing a WINDOW.GUI object because there is no physical window, windows doesn't let the stdin/stdout/stdin to be inherited. Can any one do some investigation or open a windows support ticket for this?
Seems no easy solution. My work-around in a recent project is using paexec.exe product. It captures output/error easily in JAVA(java-8), but hangs up upon completion of the remote command execution. When running this inside a server on the hosted machine, I have to spurn a new child JVM process to run paexec.exe and force kill it via its PID upon completion in order to release all the resources.
If anyone has better solution, please post it.

Categories