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();
Answer from Milhous on Stack Overflowcan java run shell script on a windows system?
bash - How to execute shell script on windows using JAVA - Stack Overflow
windows - Java code to execute a .sh file - Stack Overflow
Java program to run shell commands from a windows machine - Stack Overflow
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.
https://www.baeldung.com/run-shell-command-in-java
so, java uses linux, and as a way to cut down on coding projects time to completion, I was wondering, if there is a bash sdk or something similar for java that can be wrapped into a jar and used to make an executable, that way a windows computer can run it, and a linux computer can as well..
I want to be able to run code from other programming languages that utilize terminal, but... I don't expect end users to be able to set up bash or even work terminal, I could write batch scripts and have two different downloads or I could have the code ping for the OS of the system and send the user to one of the two, but if possible this would be really helpful to know going forward...
just wondering if anyone knows of a package that can be wrapped in for bash integration for your jar so the scripts run within the jvm and not called by it...
Make sure bash.exe is in PATH as Charles Duffy said. Having bash installed without that being the case, is, after all, not much use. When that's the case and your script is in the current directory, the following is equivalent to your code:
public class Test {
public static void main(String[] args) throws Exception {
String[] command = { "bash", "test.sh" };
ProcessBuilder pb = new ProcessBuilder(command).inheritIO();
Process p = pb.start();
p.waitFor();
System.out.println(p.exitValue());
}
}
Note: You should use ProcessBuilder to launch as it provides better control over I/O streams, and the Runtime.exec call you use is deprecated. However the outcome would be the same in your case.
The issue here is that bash on Windows is expecting a Linux style pathname, and you are passing in Windows OS pathname.
Your Path environment for bash.exe is correct because you don't get IOException : Cannot run program "bash.exe": CreateProcess error=2, The system cannot find the file specified.
Thus bash.exe has run, but it reports exit code 127 which means Command not found, or PATH error. To fix you need to form valid GNU/Linux pathname to the script. If you are using WSL the C drive is mapped as "/mnt/c" so you need to run the translated path:
String[] cmd = new String[]{ "bash.exe", "/mnt/c/Users/abc/Downloads/test.sh" };
// Using "bash" above should also work if "bash.exe" is in the Path and PATHEXT contains ".EXE"
Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();
p.getInputStream().transferTo(System.out);
System.out.println(p.waitFor());
You could avoid the OS pathname translation by using a relative path to the script and run from it's directory:
File exe = new File("C:\\Users\\abc\\Downloads\\test.sh");
// Set up relative path for the script
String[] cmd = new String[]{"bash", exe.getName()};
ProcessBuilder pb = new ProcessBuilder(cmd).redirectErrorStream(true);
// Run from the directory of the script:
pb.directory(exe.getParentFile());
Process p = pb.start();
p.getInputStream().transferTo(System.out);
System.out.println(p.waitFor());
To execute a .sh script on Windows, you would have to have a suitable command interpreter installed. For example, you could install the Cygwin environment on your Windows box and use it's bash interpreter.
However, Windows is not Linux even with Cygwin. Some scripts will not port from one environment to the other without alterations. If I had a problem executing a script via Java in Linux environment, I would prefer to debug the issue in that environment.
Remember, you could start your Java process on Linux in debug mode and attach your IDE debugger in Windows to that remote process.
Thanks everybody for your responses. I found a solution to the problem. For this kind of situation we need to bind my Windows machine to Linux system. Here is the code that worked:
Copypublic String executeSHFile(String Username, String Password,String Hostname)
{
String hostname = Hostname;
String username = Username;
String password = Password;
try{
Connection conn = new Connection(hostname);
conn.connect();
boolean isAuthenticated = conn.authenticateWithPassword(username, password);
if (isAuthenticated == false)
throw new IOException("Authentication failed.");
Session sess = conn.openSession();
sess.execCommand("sh //full path/file name.sh");
System.out.println("Here is some information about the remote host:");
InputStream stdout = new StreamGobbler(sess.getStdout());
BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
while (true)
{
String line = br.readLine();
if (line == null)
break;
current_time=line;
System.out.println(line);
}
System.out.println("ExitCode: " + sess.getExitStatus());
/* Close this session */
sess.close();
/* Close the connection */
conn.close();
}catch(IOException e)
{
e.printStackTrace(System.err);
System.exit(2);
}finally{
}
}
Thank you.
try Jsch From here to get the shell scrips executed from Java to some remote Linux machine. I have worked on this and it was really fun.although you may find little shortage of docs for understanding this but you can overcome that easily.
Also consider ExpectJ which is a wrapper around TCL Expect. The project does not appear to have any active development since mid 2010, but I have used it for SSH in the past.
http://expectj.sourceforge.net/apidocs/expectj/SshSpawn.html