C'est assez simple d'exécuter une commande Unix à partir de Java.
Runtime.getRuntime().exec(myCommand);
Mais est-il possible d'exécuter un script Shell Unix à partir de code Java? Si tel est le cas, serait-il utile d’exécuter un script Shell à partir de code Java?
Vous devriez vraiment regarder Process Builder . C'est vraiment construit pour ce genre de chose.
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();
Je dirais que ce n’est pas dans l’esprit de Java d’exécuter un script Shell à partir de Java. Java est conçu pour être multi-plateforme, et exécuter un script Shell limiterait son utilisation à seulement UNIX.
Cela dit, il est certainement possible d’exécuter un script Shell à partir de Java. Vous utiliseriez exactement la même syntaxe que celle que vous avez indiquée (je ne l’ai pas essayé moi-même, mais essayez d’exécuter le script Shell directement, et si cela ne fonctionne pas, exécutez le Shell lui-même, en le passant comme paramètre de ligne de commande). .
Je pense que vous avez répondu à votre propre question avec
Runtime.getRuntime().exec(myShellScript);
Quant à savoir s’il s’agit d’une bonne pratique ... qu’essayez-vous de faire avec un script Shell que vous ne pouvez pas faire avec Java?
Vous pouvez utiliser Apache Commons exec library aussi.
Exemple :
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");
}
}
Pour référence ultérieure, un exemple est donné sur Apache Doc aussi.
Oui, il est possible de le faire. Cela a fonctionné pour moi.
import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStreamReader;
import org.omg.CORBA.portable.InputStream;
public static void readBashScript() {
try {
Process proc = Runtime.getRuntime().exec("/home/destino/workspace/JavaProject/listing.sh /"); //Whatever you want to execute
BufferedReader read = new BufferedReader(new InputStreamReader(
proc.getInputStream()));
try {
proc.waitFor();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
while (read.ready()) {
System.out.println(read.readLine());
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
Voici mon exemple. J'espère que cela a du sens.
public static void excuteCommand(String filePath) throws IOException{
File file = new File(filePath);
if(!file.isFile()){
throw new IllegalArgumentException("The file " + filePath + " does not exist");
}
if(this.isLinux()){
Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", filePath}, null);
}else if(this.isWindows()){
Runtime.getRuntime().exec("cmd /c start " + filePath);
}
}
public static boolean isLinux(){
String os = System.getProperty("os.name");
return os.toLowerCase().indexOf("linux") >= 0;
}
public static boolean isWindows(){
String os = System.getProperty("os.name");
return os.toLowerCase().indexOf("windows") >= 0;
}
La bibliothèque ZT Process Executor est une alternative à Apache Commons Exec. Il a des fonctionnalités pour exécuter des commandes, capturer leur sortie, définir des délais, etc.
Je ne l'ai pas encore utilisé, mais il semble assez bien documenté.
Un exemple tiré de la documentation: Exécution d’une commande, pompage du stderr dans un enregistreur, renvoi du résultat sous forme de chaîne UTF8.
String output = new ProcessExecutor().command("Java", "-version")
.redirectError(Slf4jStream.of(getClass()).asInfo())
.readOutput(true).execute()
.outputUTF8();
Sa documentation répertorie les avantages suivants par rapport à Commons Exec:
Oui, c'est possible et vous y avez répondu! En ce qui concerne les bonnes pratiques, je pense qu’il est préférable de lancer des commandes à partir de fichiers et non directement à partir de votre code. Il faut donc que Java exécute la liste des commandes (ou une commande) dans un fichier .bat, .sh, .ksh ... existant. Voici un exemple d’exécution d’une liste de commandes dans un fichier "MyFile.sh":
String[] cmd = { "sh", "MyFile.sh", "\pathOfTheFile"};
Runtime.getRuntime().exec(cmd);
Pour éviter de coder en dur un chemin absolu, vous pouvez utiliser la méthode suivante pour rechercher et exécuter votre script s'il se trouve dans votre répertoire racine.
public static void runScript() throws IOException, InterruptedException {
ProcessBuilder processBuilder = new ProcessBuilder("./nameOfScript.sh");
//Sets the source and destination for subprocess standard I/O to be the same as those of the current Java process.
processBuilder.inheritIO();
Process process = processBuilder.start();
int exitValue = process.waitFor();
if (exitValue != 0) {
// check for errors
new BufferedInputStream(process.getErrorStream());
throw new RuntimeException("execution of script failed!");
}
}
Quant à moi, tout doit être simple. Pour l'exécution du script, il suffit d'exécuter
new ProcessBuilder("pathToYourShellScript").start();
C'est possible, exécutez-le comme n'importe quel autre programme. Assurez-vous simplement que votre script a le bon numéro! (she-bang) ligne en tant que première ligne du script et assurez-vous qu'il existe des autorisations d'exécution sur le fichier.
Par exemple, s'il s'agit d'un script bash, mettez #!/Bin/bash en haut du script, également chmod + x.
Aussi, si c'est une bonne pratique, non, surtout pas pour Java, mais si cela vous fait gagner beaucoup de temps à porter un script volumineux, et que vous ne recevez pas plus d'argent pour le faire;) économisez votre temps, exécutez la script et placez le portage vers Java sur votre liste de tâches à long terme.
String scriptName = PATH+"/myScript.sh";
String commands[] = new String[]{scriptName,"myArg1", "myArg2"};
Runtime rt = Runtime.getRuntime();
Process process = null;
try{
process = rt.exec(commands);
process.waitFor();
}catch(Exception e){
e.printStackTrace();
}
C'est une réponse tardive. Cependant, j'ai pensé mettre tout mon effort pour faire exécuter un script Shell à partir d'une application Spring-Boot destinée aux futurs développeurs.
Je travaillais dans Spring-Boot et je n’étais pas en mesure de trouver le fichier à exécuter à partir de mon application Java, qui lançait FileNotFoundFoundException
. Je devais conserver le fichier dans le répertoire resources
et définir le fichier à analyser dans pom.xml
lors du démarrage de l'application, comme suit.
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
<include>**/*.sh</include>
</includes>
</resource>
</resources>
error code = 13, Permission Denied
. Ensuite, je devais rendre le fichier exécutable en exécutant cette commande - chmod u+x myShellScript.sh
Enfin, je pourrais exécuter le fichier en utilisant l'extrait de code suivant.
public void runScript() {
ProcessBuilder pb = new ProcessBuilder("src/main/resources/myFile.sh");
try {
Process p;
p = pb.start();
} catch (IOException e) {
e.printStackTrace();
}
}
J'espère que cela résoudra le problème de quelqu'un.
Voici un exemple comment exécuter un script Unix bash ou Windows bat/cmd à partir de Java. Des arguments peuvent être passés sur le script et la sortie reçue du script. La méthode accepte un nombre arbitraire d'arguments.
public static void runScript(String path, String... args) {
try {
String[] cmd = new String[args.length + 1];
cmd[0] = path;
int count = 0;
for (String s : args) {
cmd[++count] = args[count - 1];
}
Process process = Runtime.getRuntime().exec(cmd);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
try {
process.waitFor();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
while (bufferedReader.ready()) {
System.out.println("Received from script: " + bufferedReader.readLine());
}
} catch (Exception ex) {
System.out.println(ex.getMessage());
System.exit(1);
}
}
Sous Unix/Linux, le chemin doit être de type Unix (avec/dans le séparateur). Sous Windows, utilisez '\'. Hier est un exemple de script bash (test.sh) qui reçoit un nombre arbitraire d'arguments et double chaque argument:
#!/bin/bash
counter=0
while [ $# -gt 0 ]
do
echo argument $((counter +=1)): $1
echo doubling argument $((counter)): $(($1+$1))
shift
done
En appelant
runScript("path_to_script/test.sh", "1", "2")
sous Unix/Linux, le résultat est:
Received from script: argument 1: 1
Received from script: doubling argument 1: 2
Received from script: argument 2: 2
Received from script: doubling argument 2: 4
Hier est un script Windows cmd test.cmd simple qui compte le nombre d'arguments d'entrée:
@echo off
set a=0
for %%x in (%*) do Set /A a+=1
echo %a% arguments received
Lors de l'appel du script sous Windows
runScript("path_to_script\\test.cmd", "1", "2", "3")
La sortie est
Received from script: 3 arguments received
pour linux
public static void runShell(String directory, String command, String[] args, Map<String, String> environment)
{
try
{
if(directory.trim().equals(""))
directory = "/";
String[] cmd = new String[args.length + 1];
cmd[0] = command;
int count = 1;
for(String s : args)
{
cmd[count] = s;
count++;
}
ProcessBuilder pb = new ProcessBuilder(cmd);
Map<String, String> env = pb.environment();
for(String s : environment.keySet())
env.put(s, environment.get(s));
pb.directory(new File(directory));
Process process = pb.start();
BufferedReader inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedWriter outputReader = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
int exitValue = process.waitFor();
if(exitValue != 0) // has errors
{
while(errReader.ready())
{
LogClass.log("ErrShell: " + errReader.readLine(), LogClass.LogMode.LogAll);
}
}
else
{
while(inputReader.ready())
{
LogClass.log("Shell Result : " + inputReader.readLine(), LogClass.LogMode.LogAll);
}
}
}
catch(Exception e)
{
LogClass.log("Err: RunShell, " + e.toString(), LogClass.LogMode.LogAll);
}
}
public static void runShell(String path, String command, String[] args)
{
try
{
String[] cmd = new String[args.length + 1];
if(!path.trim().isEmpty())
cmd[0] = path + "/" + command;
else
cmd[0] = command;
int count = 1;
for(String s : args)
{
cmd[count] = s;
count++;
}
Process process = Runtime.getRuntime().exec(cmd);
BufferedReader inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedWriter outputReader = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
int exitValue = process.waitFor();
if(exitValue != 0) // has errors
{
while(errReader.ready())
{
LogClass.log("ErrShell: " + errReader.readLine(), LogClass.LogMode.LogAll);
}
}
else
{
while(inputReader.ready())
{
LogClass.log("Shell Result: " + inputReader.readLine(), LogClass.LogMode.LogAll);
}
}
}
catch(Exception e)
{
LogClass.log("Err: RunShell, " + e.toString(), LogClass.LogMode.LogAll);
}
}
et pour l'usage;
ShellAssistance.runShell("", "pg_dump", new String[]{"-U", "aliAdmin", "-f", "/home/Backup.sql", "StoresAssistanceDB"});
OR
ShellAssistance.runShell("", "pg_dump", new String[]{"-U", "aliAdmin", "-f", "/home/Backup.sql", "StoresAssistanceDB"}, new Hashmap<>());
La même chose que Solaris 5.10 fonctionne comme ceci ./batchstart.sh
il y a une astuce que je ne sais pas si votre système d'exploitation l'accepte, utilisez plutôt \\. batchstart.sh
. Cette double barre peut aider.
Je pense avec
System.getProperty("os.name");
Le fait de vérifier le système d’exploitation peut gérer le script Shell/bash s’ils sont pris en charge ... s'il est nécessaire de rendre le code portable.