I am new to ExpectJ Java programming. I downloaded jar's and able to do few send() and expect() methods. send() would fire a command on console and expect() would identify any prompt's so inputs can be provided. Expect only reads is there are prompts, and not other info. For example, if want to fire, spawn.send("ls") and get list of all file names and so certain action, is that possible?.
Is there way so I can read normal output of spawn.send("ls") for example, without expect which only captures prompts?
You can indeed capture the output stream:
It is one of the methods of the ExpectJ.Spawn class
I am also very new to Java, but I got the output, however, I am still struggling on getting the prompt recognized as I get extra control characters from Unix so do not trust what comes after the second System.out.println (the sh,expect part)
the output works fine, just set it in a variable if you want, or if you use swing, send it to a textarea with a listener.
BTW! if you know how to do the expect without these bloody control characters, 1m,34 [001 and so on, I welcome your input
import expectj.ExpectJ;
import expectj.Spawn;
public class myExpectinator {
public myExpectinator(){
}
public void connect(){
try {
ExpectJ ex = new ExpectJ(10);
Spawn sh = ex.spawn("10.10.10.10", 22, "name", "password");
System.out.println(sh.getCurrentStandardOutContents());
System.out.println(sh.getCurrentStandardErrContents());
sh.expect("~ $");
sh.send("ps\n");
System.out.println(sh.getCurrentStandardOutContents());
//sh.expectClose();
sh.stop();
}
catch(Exception e) {
System.out.println(e);
}
}
}
Related
I'm currently dealing with the following problem:
I try to make a console input for a java application
that works with multiple threads. So while running the
software it happens sometimes, that a new line of log is
appearing while I'm writing to the readLine with a promt..
When that happens it looks like the following:
Image of the Console
so it does stack the messages like in the image.. so here is the question:
How can I keep the line and text I am writing to and log the text above it like in the example below?
Gif of the input
(Sorry for low quallity but you can guess what I mean)
As you can see my input stays at the bottom, is still editable and the lines do not stack
Thank you for some help, I am struggeling so much after trying Log4j, System.console, BufferedReaders and Scanner
Solved. It was horrible complicated..
But here for the future:
class ConsoleThread implements Runnable {
private ConsoleReader reader;
private OutputStream output;
public ConsoleThread(OutputStream output, ConsoleReader reader) {
this.output = output;
this.reader = reader;
}
#Override
public void run() {
try {
String message;
while (true) {
message = LoggingQueue.getNextLogEvent();
if(message == null) continue;
reader.print(Ansi.ansi().eraseLine(Ansi.Erase.ALL).toString() + ConsoleReader.RESET_LINE);
reader.flush();
output.write((message + System.lineSeparator()).getBytes());
output.flush();
try {
reader.drawLine();
} catch (Throwable ex) {
reader.getCursorBuffer().clear();
}
reader.flush();
}
} catch (IOException e) {
Controller.handleException(Thread.currentThread(), e);
}
}
Using the ConsoleReader of jLine2 and jAnsi. The output stream is just System.out.
You just need a second thread which reads and you are done :)
You need to handle the threads competing for stdin/stdout.
In theory, that would imply some kind of mutex but, since you're using external libraries, it seems like too much trouble...
From your images, it seems that you're running a sort of server application that takes commands.
If that's the case, I recommend re-architecting to use two separate processes: one for the server part and one for the command prompt.
The two processes then communicate through a socket.
This allows you to make the command prompt single threaded or, at least, behave like a single threaded application, since it is only reacting to user commands.
This is what lots of applications, like Docker, Kubernetes or MySQL do.
In the case of Docker and Kubernetes, they expose full REST APIs on that socket so you can leverage libraries for that.
I have written a sample code:
import java.util.Scanner;
public class abcd {
public static void main(String[] args) {
System.out.print("please enter a: ");
Scanner a = new Scanner(System.in);
String b = a.next();
System.out.println(b);
}
}
I am able to compile and execute this code via Ubuntu terminal. In SciTe, it compiles fine, but when I run it, I am faced with this error:
please enter a: Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1371)
at abcd.main(abcd.java:8)
Any Suggestions?
EDIT: When I execute a file in terminal, I do: 'java abcd' Scite does: 'java -cp .abcd'. How are the two commands different and why isn't java -cp working?
It appears that there is a bug/improper implementation in the handling of standard input in SciTE on Linux/Unix.
The description of the bug and a workaround are in this PDF document: A Problem with SciTE Go Command on Linux
Note: this is not official documentation, but it seems to match your problem.
According to that document, when running a Java program through the "Go" command on SciTE, input is supposed to come from the output pane. However, on Linux this does not work properly, and it's as if you are reading from an empty stream.
When you are reading from an empty stream, Scanner sees the end-of-file marker when it attempts to read a value using next(), nextInt() etc. And it throws a NoSuchElementException as there is no input element in the stream.
Your options to work around this problem:
Try the method mentioned in the aforesaid document, to use "Go" in a Linux terminal instead of the output pane.
Run the program in a terminal and avoud the "Go" command altogether.
Use a different IDE which doesn't have this problem.
Try to use hasNext() before next();
import java.util.Scanner;
public class abcd {
public static void main(String[] args) {
System.out.print("please enter a: ");
Scanner a = new Scanner(System.in);
while(a.hasNext()) {
try {
String b = a.next();
System.out.println(b);
} catch (NoSuchElementException e) {}
}
}
}
I don't mean to offend, but using hasNext() as suggested in Alexander's answer won't solve this problem, it will only enable OP to handle it well. I don't think that is what he/she is looking for.
Now I am no expert by any means and for some reason your program code works on my machine... But anyways, a NoSuchElementException is thrown when your program is cycling over an iterable object and there is nothing more to cycle over, despite your program expecting something there. A quick look-up in the Java-docs of Scanner.next()
shows that this exception is thrown if there are no more tokens available for read.
Now, if I had to guess I would advise you to try using something other than Scanner.next() and see if that works.
The fact that it works on my machine but not on yours is somewhat surprising, so could you provide some information on how you try to run your program? Are you running it from the default command-line? Or within Scite? (If second is the case, I really won't be able to help you, I have never even touched Scite).
First of all I regret as I am asking a very basic and peculiar question;But I am new to Java as well as programming. I studied that "out" in system.out.println() is an object of system class.Can "out" be Replaced with any other objects of the system class ? If so what are the members and how???
You can call println() on any PrintStream. If you look at the System javadoc, you will find another PrintStream static field, namely System.err. For example:
System.err.println("This goes to POSIX standard error!");
If you want to actually replace standard out with your own output stream, you can pass your stream to System.setOut(PrintStream) or the corresponding System.setErr(PrintStream)
here are 2 very useful links (hope this helps)
Javapapers: system.out.print
http://docs.oracle.com/javase/7/docs/api/java/lang/System.html
here's a short description of it below :
Structure of System.out.println
Following is the skeletal structure of System.out.println in the JDK source. Through this code snippet the essential parts are highlighted and its given for better understanding.
public final class System {
static PrintStream out;
static PrintStream err;
static InputStream in;
...
}
public class PrintStream extends FilterOutputStream {
//out object is inherited from FilterOutputStream class
public void println() {
...
}
Change out of System.out.println
‘out’ object can be customized. out gets initialized by java runtime environment at startup and it can be changed by developer during execution.
Instead of standard output, in default cases when you run a program through command line, the output is printing in the same command window. We can change that behavior using setOut method as below.
In the following example
public class ChangeOut {
public static void main(String args[]) {
try {
System.setOut(new PrintStream(new FileOutputStream("log.txt")));
System.out.println("Now the output is redirected!");
} catch(Exception e) {}
}
}
Yes
System.setOut(out) does just that.
where out can be any instance of PrintStream.
For example :
System.setOut(System.err); would set the default output stream to be the same as the default error stream.
yes. you can use different key words as System.err.println() or system.in and different , you can get the complete view here http://javapapers.com/core-java/system-out-println/ in this link you can have a complete tutorial thing for you.
Yes, e.g. err
But I would download any of Java IDE (Intellij IDEA or Ecliplse), create a new java project, new class, new main method, type System.out and hit Ctrl + Space and see what happens
I was doing some work for college and my main runs this:
Spreadsheet sheet = new Spreadsheet(0,0);
SpreadsheetManager manager = new SpreadsheetManager(sheet);
/* Read an Import file, if any */
String filename = System.getProperty("import");
if (filename != null)
sheet.parseInputFile(filename, sheet);
Thing is, when I actually try to import a file it doesn't do what is supposed to and the filename is always null, so it never reaches my parseInputFile.
My teachers made a bunch of code for different programming exercises that do similar things available, and I've also looked at projects my colleagues did in previous years, but every single one does what I am doing above.
I have to run my program like this: java -Dimport=A-002-002-M-ok.import calc.textui.Calc otherwise none of the tests given by the teachers will run.
I'm sorry if this is not a useful question, but I've tried looking everywhere. If anyone could explain how the System.getProperty("import") works and why it isn't working in this case, I would be very grateful.
I suggest you take a look at the documentation of System.getProperty().
Basically it retrieves a value from the system, either already present or set by you.
To avoid retrieving null you can use another method signature that specify a default value:
System.getProperty("import", "file.txt");
To set a System property, you can specify it at launch:
java -Dimport="file.txt" your_application
or set it programatically :
System.setProperty("import", "file.txt");
When you run your program with:
java -Dimport=foo
then the method call
System.getProperty("import")
should return "foo".
Is ist possible that you write a tiny example program to convince yourself? Without any SheetManagers and all stuff, just
class ItWorks {
public static void main(String[] args) {
System.out.println(System.getProperty("import"));
}
}
Call it thus
java -Dimport=indeed ItWorks
and report what happens.
That being said: if you want to pass command line arguments, why don't you use the facility for command line arguments? (i.e. the String[] array passed to main?)
You could then call your program like this:
java calc.textui.Calc my-nice-spreadsheet.data
=====================================================
Please write the follwoing in your calc.textui.Calc program immediately after the open brace of your class definition:
public class Calc ..... { // a line like this already exists
// insert next line here
public static String filename = System.getProperty("import");
// rest of your class, as before.
}
Then comment out the getProperty() line in your method that didn't work, but leave the rest including the System.out.println(filename);
Does it change?
Maybe system properties are not the most indicated way to do that (depends on your application).
You could also use command line arguments to pass the file name to your main method:
public class CommandLineExample {
public static void main(String[] args) {
if (args.length < 1) {
System.err.println("usage: CommandLineExample <filename>");
System.exit(1);
}
String filename = args[0];
if (filename !=null && !filename.isEmpty()) {
...
}
}
}
Your program should be called as:
java CommandLineExample theFileName
the string "theFileName" will be passed to the main method in args[0] (any additional words will be passed in subsequent positions of args {args[1], args[2], ...})
EDIT
if the program must be called with
java -Dimport=filename ...
then System.getProperty("import") will return the filename.
Confirm that you are calling the correct program (class name, package, version, last compile was successful, ...) and also check that the property is not mistyped like java -Dinport=A-... or has additional spaces, uppercase letters...
(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.