Classe Runtime

Olá pessoal, estou com a seguinte dúvida:
Preciso, em um projeto Java, chamar um script que tem a seguinte linha de comado:

#!/bin/sh

rm *.txt
rm *.class
#rm *.ini

clear

echo "Aguarde..."

javac Principal.java

java Principal

O porem é, esse projeto Java está em uma pasta e esse script está em outra.
Pensei em usar a Classe Runtime da seguinte maneira:

Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("./script.sh");

Tem como, com essa classe, passar o caminho do script e o comando a ser dado?
ficando algo do tipo:

Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("./script.sh", "/home/../ferramentaRSSF");

Teria como? Se não, tem outro jeito?

Até!!!

Tem sim. Use a classe ProcessBuilder.

//instanciando
ProcessBuilder processBuilder = new ProcessBuilder();
//passando o comando
processBuilder.command("./script.sh");
java.io.File file = new java.io.File("/home/…/ferramentaRSSF");
//passando o diretório
processBuilder.directory(file);
try {
processBuilder.start();
} catch (IOException e) {
e.printStackTrace();
}

Runtime.exec , ProcessBuilder etc. não podem rodar diretamente scripts, mesmo que eles comecem por “#!” - eles precisam de um binário executável.

No caso do Linux, isso quer dizer que se um arquivo, quando submetido ao comando file, mostra algo semelhante a:

-- exemplo para 32 bits
[entanglement@middleearth bin]$ file /usr/java/jdk1.6.0_24_i586/bin/java
/usr/java/jdk1.6.0_24_i586/bin/java: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped
-- exemplo para 64 bits
[entanglement@middleearth bin]$ file /usr/java/jdk1.7.0_21/bin/java
/usr/java/jdk1.7.0_21/bin/java: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped

pode ser executado diretamente por Runtime.exec ou ProcessBuilder, mas

[entanglement@middleearth bin]$ file script.sh
seeall: Korn shell script text executable
[entanglement@middleearth bin]$ file script2.sh
cleanUp: Bourne shell script text executable

não pode.

Isso quer dizer que você não pode rodar scripts? É claro que pode, mas você precisa passar o nome do executável do processador de scripts. Por exemplo, em vez de “./script.sh”, você tem de especificar “/bin/bash -c ./script.sh” ou coisa semelhante.

Procure a documentação do seu processador de scripts para saber qual é o comando correto (se é com -c, por exemplo).

Isso também quer dizer que você pode rodar outros tipos de scripts, como perl e awk, a única coisa é que você precisa especificar que vai usar o perl ou o awk, não simplesmente marcar o arquivo como executável.

[quote=Paul Anderson]Tem sim. Use a classe ProcessBuilder.

//instanciando
ProcessBuilder processBuilder = new ProcessBuilder();
//passando o comando
processBuilder.command("./script.sh");
java.io.File file = new java.io.File("/home/…/ferramentaRSSF");
//passando o diretório
processBuilder.directory(file);
try {
processBuilder.start();
} catch (IOException e) {
e.printStackTrace();
}[/quote]
Paul Anderson irei tentar o que você recomendou e logo eu volto para dizer se deu certo…
Obrigado por responder!!!

[quote=entanglement]Runtime.exec , ProcessBuilder etc. não podem rodar diretamente scripts, mesmo que eles comecem por “#!” - eles precisam de um binário executável.

No caso do Linux, isso quer dizer que se um arquivo, quando submetido ao comando file, mostra algo semelhante a:

-- exemplo para 32 bits
[entanglement@middleearth bin]$ file /usr/java/jdk1.6.0_24_i586/bin/java
/usr/java/jdk1.6.0_24_i586/bin/java: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped
-- exemplo para 64 bits
[entanglement@middleearth bin]$ file /usr/java/jdk1.7.0_21/bin/java
/usr/java/jdk1.7.0_21/bin/java: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped

pode ser executado diretamente por Runtime.exec ou ProcessBuilder, mas

[entanglement@middleearth bin]$ file script.sh
seeall: Korn shell script text executable
[entanglement@middleearth bin]$ file script2.sh
cleanUp: Bourne shell script text executable

não pode.

Isso quer dizer que você não pode rodar scripts? É claro que pode, mas você precisa passar o nome do executável do processador de scripts. Por exemplo, em vez de “./script.sh”, você tem de especificar “/bin/bash -c ./script.sh” ou coisa semelhante.

Procure a documentação do seu processador de scripts para saber qual é o comando correto (se é com -c, por exemplo).

Isso também quer dizer que você pode rodar outros tipos de scripts, como perl e awk, a única coisa é que você precisa especificar que vai usar o perl ou o awk, não simplesmente marcar o arquivo como executável. [/quote]

