Java Runtime not capturing STDOUT on Mac - java

Mac OS here, but looking for a solution that is platform agnostic. Also please note, even though Consul is mentioned here, it is just arbitrary and the solution should have nothing to do with, nor require knowledge of, Consul.
When I open a shell and run consul -v (to determine if Consul is installed locally), I get the following STDOUT:
Consul v0.5.2
Consul Protocol: 2 (Understands back to: 1)
When I run the following code:
public class VerifyConsul {
public static void main(String[] args) {
PrintStream oldPS = System.out;
try {
Runtime runtime = Runtime.getRuntime();
Process proc;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream newPS = new PrintStream(baos);
System.setOut(newPS);
proc = runtime.exec(“consul -v”);
proc.waitFor();
String capturedOut = baos.toString();
if(capturedOut.isEmpty()) {
throw new IllegalArgumentException(“Consul not found.”);
}
} catch(Throwable t) {
System.out.println(t.getMessage());
System.setOut(oldPS);
}
}
}
I get the IllegalArgumentException stating that Consul [is] not found.
What is wrong with my code? Why isn’t it “hooking”/capturing STDOUT?

Use Process#getInputStream() to read STDOUT or Process#getErrorStream() to read STDERR
Here's an example (using java process and reading STDERR):
package so32589604;
import org.apache.commons.io.IOUtils;
public class App {
public static void main(String[] args) throws Exception {
final Runtime runtime = Runtime.getRuntime();
final Process proc = runtime.exec("java -version");
proc.waitFor();
// IOUtils from apache commons-io
final String capturedOut = IOUtils.toString(proc.getErrorStream());
System.out.println("output = " + capturedOut);
if(capturedOut.isEmpty()) {
throw new IllegalArgumentException("Java not found.");
}
}
}

Related

ADB PULL Command

I am trying to use adb for working with the files in my device from a MAC PC.
One of my folders in my phone has a space in it, so I looked around and tried using escape i.e \ and also using quotes with as given below
import java.io.*;
public class TestModule {
public static void main(String[] args) throws IOException,InterruptedException {
String line = "null";
String cmd = "adb pull /storage/sdcard1/Android/data/files/test\\ Information/ /Users/sbc/Desktop";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
while ((line=buf.readLine())!=null) {
System.out.println(line);
}
}
}
I ran the same command in terminal I can access the file but through java it gives me remote object does not exist error.
Any help is very much appreciated
I found a workaround for my problem, posting code below,
import java.io.*;
public class TestModule {
public static void main(String[] args) throws IOException,InterruptedException {
String line = "null";
String cmd = "adb pull /storage/sdcard1/Android/data/files /Users/sbc/Desktop";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
while ((line=buf.readLine())!=null) {
System.out.println(line);
}
}
}
In place of accessing the folder with the space, I accessed it's parent folder
/storage/sdcard1/Android/data/files/test\ Information/<--current folder with space
/storage/sdcard1/Android/data/files<--Parent Folder.
Now adb downloads all the contents of "Parent Folder"

Run the appium server programmatically

