Get the "watch" command output in java getRuntime().exec - java

I am trying to get the output from watch free -b and/or top commands in java but when i call it using the getRuntime().exec() method in java, i get an error. Here is what i have tried:
Attempt #1
// This java code
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "watch -t -n 1 free -b");
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
Process process = pb.start();
int exitVal = process.waitFor();
// Gives this error
Error opening terminal: unknown
Attempt #2
// This java code
Process process = Runtime.getRuntime().exec("/bin/bash");
OutputStream stdin = process.getOutputStream();
PrintWriter pw = new PrintWriter(stdin);
pw.println("watch -t -n 1 free -b < /dev/tty > /dev/tty");
pw.close();
int exitVal = process.waitFor();
// Gives this error
Error opening terminal: unknown
Attempt #3
// This java code
Process process = Runtime.getRuntime().exec("/bin/bash");
OutputStream stdin = process.getOutputStream();
PrintWriter pw = new PrintWriter(stdin);
pw.println("watch -t -n 1 free -b < /dev/tty > /dev/tty");
pw.close();
int exitVal = process.waitFor();
// Gives this error
/bin/bash: line 1: /dev/tty: No such device or address
Also, if i try to pass the command this way to the process builder
ProcessBuilder pb = new ProcessBuilder("/usr/bin/watch -t -n 1 /usr/bin/free -b");
I get this error:
Cannot run program "/usr/bin/watch -t -n 1 /usr/bin/free -b": error=2, No such file or directory
Instead, when i pass the command `top` instead of `watch` i get the following error:
TERM environment variable not set
I think the problems are related because they both work with interactive shell, and also because any other command ( like ping for example ) works perfectly fine. But i am not sure at all.
Is there a way to continuously get the output from a command like watch in java?

Related

Incomplete output about Java Runtime.getRuntime().exec(command)

I want to build an app like Jenkins terminal:
And I use Java Runtime.getRuntime().exec(command) to execute the command, find out that the output is incomplete.
textshell.sh:
# textshell.sh
echo "wwwwwww";
sleep 2
ls
For example:
When I execute textshell.sh in my mac terminalsh -x testshell.sh , output :
+ echo wwwwwww
wwwwwww
+ sleep 2
+ ls
testshell.sh
but when I execute by java Java Runtime.getRuntime().exec("sh -x testshell.sh") , output:
wwwwwww
testshell.sh
the shell args -x seems useless
How can I fix it?
As #Joachim Sauer points out you are not reading STDERR so miss the lines of echo output from the set -x output. Adjust your code to access the process.getErrorStream() as well.
Alternatively you can switch to ProcessBuilder if wanting to read the error stream merged with the output:
String[]cmd = new String[]{"sh", "-x", "testshell.sh"}
ProcessBuilder pb = new ProcessBuilder(cmd);
// THIS MERGES STDERR>STDOUT:
pb.redirectErrorStream(true);
// EITHER send all output to a file here:
Path stdout = Path.of("mergedio.txt");
pb.redirectOutput(stdout.toFile());
Process p = pb.start();
// OR consume your STDOUT p.getInputStream() here as before:
int rc = p.waitFor();
System.out.println("STDOUT: \""+Files.readString(stdout)+'"');

Cannot run shell script from java Command Line

I'm trying to run this script shell from java, but it's not working.
I get this error message:
Process exited with an error: 1 (Exit value: 1)
Can someone help?
String pwd = "blabla";
String s_key = "0000";
String path = "C:/Files/scripts";
CommandLine commandLine = CommandLine.parse("C:\\Program Files (x86)\\Git\\bin\\git.exe");
commandLine.addArgument("fileName.sh");
commandLine.addArgument(password);
commandLine.addArgument(s_key);
DefaultExecutor defaultExecutor = new DefaultExecutor();
ByteArrayOutputStream sdtout = new ByteArrayOutputStream();
ByteArrayOutputStream sdterr = new ByteArrayOutputStream();
PumpStreamHandler streamHandler = new PumpStreamHandler(sdtout, sdterr);
defaultExecutor.setStreamHandler(streamHandler);
defaultExecutor.execute(commandLine);
Here is the script
#!/bin/sh
pwd=$1
s_key=$2
....
echo $pwd
it works well with git bash
$ ./fileName.sh blabla 0000
nkfjWmiG7dDnYUmjr6VD0A==
There are some points to be aware of.
If you want to run the git bash command you need to execute the git-bash.exe, on the cmd console you need to execute this command:
%windir%\system32\cmd.exe /c ""C:\Program Files\Git\git-bash.exe" --login -i -- D:\temp\test.sh param1"
If you want to execute it from a java app it's the same, the command you need to execute is git-bash.exe not git.exe.
This is an example of running a command from java. I'm not using the objects that you're using but the simple java objects. However you can adapt it to your code.
public static void main(String[] args) throws IOException {
String[] command = {"C:\\\\Program Files\\\\Git\\\\git-bash.exe",
"D:\\temp\\test.sh",
"param1"};
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectErrorStream(true);
processBuilder.start();
}
There are a couple issues with your code:
You don't seem to be inspecting the stderr/stdout of the program, or inspecting the Exception that gets thrown.
Git.exe doesn't take shell scripts as the first argument. As #reos says, you probably need to invoke git-bash.exe rather than git.exe