entanglement, teria como você dar um exemplo? Ou poderia dizer como eu faria solucionar minha dúvida?
Tenho pouquíssimo conhecimento nesse assunto e por isso que não intendi muito bem a sua colocação.
Agradeço por responder.

Bom, leia atentamente o que escrevi, sem pular nenhuma linha. Eu até dei um exemplo, basta você substituir no seu próprio programa !!!

[quote=entanglement]Bom, leia atentamente o que escrevi, sem pular nenhuma linha. Eu até dei um exemplo, basta você substituir no seu próprio programa !!!

[/quote]

Mas, como eu colocaria no código do meu Projeto java o jeito para chamar o script para ser executado, sabendo que meu projeto java e o script está em pastas/diretório diferente?
Eu usaria qual comando, no projeto java, para acionar o script? (ProcessBuilder, Runtime).

Como o script está em um diretório diferente, eu recomendaria passar o diretório completo para o programa Java, de alguma forma (como configuração, digamos).

Mas como scripts tendem a só funcionar corretamente se estiverem em um determinado diretório, eu recomendaria uma abordagem diferente.

No ProcessBuilder existe um modo de você ir para o diretório desejado ANTES de executar o programa.

Vou modificar um exemplo que está no próprio javadoc do ProcessBuilder. Vou fazer o seguinte: digamos que o script.sh esteja no diretório /opt/local, e que só execute corretamente se ele rodar no diretório /home/diego/projetos/exemplo. O comando adequado para o script.sh (supondo que ele seja um script Bash) seria:

http://docs.oracle.com/javase/6/docs/api/java/lang/ProcessBuilder.html

 ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "/opt/local/script.sh"); // note que script.sh não roda sozinho; ele precisa do bash para ser executado
 pb.directory(new File("/home/diego/projetos/exemplo")); // Equivale a você digitar "cd /home/diego/projetos/exemplo" antes de você dar o comando /opt/local/script.sh
 Process p = pb.start(); // e é aqui que o comando é realmente executado

[quote=entanglement]Como o script está em um diretório diferente, eu recomendaria passar o diretório completo para o programa Java, de alguma forma (como configuração, digamos).

Mas como scripts tendem a só funcionar corretamente se estiverem em um determinado diretório, eu recomendaria uma abordagem diferente.

No ProcessBuilder existe um modo de você ir para o diretório desejado ANTES de executar o programa.

Vou modificar um exemplo que está no próprio javadoc do ProcessBuilder. Vou fazer o seguinte: digamos que o script.sh esteja no diretório /opt/local, e que só execute corretamente se ele rodar no diretório /home/diego/projetos/exemplo. O comando adequado para o script.sh (supondo que ele seja um script Bash) seria:

http://docs.oracle.com/javase/6/docs/api/java/lang/ProcessBuilder.html

ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "/opt/local/script.sh"); // note que script.sh não roda sozinho; ele precisa do bash para ser executado pb.directory(new File("/home/diego/projetos/exemplo")); // Equivale a você digitar "cd /home/diego/projetos/exemplo" antes de você dar o comando /opt/local/script.sh Process p = pb.start(); // e é aqui que o comando é realmente executado [/quote]

Na verdade o scrip, rodaJava.sh, deve ser executado dentro da pasta/diretório que ele está.
Ou seja, o meu Projeto Java X, executado o comando ProcessBuilder para o rodaJava.sh entrar em execução, esse irá gerar informações dentro da pasta dele mesmo, ao finalizar esse processo, irei, com o projeto X, ler essas informações.
Para isso eu fiz da seguinte maneira:

        // "-c" significa?
        // rodaJava.sh deve ser executado na pasta dele mesmo, pois ele tem dependências de outros arquivos dentro dessa pasta.
        ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c",
                "/home/laboratorioic/omnetpp/Castalia-3.2/Simulations/redesCorporais/rodaJava.sh");
      
        pb.directory(new File("/home/laboratorioic/omnetpp/Castalia-3.2/Simulations/redesCorporais"));
        
        try {
            Process p = pb.start();
        } catch (IOException ex) {
            Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
        }

Parece que ele executa de modo incompleto, pois rodaJava.sh apagar os arquivos txt na sua pasta, o que ele deve fazer mesmo, mas o resultado final não é gerado.
Pelo terminal funciona normalmente.

laboratorioic@laboratorioic-Vostro-260s:~$
laboratorioic@laboratorioic-Vostro-260s:~$ cd omnetpp/Castalia-3.2/Simulations/redesCorporais/
laboratorioic@laboratorioic-Vostro-260s:~/omnetpp/Castalia-3.2/Simulations/redesCorporais$ ./rodaJava.sh 

No final da execução é gerado txt com valores.

Tem ideia do que pode ser?

Desde já agradeço pela ajuda!