I am trying to run the Appium server programmatically. I tried all the possible options that Appium is providing, but not getting any result
From the command line, if I am trying C:\Users\User>appium it's starting the server. How to do the same by using java code?
Note: the version of Appium is 1.6.5
AppiumDriverLocalService service=AppiumDriverLocalService.buildDefaultService();
service.start();
This the code what i am using to run the appium server programmatically .
The error i am getting is
java.lang.NoClassDefFoundError: org/apache/commons/validator/routines/InetAddressValidator
Did you tried this,
import java.io.*;
public class CmdTest {
public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime().exec("appium");
}
}
I know you are asking for Java, but I do this programmatically with C#. So I paste my solution in case it can help to get an idea:
C# Code:
public void startAppiumServerLocally()
{
try
{
string nodejs = "\"" + Environment.GetEnvironmentVariable("nodejs") + "\""; // Environment path for node.exe
string appium = "\"" + Environment.GetEnvironmentVariable("appium") + "\""; // Environment path for main.js or appium.js
ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(nodejs);
myProcessStartInfo.UseShellExecute = false;
myProcessStartInfo.RedirectStandardOutput = true;
myProcessStartInfo.RedirectStandardError = true;
myProcessStartInfo.CreateNoWindow = true;
// getOverride() method returns '--session-override'
// getDesiredCapabilitiesJson() returns a JSON with some capabilities '--default-capabilities {"udid":identifier..., deviceName: "Samsung S7"....}'
// getDriverPort() returns --port X just in case I need to start in a different and unused port.
string args = appium + getOverride() + getDesiredCapabilitiesJson() + getDriverPort();
myProcessStartInfo.Arguments = args;
nodeProcess = new Process();
nodeProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
nodeProcess.StartInfo = myProcessStartInfo;
nodeProcess.Start();
nodeProcess.BeginErrorReadLine();
StreamReader myStreamReader = nodeProcess.StandardOutput;
while (_bAppiumForceEnd == false)
{
if (_bAppiumInit == false)
{
string line = myStreamReader.ReadLine();
if (line.Contains("listener started"))
{
// _bAppiumInit is a flag to start my tests once the server started
_bAppiumInit = true;
}
}
else
{
myStreamReader.ReadLine();
}
}
myStreamReader.Close();
}
catch (Exception e)
{
//Log(e.Message);
}
}
I know that creating a while loop is not the best solution, but sometimes my nodeProcess was not stoping... So I changed it to this way, and it works perfectly.
Make sure you installed Appium globally...
npm install -g appium
Here is how you start and stop appium server programmatically using Java code
import java.nio.file.Paths;
public class AppiumSetupAndTearDown {
public static void startAppiumServer() throws IOException, InterruptedException {
String logDir = <the path where you want to create the appium output file>;
File appiumOutput = new File(logDir);
if (!appiumOutput.exists()) {
boolean status = appiumOutput.createNewFile();
if (!status) {
throw new IOException("Failed to create Appium output file!");
}
}
String cmd[] = {"/bin/bash", Paths.get(System.getProperty("user.dir")).getParent().getParent().toString() + "/Modules/Shared/startAppium.sh"};
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectError(new File(logDir));
pb.redirectInput(new File(logDir));
pb.redirectOutput(new File(logDir));
pb.start();
System.out.println("Appium server started!");
}
public static void stopAppiumServer() throws IOException, InterruptedException {
String cmd[] = {"/bin/bash", Paths.get(System.getProperty("user.dir")).getParent().getParent().toString() + "/Modules/Shared/stopAppium.sh"};
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.start();
System.out.println("Appium server stopped!");
}
}
You can also add Thread.sleep(5000) after starting and stopping the appium server in case you run into timing issues.
Try to addthe commons validator lib to your classpath/pom.xml (commons-validator-1.4.0.jar)

Run java -jar from exec

I'm try to run:
java -jar /home/user/workspace/maltparser-1.8/maltparser-1.8.jar
This is work. And return:
-----------------------------------------------------------------------------
MaltParser 1.8
-----------------------------------------------------------------------------
MALT (Models and Algorithms for Language Technology) Group
Vaxjo University and Uppsala University
Sweden
-----------------------------------------------------------------------------
Usage: java -jar maltparser-1.8.jar -f <path to option file> <options> java -jar maltparser-1.8.jar -h for more help and options
help ( -h) : Show options
----------------------------------------------------------------------------- option_file ( -f) : Path to option file
----------------------------------------------------------------------------- verbosity *( -v) : Verbosity level debug - Logging of debugging messages error - Logging of error events fatal - Logging of very severe error events info
- Logging of informational messages off - Logging turned off warn - Logging of harmful situations
-----------------------------------------------------------------------------
Documentation: docs/index.html
And now, I'm try to run this .jar from my class:
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
Process ps = Runtime.getRuntime().exec(new String[]{"java","-jar","/home/user/workspace/maltparser-1.8/maltparser-1.8.jar"});
ps.waitFor();
java.io.InputStream is=ps.getInputStream();
byte b[]=new byte[is.available()];
is.read(b,0,b.length);
System.out.println(new String(b));
}
}
And it return me nothing... I want to intercept output stream. How I can do it?
IMHO, the your method of reading the InputStream is a little weird, you probably don't want to wait till the stream is fill before printing something out, also, you ignoring the error stream...
I prefer to use ProcessBuilder because...
You can redirect the error stream to the InputStream, which makes it easier to manage and
You can change the context of the working directory from which the command will be started in...
As an example...
try {
ProcessBuilder pb = new ProcessBuilder(new String[]{"java", "-jar", "Your.jar"});
pb.redirectError();
//pb.directory(new File("you/path"));
Process ps = pb.start();
try (java.io.InputStream is = ps.getInputStream()) {
int read = -1;
while ((read = is.read()) != -1) {
System.out.print((char) read);
}
}
System.out.println("Command exited with: " + ps.waitFor());
} catch (IOException | InterruptedException exp) {
exp.printStackTrace();
}
Updated
For reasons that I'm unaware of, output sent through log4j's ConsoleAppender doesn't seem to reach the Processs InputStream...
To resolve this, you can use ProcessBuilders inheritIO...
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class TestRunJar {
public static void main(String[] args) {
try {
ProcessBuilder pb = new ProcessBuilder(new String[]{"java", "-jar", "/../maltparser-1.8.jar"});
pb.inheritIO();
pb.redirectError();
pb.directory(new File("/..")); // Path to where maltparser-1.8.jar resides
Process ps = pb.start();
InputStreamConsumer stdout = new InputStreamConsumer(ps.getInputStream());
InputStreamConsumer stderr = new InputStreamConsumer(ps.getErrorStream());
stderr.start();
stdout.start();
stderr.join();
stderr.join();
System.out.println("Command exited with: " + ps.waitFor());
} catch (IOException | InterruptedException exp) {
exp.printStackTrace();
}
}
public static class InputStreamConsumer extends Thread {
private InputStream is;
private IOException exp;
private StringBuilder output;
public InputStreamConsumer(InputStream is) {
this.is = is;
}
#Override
public void run() {
int in = -1;
output = new StringBuilder(64);
try {
while ((in = is.read()) != -1) {
output.append((char) in);
}
} catch (IOException ex) {
ex.printStackTrace();
exp = ex;
}
}
public StringBuilder getOutput() {
return output;
}
public IOException getException() {
return exp;
}
}
}
This is just my test code, so it might be a little over the top ;)
Which finally dumped out...
-----------------------------------------------------------------------------
MaltParser 1.8
-----------------------------------------------------------------------------
MALT (Models and Algorithms for Language Technology) Group
Vaxjo University and Uppsala University
Sweden
-----------------------------------------------------------------------------
Usage:
java -jar maltparser-1.8.jar -f <path to option file> <options>
java -jar maltparser-1.8.jar -h for more help and options
help ( -h) : Show options
-----------------------------------------------------------------------------
option_file ( -f) : Path to option file
-----------------------------------------------------------------------------
verbosity *( -v) : Verbosity level
debug - Logging of debugging messages
error - Logging of error events
fatal - Logging of very severe error events
info - Logging of informational messages
off - Logging turned off
warn - Logging of harmful situations
-----------------------------------------------------------------------------
Documentation: docs/index.html
Command exited with: 0