bash script not waiting for completion of commands when called from java

I am running the following bash script
scrapy crawl flipkart -a key="$1" -o "$2"flipkart.xml
scrapy crawl myntra -a key="$1" -o "$2"myntra.xml
scrapy crawl jabong -a key="$1" -o "$2"jabong.xml
echo " scrapy completed"
The bash script when executed through the terminal is running as expected as in it completes one execution of the scrapy command then the other but when i try to invoke it through java the same script does not execute the scrapy commands.
It executes the shell script as i am able to read the echo data through the input stream in java.
String command = "/Users/renny/Documents/WorkSpaces/Scrapy/tutorial/tutorial/crawls.sh";
String[] cmd = new String[]{"/bin/sh", command,key,formattedDate};
//Process p = Runtime.getRuntime().exec(cmd);
ProcessBuilder p = new ProcessBuilder(cmd);
Process p2 = p.start();
InputStream error = p2.getErrorStream();
for (int i = 0; i < error.available(); i++) {
System.out.println("" + error.read());
}
BufferedReader br = new BufferedReader(new InputStreamReader(p2.getInputStream()));
String line;
System.out.println("Output of running " + command + " is: ");
please suggest me how i can ensure that the scrapy commands get executed.
In a batch file i think we could have called start to ensure that the commands run in separate prompts is there something similar i can do in bash scripts
export PATH=usr/local/bin/scrapy:$PATH
export PATH=/usr/local/bin:$PATH
Adding the export path to the script file solved the issue thanks #RealSkeptic.
By using start, you are asking to start the batch file in the background.
Call Process#waitFor():
Causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.
Also you will get the exit value of the subprocess. If successfully code 0, or non-zeroif error exit code`.

Java throws Process exitValue: 127 when running expect script

I'm trying a new approach to a hitch I've been stuck on. Instead of using expect4j for my SSH connection, (I couldn't figure out a way past blocking consumer runs and issues with closures, see past posts for more info on that if you're knowledgeable and feeling saintly,) I'm going to try to use an expect script. I have a runtime exec coded in to a button.onclick, see below. Why am I getting a 127 exit value? I basically just need this expect script to ssh in, run a single set of expect and send, give me the readout, and that's it...
I'm using cygwin. Not sure if that's relevant to why this isn't working...is my sh-bang line pointing to the right place? My cygwin install is a full install, all packages, in C:\cygwin.
Why am I getting a 127 exit value instead of a readout from my server, and how do I alleviate this?
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec( new String [] {"C:\\cygwin\\bin\\bash.exe", "C:\\scripts\\login.exp"});
InputStream stdin = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdin);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<OUTPUT>");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("</OUTPUT>");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
#!/usr/bin/expect -f
spawn ssh userid#xxx.xxx.xxx.xxx password
match_max 100000
expect "/r/nDestination: "
send -- "xxxxxx\r"
expect eof
The problem is that you use bash to execute an expect script. You need to use expect to execute an expect script, or bash to execute an expect script by means of a shell commandline (that would be Process proc = rt.exec( new String [] {"C:\\cygwin\\bin\\bash.exe", "-c", "C:\\scripts\\login.exp"});, note the "-c" which I have inserted) which makes use of the magic shebang at the top of your script. Or better, use only the shebang: Process proc = rt.exec( new String [] {"C:\\scripts\\login.exp"});
The exit value of 127 is a special exit value, and tells you "command not found". Which makes sense as you expect script contains many words for which no system binaries or shell builtins exist.

running Echo from Java

I'm trying out the Runtime.exec() method to run a command line process.
I wrote this sample code, which runs without problems but doesn't produce a file at c:\tmp.txt.
String cmdLine = "echo foo > c:\\tmp.txt";
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(cmdLine);
BufferedReader input = new BufferedReader(
new InputStreamReader(pr.getInputStream()));
String line;
StringBuilder output = new StringBuilder();
while ((line = input.readLine()) != null) {
output.append(line);
}
int exitVal = pr.waitFor();
logger.info(String.format("Ran command '%s', got exit code %d, output:\n%s", cmdLine, exitVal, output));
The output is
INFO 21-04 20:02:03,024 - Ran command
'echo foo > c:\tmp.txt', got exit code
0, output: foo > c:\tmp.txt
echo is not a standalone command under Windows, but embedded in cmd.exe.
I believe you need to invoke a command like "cmd.exe /C echo ...".
The > is intrepreted by the shell, when echo is run in the cmmand line, and it's the shell who create the file.
When you use it from Java, there is no shell, and what the command sees as argument is :
"foo > c:\tmp.txt"
( Which you can confirm, from the execution output )
You can't just pass "> c:\tmp.txt" to Runtime.exec as part of the command line to make redirection happen. From the Javadocs: "All its standard io (i.e. stdin, stdout, stderr) operations will be redirected to the parent process through three streams (getOutputStream(), getInputStream(), getErrorStream())."
If you want to redirect output to a file, to the best of my knowledge the only way to do that would be to open the file in Java, do getInputStream, and then read from the process's input stream and write to the desired file.

Categories

Resources