How does java run a batch file in the background?
I have a batch file with the following content
#echo off
:start
start /b cmd /c example.exe -c config >nul 2>&1
goto :eof
In fact, I run this code under the command line, it can run in the background, but it seems that the "execution" of the java call will hang on the console on the idea, I am a java novice and I don't know the principle.
java code:
package com.example;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
public class Example {
public static void main(String[] args) throws Exception{
System.out.println("Hello World");
System.out.println("Started.");
String script_path = "";
boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows");
System.out.println(isWindows);
if (isWindows) {
System.out.println("it's Windows");
script_path = "c:/users/test-running/desktop/example.bat";
CommandLine cmdLine = new CommandLine("cmd");
cmdLine.addArgument(script_path);
cmdLine.addArgument("start").addArgument("server");
DefaultExecutor executor = new DefaultExecutor();
executor.execute(cmdLine);
System.out.println("Finished.");
} else {
System.out.println("it's Linux");
script_path = "/Users/seth/Downloads/example.sh";
CommandLine cmdLine = new CommandLine("/bin/bash");
cmdLine.addArgument(script_path);
cmdLine.addArgument("start").addArgument("server");
DefaultExecutor executor = new DefaultExecutor();
executor.execute(cmdLine);
System.out.println("Finished.");
}
}
}
So does anyone know what java is doing? Or is the syntax of the batch file wrong?
Related
The following command works well in command line
shp2pgsql -s 4326 /Users/abc.shp | psql -U user1 -h localhost -p 5432 -d postgis
However when I run the following command in Java using ProcessBuilder it says command not found. Here is the code:
public static void main(String arg[]) throws Exception {
ProcessBuilder pb =
new ProcessBuilder("/bin/sh -c shp2pgsql /Users/abc.shp | psql -U user1 -h localhost -p 5432 -d postgis");
Process p = pb.start();
showOutput(p.getInputStream(), System.out);
showOutput(p.getErrorStream(), System.err);
}
private static void showOutput(final InputStream src, final PrintStream dest) {
new Thread(new Runnable() {
public void run() {
Scanner sc = new Scanner(src);
while (sc.hasNextLine()) {
dest.println(sc.nextLine());
}
}
}).start();
}
It seems that Java does not understand where the path of your environment (psql or shp2pgsql ..) is
You need to specify the path so that it can execute. It is usually in /usr/local/bin or usr/bin. Also, note the argument for "/bin/sh and "-c" (this you specify the command your going to execute is in string format)is separate. Just modify the following snippet. It should work!!
String env = "/usr/local/bin/";
ProcessBuilder pb =
new ProcessBuilder("/bin/sh", "-c", env +"shp2pgsql /Users/abc.shp | "+env+"psql -U user1 -h localhost -p 5432 -d postgis");
Process p = pb.start();
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)
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
I know that I can run non GUI jar files from the command line. Is there any way that can do so by clicking or something and not writing the commands again and again.? Is there any software to do so. ( I am talking about a compiled jar and don't want to run from any ide)
public static final String TITLE = "CONSOLE title";
public static final String FILENAME = "myjar.jar";
public static void main(String[] args) throws InterruptedException, IOException {
if(args.length==0 || !args[args.length-1].equals("terminal")) {
String[] command;
if(System.getProperty("os.name").toLowerCase().contains("win")) {
command = new String[]{"cmd", "/c", "start \"title \\\""+TITLE+"\\\" & java -jar \\\""+new File(FILENAME).getAbsolutePath()+"\\\" terminal\""};
} else {
command =new String[]{"sh", "-c", "gnome-terminal -t \""+TITLE+"\" -x sh -c \"java -jar \\\""+new File(FILENAME).getAbsolutePath()+"\\\" terminal\""};
}
try {
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
} catch(Throwable t){
t.printStackTrace();
}
} else {
//THERE IS YOUR CONSOLE PROGRAM:
System.out.println("Hey! What's your name?");
String read = new BufferedReader(new InputStreamReader(System.in)).readLine();
System.out.println("Hey, "+read+"!");
Thread.sleep(10000);
}
}
You can run it with double clicking on .jar file. Don't forget about MANIFEST.MF! :) (working on linux, also!)
Example (I only double clicked on jar file):
The way intended by Java is that you call java -jar XXXX.jar on the jars you need. Drawback is that you can't specify a classpath so all classes should be there.
A cooler way to package an application is by using Java WebStart. With that the user installs the application jut by clicking on a web browser. Check here http://docs.oracle.com/javase/8/docs/technotes/guides/javaws/developersguide/contents.html
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