Java command to show the processus

hi i want to show the jboss 7 as process information and the database sessions information in java code...
i try this code:
Process p = Runtime.getRuntime().exec
(System.getenv("windir") +"\\system32\\"+"tasklist.exe");
and this code:
Process p = Runtime.getRuntime().exec
("C:\\Users\\user\\Downloads\\PSTools\\pslist.exe -s 2");
and it works good but it works only on windows operating system .
so i want to a java code which work on each operating system, and not only on windows or linux ...
can u help me please?
thanks for everybody.
Finding java processes on the same host is fairly straight forward (some caveats listed later). Connecting to their JMX interfaces is also achievable. As far as tracking database sessions, you can conceptually acquire any data you want, as long as it is published through an accessible MBean.
The process requires using the Java Attach API. Here's a simple example where I will list all the JVM's running on my host, attempt to attach to them and list their heap usage.
First off, here's the imports:
import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import java.util.List;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
The com.sun.tools.attach classes are in your JVM's tools.jar. Here's the code:
public class AttachAPIExample {
/**
* Uses the attach API to locate all JVMs accessible on this machine.
* #param args None
*/
public static void main(String[] args) {
// Get my PID
final String MYPID = ManagementFactory.getRuntimeMXBean().getName().split("#")[0];
log("Scanning for JVMs...");
// List all the Virtual Machine Descriptors
List<VirtualMachineDescriptor> descriptors = VirtualMachine.list();
for(VirtualMachineDescriptor vmd: descriptors) {
VirtualMachine vm = null;
// Do this in a catch block in case we run into a JVM that is not the same "bit" as we are
try {
vm = vmd.provider().attachVirtualMachine(vmd.id());
String display = vmd.displayName().trim().isEmpty() ? "Unknown" : vmd.displayName();
log("JVM%sPID: %s Display: %s", vmd.id().equals(MYPID) ? " (Me) " : " ", vmd.id(), display);
String connectorAddress = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress", null);
if(connectorAddress!=null) {
log("\tConnector Found Installed at [%s]", connectorAddress);
} else {
String javaHome = vm.getSystemProperties().getProperty("java.home");
File agentJarFile = new File(javaHome + File.separator + "lib" + File.separator + "management-agent.jar");
if(agentJarFile.exists()) {
log("I think we can find this JVM's management agent here: [%s]", agentJarFile.toString());
vm.loadAgent(agentJarFile.getAbsolutePath());
connectorAddress = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress", null);
log("\tConnector Installed at [%s]", connectorAddress);
} else {
log("Cannot find the agent jar for JVM [%s] at [%s]", vmd.id(), javaHome);
}
}
// Now lets try and connect and read some MBean values
if(connectorAddress!=null) {
log("Attaching to JVM [%s]...", vmd.id());
JMXServiceURL jmxUrl = new JMXServiceURL(connectorAddress);
JMXConnector connector = null;
try {
connector = JMXConnectorFactory.connect(jmxUrl);
MBeanServerConnection conn = connector.getMBeanServerConnection();
MemoryUsage heap = MemoryUsage.from((CompositeData)conn.getAttribute(new ObjectName(ManagementFactory.MEMORY_MXBEAN_NAME), "HeapMemoryUsage"));
log("Heap Usage: %s", heap);
} finally {
if(connector!=null) {
try { connector.close(); } catch (Exception ex) {/* No Op */}
}
}
}
} catch (Exception ex) {
/* No Op */
} finally {
if(vm!=null) try { vm.detach(); } catch (Exception ex) {/* No Op */}
log("======================================");
}
}
}
public static void log(String fmt, Object...args) {
System.out.println(String.format(fmt, args));
}
}
And here's some sample output:
Scanning for JVMs...
JVM PID: 27928 Display: sun.tools.jconsole.JConsole
Connector Found Installed at [service:jmx:rmi://127.0.0.1/stub/rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LnJlbW90ZS5ybWkuUk1JU2VydmVySW1wbF9TdHViAAAAAAAAAAICAAB4cgAaamF2YS5ybWkuc2VydmVyLlJlbW90ZVN0dWLp/tzJi+FlGgIAAHhyABxqYXZhLnJtaS5zZXJ2ZXIuUmVtb3RlT2JqZWN002G0kQxhMx4DAAB4cHc3AAtVbmljYXN0UmVmMgAADDEwLjEyLjExNC4zNwAA9bhcC21U1Z9PMPLlR/0AAAFAxsF5moACAHg=]
Attaching to JVM [27928]...
Heap Usage: init = 8388608(8192K) used = 40242696(39299K) committed = 44236800(43200K) max = 5726666752(5592448K)
======================================
JVM PID: 25028 Display: org.jboss.Main -c ecseu -b 0.0.0.0
I think we can find this JVM's management agent here: [c:\java\jdk1.6.0_30\jre\lib\management-agent.jar]
Connector Installed at [service:jmx:rmi://127.0.0.1/stub/rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LnJlbW90ZS5ybWkuUk1JU2VydmVySW1wbF9TdHViAAAAAAAAAAICAAB4cgAaamF2YS5ybWkuc2VydmVyLlJlbW90ZVN0dWLp/tzJi+FlGgIAAHhyABxqYXZhLnJtaS5zZXJ2ZXIuUmVtb3RlT2JqZWN002G0kQxhMx4DAAB4cHc4AAtVbmljYXN0UmVmMgAADVBQLVdLLU5XSEktMDEAAPjJTzYbxtjrUKazaPTEAAABQMuKX+6ABAB4]
Attaching to JVM [25028]...
Heap Usage: init = 1073741824(1048576K) used = 173876432(169801K) committed = 982581248(959552K) max = 982581248(959552K)
======================================
Caveats
JMVs can only attach to like bit JVMs (i.e. 32bit to 32bit, 64bit to 64bit)
The OS user launching the attach must have the OS authorization to access other processed. So same user, no problem. Other user... you should be root.
The attach api has mixed results when used across different JVM vendor implementations. ie. if it's Sun/Oracle/OpenJDK, you're probably good. If it's those, and you're trying to connect to an IBM JVM (or vice-versa) then I have no idea what will happen, although JRockit seems to be fairly friendly in this regard.
I don't know all the caveats.

Running java program from another java program

I'm trying to run a Java program from another Java application. Here is my code:
public class Main {
public static int Exec() throws IOException {
Process p = Runtime.getRuntime().exec("javac -d C:/Users/Dinara/Desktop/D/bin "
+ "C:/Users/Dinara/Desktop/D/src/test.java");
Process p1 = Runtime.getRuntime().exec("java -classpath C:/Users/Dinara/Desktop/D/bin test");
return 0;
}
public static void main(String[] args) throws IOException {
Exec();
}
}
javac works fine and creates test.class file in bin directory. However java -classpath C:/Users/Dinara/Desktop/D/bin test does not run the test.class file.
the content of the test.java:
import java.io.*;
class test {
public static void main(String args[]) {
try {
FileWriter fstream = new FileWriter("out.txt");
BufferedWriter out = new BufferedWriter(fstream);
out.write("Hello Java");
out.close();
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
I suppose that something wrong with recognizing Java command. Could you please give me a sample code for fixing this problem or share idea? I'm using Netbeans to run Main class and the location of the application folder is C:\Users\Dinara\Main
Use
System.getProperty("java.home") + "/bin/java -classpath C:/Users/Dinara/Desktop/D/bin test"
instead of
"java -classpath C:/Users/Dinara/Desktop/D/bin test"
You need to supply the full path to the javac, exec won't use the ath to find it for you

Categories

Resources