I have a log file on a UNIX server which is dynamically changing.
I want to build an application to view that file on a Java GUI using Swings in multiple pages using SSH.
I am using JSCH Library to execute the "more" command for that log file. But in the output, some special characters like '[24;1H[K[7m' are printed. How to remove these special characters.
I am using the following code
session.setConfig("StrictHostKeyChecking", "no");
session.connect(30000);
Channel channel=session.openChannel("shell");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect();
Thread.sleep(3000);
PrintStream ps = new PrintStream(channel.getOutputStream(), true);
ps.println("more " + fileName);
The output is :
[?7h[?1l(B=[24;1H[K************ Start Display Current Environment ************
[24;1H[K[7mSystemOut.log (0%)[m[24;1H[24;1H[KID: soacore.FP6123 BuildVrsn: null Desc: WebSphere Process Server 6.1.2.3
[24;1H[K[7mSystemOut.log (0%)[m
As you can see, some special characters are printed. How to remove those special characters?
I found out the answer. Just one line of code does the trick.
((ChannelShell) channel).setPtyType("dumb");
Adding the above line before the connect() removes all the non printable characters.
If you are developing a terminal emulator you can consider using a third-party library that could help you to manage the input data flow, specially dealing with the ANSI terminal control characters you are encountering. Tools like Expect are traditionally used to automate interacting between a program and text based terminal systems.
There are several exiting Expect for Java implementations you can use. Here I'd like to promote my own open source tool called ExpectIt. It supports filtering the input data to remove unwanted characters like terminal control that you may find very useful for your use case. It has other advantages stated on the project page.
Here is an example of using ExpectIt to iterate through the results of the more command. Note registering the removeColors filter which filters out the terminal characters.
session.setConfig(config);
session.connect();
Channel channel = session.openChannel("shell");
Expect expect = new ExpectBuilder()
.withOutput(channel.getOutputStream())
.withInputs(channel.getInputStream(), channel.getExtInputStream())
// register filters to remove ANSI color characters
.withInputFilters(removeColors())
.build();
try {
channel.connect();
// define the command line prompt
final String PROMPT = "...";
expect.expect(contains(PROMPT));
expect.sendLine("more <file>");
while (true) {
// expect either the end of the page or the end of the command
MultiResult result = expect.expect(anyOf(contains("--More--"), contains(PROMPT)));
// print the result
System.out.println(result.getBefore());
// exit if reach the end
if (result.getResults().get(1).isSuccessful()) {
break;
}
// scroll to the next page
expect.send(" ");
}
The code below works assuming that the corresponding methods are imported statically.
Related
I am re-implementing a subset of pdftk (pdftk fails with newer versions of pdf) and one of it's features it the ability to output an interactive pdf file to the command line (for piping purposes). I currently am doing that with
if("".equals(output)){
File tmp=new File("tmp.pdf");
doc.save(tmp);
output= new String(Files.readAllBytes(Paths.get("tmp.pdf")), "UTF-8");
tmp.delete();
}
System.out.println(output);
The problem is when I pipe this to out.pdf. and open it, only the form fields are in the new pdf field. My first thought would be that the second line would be the faulty one, but tmp.pdf is the full pdf file, suggesting that the problem is in the line where I am reading the pdf. Any suggestions?
Edit:
I found a different way that mostly works using /dev/nul or CON (os dependent). This way is better as it doesn't create temp files, but on windows it doesn't pipe correctly. Any ways to make it pipe?
if("".equals(output)){
if("W".equals(System.getProperty("os.name").substring(0,1)))
doc.save(new File("CON"));
else
doc.save(new File("/dev/stdout"));
System.out.println(output);
As discussed in the comments - instead of saving to a temp file, you can save to System.out:
doc.save(System.out);
Although I've never tested whether System.out can be used for such a purpose and keep the content intact, so I'd recommend that you do some binary test to compare the original PDF and what you get out of the pipe.
The application works fine on Windows machines where DB2 is setup in English language, since need to validate the executed commands output like
> db2 attach to DB2 user db2admin using xxxxxx
Instance Attachment Information
Instance server = DB2/NT64 10.5.1
Authorization ID = DB2ADMIN
Local instance alias = DB2
Actually the above output is redirected into a text file and then validated by a Java code as
String message = Utils.readFile(filePath);
message = message.trim().replaceAll("\\s+", " ");
String upperStr = message.toUpperCase();
if (upperStr.indexOf("INSTANCE ATTACHMENT INFORMATION") != -1
&& upperStr.indexOf("AUTHORIZATION ID") != -1)
return "SUCCESS";
else
return "FAILURE";
But the issue is: On Japanese/Chinese machine the DB2 commands generate the output in their language e.g. In Japanese Machine
インスタンス?Eアタッチ?﨣・インスタンス?Eサ?[バ?[ = DB2/NT 10.5.5 許可 ID = DB2ADMIN ・?[カル?Eインスタンス別名 = DB2
So, how to modify that language to work normally like English?
Or could the command's output be generated in English only?
It seems that you chose an unreliable way to determine success (or failure) of an external program. Apart from the language problem you are dealing with, there are other possible issues with trying to save and parse program output.
A better way to check the external program result is to look at its exit code. By convention, most programs (DB2 CLP included) return 0 when they end successfully and a different value if there is some sort of a problem. You can find more information in the manual.
When executing an external program from Java, you can use Process.exitValue() to obtain its exit code.
I have a Java application that creates and runs a process (x.exe). When process x is executed, it prompts the user to enter a password. How to pass this password to the user?
I tried to use the OutputStream of the process and wrote the password to the stream but still the process didn't run.
Runtime r=Runtime.getRuntime();
Process p=r.exec("x.exe");
p.getOutputStream()//.use to pass the arguments
You need to flush the stream, and also, it maybe expects a CR at the end of the password to simulate the ENTER key the user types at the end of the password. This works for me in Linux:
Runtime r = Runtime.getRuntime();
Process p = r.exec("myTestingExe");
p.getOutputStream().write("myPassword\n".getBytes()); // notice the `\n`
p.getOutputStream().flush();
Some caveats:
This works in Linux with '\n' at the end, maybe in Windows you would need \r instead (honestly I'm not sure of how Windows handles the "ENTER" key in the input)
I'm using "myPassword\n".getBytes() but a more complete value would be new String("myPassword".getBytes(), Charset.forName("MyCharsetName")); (where "MyCharsetName" is a supported encoding) if you are using an encoding like "UTF-8".
As already was pointed out you can consider to use an Expect-like library for interacting between your Java program and a spawn OS process. Basically, you would need to wait until the password prompt gets available in the process input stream and then write the password terminated by the end-of-line to the process output stream.
If you decide to go with a third party library approach I'd recommend you to give a try my own modern alternative to expect4j and others. It is called ExpectIt has no dependencies and is Apache licensed.
Here is a possible example with the use of the expect library:
Process process = Runtime.getRuntime().exec("...");
Expect expect = new ExpectBuilder()
.withInputs(process.getInputStream())
.withOutput(process.getOutputStream())
.withErrorOnTimeout(true)
.build();
expect.expect(contains("Password:"));
expect.sendLine("secret");
expect.close();
Note: the contains method is statically imported.
You can try library like expect4j to interact with the external process
I use the Apache Commons API to append a new line to a file using the FTPClient class. When I run the following code in Java, a new line is appended to the file on the FTP server. However, when I run the same code in Android, the String is appended to the file without a new line.
Why is the new line using - System.getProperty("line.separator") - not transferred via FTP under Android?
Also, the new line is correctly displayed in the LogCat but does not work in the txt file on the FTP server. Maybe there is a difference in character encoding between Java and Android?
Thank you very much.
String log = System.getProperty("line.separator") + "blablabla";
boolean done = ftpClient.appendFile("log.txt", new ByteArrayInputStream(log.getBytes("UTF-8")));
System.out.println("LOG: " + log);
As the file is on the server, I wouldn't think you'd want the client's value of System.getProperty("line.separator"); You want to know what the line separator on the server is, especially as you're working (apparently) in binary mode and so the FTP middle layer can't do line-ending conversions for you. (Which was once — possibly still is — quite a common thing for FTP clients and servers to do; it was called "ASCII" mode. [Ah, those halcyon days, when we thought we could assume text would be in ASCII, despite knowing, deep down, that that just wasn't sustainable... Like two-digit years...])
You could either query that information from the server, or choose to always use a particular line separator in your server-side log file. If the latter, \n would be a good choice if you're using a *nix-based server. If you're always on the Microsoft stack on the server, then \r\n would probably be a better choice.
Windows uses \r\n as its line separator, unlike UNIX which uses just \n
So,try to use
String log = "\n" + "blablabla";
or
String log = "\r\n" + "blablabla";
instead of
String log = System.getProperty("line.separator") + "blablabla";
I am currently writing a service that should take cleartext commands and then return something according to thoose commands, which is also in cleartext.
I have this odd problem with BufferedReader, or, it might be telnet that is odd, for some reason the BufferedReader reads the first command, however that command is ignored no matter what i do, which i can get around by sending the first command twice, but that is just stretching it a bit, in my oppinion.
The code below is in a run() method.
Then i set out as a PrintWriter and in as a BufferedReader.
The runs variable is by default true.
out = new PrintWriter(handle.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(handle.getInputStream()));
while (runs) {
String msg;
msg = in.readLine();
String[] command;
command = msg.split(" ", 3);
/* do something with the command */
}
So my question is if BufferedReader is ignoring the first line or is it telnet that is not coorperating with me?
If it is something else, then please enlighten me.
EDIT
I got this debug message:
Debug: ���� ����'������/nick halmark
so i suppose that it is about all the questionmarks.
I am actually using the latest Putty since i am developing on a windows box... and as far as i recall... then it does not exist by default
If you are using PuTTY, you need to choose the "Raw" Connection Type.
Microsoft telnet servers like to have some content/protocol negotiation at the beginning, so PuTTY will do this by default as per the RFC 854 spec. That's the garbage that you are reading.