You can only call the main method. Design your main method such that it calls the method you want.
When I say call main method, you don't explicitly invoke it. It's the only entry point to a java program when you invoke it.
If your class looks like:
package com.foo;
public class Test {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
You can use the following command line to invoke the main from within the directory where you can find com/foo/Test.class (If you're in the classes directory in the structure shown far below):
java com.foo.Test
If you want to do so from a different (See the directory structure far below) directory, then you'll have to set classpath.
java -cp /path/to/classes com.foo.Test
Assume the below directory structure for clarity.
-path
-to
-classes
-com
-foo
>Test.class
Answer from adarshr on Stack OverflowYou can only call the main method. Design your main method such that it calls the method you want.
When I say call main method, you don't explicitly invoke it. It's the only entry point to a java program when you invoke it.
If your class looks like:
package com.foo;
public class Test {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
You can use the following command line to invoke the main from within the directory where you can find com/foo/Test.class (If you're in the classes directory in the structure shown far below):
java com.foo.Test
If you want to do so from a different (See the directory structure far below) directory, then you'll have to set classpath.
java -cp /path/to/classes com.foo.Test
Assume the below directory structure for clarity.
-path
-to
-classes
-com
-foo
>Test.class
You can't execute an arbitrary method directly from a shell script, you'll need to have that method exposed externally in some way.
The simplest way of course is to write a main method that directly invokes the code you want to test.
Alternatively, you could make use of a Java application that takes parameters to act as a sort of launcher. In its crudest form you can imagine an app that takes a classname and method name as arguments, then instantiates the class and invokes the method via reflection. In a similar vein, but a bit more elegant, we use an app that invokes operations exposed via JMX in order to fire certain methods on a server when required.
Ultimately though, bash (or equivalent) doesn't understand JVM bytecode. You will need to launch a Java process to run the method, which will involve executing some main method that in turn invokes what you need.
Videos
You should really look at Process Builder. It is really built for this kind of thing.
ProcessBuilder pb = new ProcessBuilder("myshellScript.sh", "myArg1", "myArg2");
Map<String, String> env = pb.environment();
env.put("VAR1", "myValue");
env.remove("OTHERVAR");
env.put("VAR2", env.get("VAR1") + "suffix");
pb.directory(new File("myDir"));
Process p = pb.start();
You can use Apache Commons exec library also.
Example :
package testShellScript;
import java.io.IOException;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
public class TestScript {
int iExitValue;
String sCommandString;
public void runScript(String command){
sCommandString = command;
CommandLine oCmdLine = CommandLine.parse(sCommandString);
DefaultExecutor oDefaultExecutor = new DefaultExecutor();
oDefaultExecutor.setExitValue(0);
try {
iExitValue = oDefaultExecutor.execute(oCmdLine);
} catch (ExecuteException e) {
System.err.println("Execution failed.");
e.printStackTrace();
} catch (IOException e) {
System.err.println("permission denied.");
e.printStackTrace();
}
}
public static void main(String args[]){
TestScript testScript = new TestScript();
testScript.runScript("sh /root/Desktop/testScript.sh");
}
}
For further reference, An example is given on Apache Doc also.
I don't know anything about Java, but I can show you a proof of concept. Say we have localfile.txt:
Here is the local file.
and on the remote machine, we have remote.sh:
#!/bin/bash
cat /dev/stdin
Note that the script on the remote machine invokes a program which reads from stdin. Then pass the contents of localfile.txt to your ssh command:
user@local:~$ cat localfile.txt | ssh user@remote remote.sh
Here is the local file.
Your Java program is trying to read a file which does not exist on the remote machine. I guess you could try to mimic a local file.
Change remote.sh to:
#!/bin/bash
cat "$@"
and invoke it with
user@local:~$ cat localfile.txt | ssh user@remote 'remote.sh <(cat /dev/stdin)'
Here is the local file.
I think it would be easier to change that part in your Java program to read from stdin.
I guess things might get messy if localfile.txt contains anything that might be interpreted by the shell as expandable (such as *), but that's for you to figure out.
The problem is that the shell redirection (<) sends the file over the ssh tunnel. And the Java class is expecting not the file, but a string with the "filename" of a local file that will be read with a FileReader.
Instead of passing the filename to the FileReader, read from the standard input.
InputStreamReader isReader = new InputStreamReader(System.in);
BufferedReader iR = new BufferedReader (isReader);
Used this as a reference: https://stackoverflow.com/questions/5724646/how-to-pipe-input-to-java-program-with-bash
Now your class will be:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
public class ReadFirstLine
{
public static void main(String[] args) throws Exception
{
String filename = args[0];
System.out.println(filename);
//BufferedReader iR = new BufferedReader (new FileReader(filename));
InputStreamReader isReader = new InputStreamReader(System.in);
BufferedReader iR = new BufferedReader (isReader);
BufferedWriter oW = new BufferedWriter(new OutputStreamWriter(System.out));
//outputWriter.write(iR.readLine());
System.out.println(iR.readLine());
iR.close();
oW.close();
}
}
But for this task I would definitely use instead:
head -1 filename.txt
:)
At the end of the shell command, you can put the &. It makes the program run in a subshell.
java -cp /.../.../....jar ClassWithMain &
Adding & to the end will send Java to the background. That means that Java will run in the background and the shell script will continue running. But once the shell script reaches the end, it will wait for Java to finish before it exits. You have to disown the java program, and then the script will exit and java will continue to run. Just add the command "disown" directly below where you run the jar file.
create a file named "sync" in /usr/bin containing the following:
java -jar {PATH TO JARFILE} $1 $2
Replace {PATH TO JARFILE} with the path to the jarfile
Make the file executable by typing chmod +x sync while in /usr/bin
you can create a shell with name say "run.sh" (note .sh extension which tell it is a shell script) and copy it in /usr/local/bin directory.
1.Script (run.sh)
#!/bin/sh
arg1=$1
arg2=$2
##directory where jar file is located
dir=/directory-path/to/jar-file/
##jar file name
jar_name=json-simple-1.1.1.jar
## Permform some validation on input arguments, one example below
if [ -z "$1" ] || [ -z "$2" ]; then
echo "Missing arguments, exiting.."
echo "Usage : $0 arg1 arg2"
exit 1
fi
java -jar $dir/$jar_name arg1 arg2
copy the script in /usr/local/bin
cp run.sh /usr/local/bin
Give execute permission to the script
chmod u+x /usr/local/bin/test.sh
now you can type just word run or run.sh on command line : shell will auto-complete the script name and also it can executed by pressing enter key.