É bastante simples executar um comando Unix a partir de Java.
Runtime.getRuntime().exec(myCommand);
Mas é possível executar um script de shell Unix a partir do código Java? Se sim, seria uma boa prática executar um script de shell no código Java?
É bastante simples executar um comando Unix a partir de Java.
Runtime.getRuntime().exec(myCommand);
Mas é possível executar um script de shell Unix a partir do código Java? Se sim, seria uma boa prática executar um script de shell no código Java?
Respostas:
Você realmente deve olhar para o Process Builder . É realmente construído para esse tipo de coisa.
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();
Você também pode usar a biblioteca executiva do Apache Commons .
Exemplo:
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");
}
}
Para referência adicional, também é fornecido um exemplo no Apache Doc .
OutputStreampara DefaultExecuterusar DefaultExecuter.setStreamHandlermétodo para saída de captura em OutputStream. Por favor, consulte esta discussão para mais informações: Como posso capturar a saída de um comando ...
Eu diria que não está no espírito do Java executar um script de shell a partir do Java. O Java deve ser multiplataforma, e a execução de um shell script limitaria seu uso a apenas UNIX.
Com isso dito, é definitivamente possível executar um shell script a partir do Java. Você usaria exatamente a mesma sintaxe listada (eu ainda não tentei, mas tente executar o shell script diretamente e, se isso não funcionar, execute o próprio shell, passando o script como parâmetro de linha de comando) .
switchese ifinstruções para contornar todas as nuances que não funcionam exatamente da mesma maneira em plataformas diferentes, apesar dos melhores esforços das pessoas que criaram as bibliotecas principais do java.
Eu acho que você respondeu sua própria pergunta com
Runtime.getRuntime().exec(myShellScript);
Quanto à boa prática ... o que você está tentando fazer com um shell script que não pode fazer com Java?
Sim, é possível fazer isso. Isso funcionou para mim.
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());
}
}
Aqui está o meu exemplo. Espero que faça sentido.
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(isLinux()){
Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", filePath}, null);
}else if(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;
}
Sim, é possível e você já respondeu! Sobre boas práticas, acho melhor iniciar comandos a partir de arquivos e não diretamente do seu código. Então você tem que fazer Java executar a lista de comandos (ou um comando) em uma já existente .bat, .sh, .ksh... arquivos. Aqui está um exemplo de execução de uma lista de comandos em um arquivo MyFile.sh:
String[] cmd = { "sh", "MyFile.sh", "\pathOfTheFile"};
Runtime.getRuntime().exec(cmd);
Para evitar a necessidade de codificar um caminho absoluto, você pode usar o método a seguir que encontrará e executará seu script se ele estiver no diretório raiz.
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!");
}
}
Quanto a mim, todas as coisas devem ser simples. Para executar o script, basta executar
new ProcessBuilder("pathToYourShellScript").start();
A biblioteca do ZT Process Executor é uma alternativa ao Apache Commons Exec. Possui funcionalidade para executar comandos, capturar sua saída, definir tempos limites etc.
Ainda não o usei, mas parece razoavelmente bem documentado.
Um exemplo da documentação: Executando um comando, bombeando o stderr para um criador de logs, retornando a saída como sequência UTF8.
String output = new ProcessExecutor().command("java", "-version")
.redirectError(Slf4jStream.of(getClass()).asInfo())
.readOutput(true).execute()
.outputUTF8();
Sua documentação lista as seguintes vantagens sobre o Commons Exec:
Aqui está um exemplo de como executar um script bat / cmd do bash do Unix ou do Windows a partir de Java. Os argumentos podem ser transmitidos no script e a saída recebida do script. O método aceita um número arbitrário de argumentos.
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);
}
}
Ao executar no Unix / Linux, o caminho deve ser semelhante ao Unix (com '/' como separador), ao executar no Windows - use '\'. Hier é um exemplo de um script bash (test.sh) que recebe um número arbitrário de argumentos e dobra todos os argumentos:
#!/bin/bash
counter=0
while [ $# -gt 0 ]
do
echo argument $((counter +=1)): $1
echo doubling argument $((counter)): $(($1+$1))
shift
done
Ao ligar
runScript("path_to_script/test.sh", "1", "2")
no Unix / Linux, a saída é:
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 é um script cmd simples do Windows test.cmd que conta o número de argumentos de entrada:
@echo off
set a=0
for %%x in (%*) do Set /A a+=1
echo %a% arguments received
Ao chamar o script no Windows
runScript("path_to_script\\test.cmd", "1", "2", "3")
A saída é
Received from script: 3 arguments received
É possível, apenas executá-lo como qualquer outro programa. Apenas verifique se o seu script possui o # apropriado! (she-bang) como a primeira linha do script e verifique se há permissões de execução no arquivo.
Por exemplo, se for um script bash, coloque #! / Bin / bash na parte superior do script, também chmod + x.
Além disso, se for uma boa prática, não, não é, especialmente para Java, mas se você economizar muito tempo exibindo um script grande e não receber um pagamento extra por isso;) economize seu tempo; script e coloque a portabilidade para Java na sua lista de tarefas de longo prazo.
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();
}
Esta é uma resposta tardia. No entanto, pensei em me esforçar para conseguir que um script shell fosse executado a partir de um aplicativo Spring-Boot para futuros desenvolvedores.
Eu estava trabalhando no Spring-Boot e não consegui encontrar o arquivo a ser executado no meu aplicativo Java e estava sendo lançado FileNotFoundFoundException. Eu tive que manter o arquivo no resourcesdiretório e tive que definir o arquivo para ser verificado pom.xmlenquanto o aplicativo estava sendo iniciado da seguinte maneira.
<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. Então eu tive que tornar o arquivo executável executando este comando -chmod u+x myShellScript.sh Finalmente, eu poderia executar o arquivo usando o seguinte trecho de código.
public void runScript() {
ProcessBuilder pb = new ProcessBuilder("src/main/resources/myFile.sh");
try {
Process p;
p = pb.start();
} catch (IOException e) {
e.printStackTrace();
}
}
Espero que isso resolva o problema de alguém.
para uso em 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);
}
}
e para uso;
ShellAssistance.runShell("", "pg_dump", new String[]{"-U", "aliAdmin", "-f", "/home/Backup.sql", "StoresAssistanceDB"});
OU
ShellAssistance.runShell("", "pg_dump", new String[]{"-U", "aliAdmin", "-f", "/home/Backup.sql", "StoresAssistanceDB"}, new Hashmap<>());