[RESOLVIDO] Dúvida Runtime.getRuntime().exec

Olá Pessoas,
Não estou conseguindo trabalhar com o Runtime. Em um determinado momento preciso executar um arquivo .sh que está em uma determinada pasta com um determinado nome.

O código:

\\pasta
private String path = "/home/geek/TCC/PROJETO/texto/";
\\nome do arquivo
private String execJspell= "executajspell.sh";
.
.
.
public boolean iniciaJspell(){
     try{
          Runtime.getRuntime().exec(path+execJspell);
     }catchcatch (IOException e) {  
          e.printStackTrace(); 
          return false;
     }  
     return true;
}

O que acontece é que o código funciona, porém o .sh não roda. Para tirar a dúvida executei o .sh na mão e funciona normalmente.

O que estou fazendo de errado?
O Runtime e o terminal do SO trabalhão da mesma forma - digo o Runtime utiliza o terminal?

Bem estou utilizando uma o Ubunto 10.1 (acho)!

Estou começando com Linux e Java

Runtime.exec só consegue executar arquivos binários executáveis, não scripts (que são apenas texto para o Runtime.exec).

Por exemplo, o /bin/bash (shell) é um binário executável, porque quando você roda o comando file sobre o arquivo /bin/bash, vai ver que ele mostra “… executable …”, como o exemplo abaixo.

[entanglement@guj ~]$ file test.sh
test.sh: ASCII text
[entanglement@guj ~]$ file /bin/bash
/bin/bash: 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, stripped

Quem executa os scripts é o shell, portanto você tem de chamar explicitamente o shell no Runtime.exec, para poder executar um script.
Por exemplo:


...
              Runtime.getRuntime().exec(new String[]{ "/bin/bash", "-c", "/home/geek/TCC/PROJETO/texto/executajspell.sh"});
...
1 curtida

complementando o que o entaglement disse.

vc pode usar o programa bash, ele faz isso tbm.

…exec(bash /opt/seu_arquivo.sh);

Então não foi…:frowning:

Vou explicar meu script:

#!/bin/bash
jspell -d port -a < arquivodeentrada.txt > resposta.txt 2>erros.txt

Se eu executo na mão o script funciona, se eu executo a linha dentro do script funciona tb, tentei colocar dentro da runtime tb mas não foi:

Runtime.getRuntime().exec(path +"jspell -d port -a < arquivodeentrada.txt > resposta.txt 2>erros.txt");  
Runtime.getRuntime().exec(path);
Runtime.getRuntime().exec("jspell -d port -a < arquivodeentrada.txt > resposta.txt 2>erros.txt");  

para entender melhor: o que eu faço é receber um texto que o usuário entra, eu gravo este texto no arquivodeentrada.txt deveria chamar o jspell, e entrar com com o texto dentro do arquivodeentrada.txt. a resposta do jspell me da classificação de todas as palavras baseadas em um dicionário, esta resposta é gravada no arquivo resposta.txt, e assim posso continuar o trabalho com a resposta do jspell.

Alguém tem mais alguma idéia?

Aeee me matei no fds mas acho que consegui. :lol:

Vamós lá segundo as informações do @entanglement a runtime só poderia executar “executáveis”, que não era o caso da minha .sh

Então mudei o código para:

String command = "sh " + path + "executarjspell.sh";
Runtime.getRuntime().exec(command);

Ele executava o scrpit, porém não lia o arquivo de entrada e nem criava o de sáida, não sei porque mas troquei o caminho relativo para o absoluto:

#!/bin/bash jspell -d port -a < /home/geek/TCC/feilibras2/texto/arquivodeentrada.txt > /home/geek/TCC/feilibras2/texto/resposta.txt 2> /home/geek/TCC/feilibras2/texto/erros.txt [

Ohhhh funcionou, mas ai deparei com outro problema:
O script era executado? sim
O arquivo de entrada era lido? sim
O arquivo de saída era criado?Sim, mas não a tempo da aplicação perceber isso, ela ia para o próximo comando e lia o arquivo do teste anterior

Tive que mudar um pouco pois precisava que a aplicação esperasse o arquivo de resposta ser criando corretamente, então criei ele dentro de uma Process, que pelo que eu entendi, ela meio que se torna dona da execução e é uma forma de monitorar algo externo ao java. Então pedi para ela ler toda a resposta da aplicação, (que por incrível que parece, não lia nada, acho que porque o shell troca o output padrão que é o monitor para o arquivo, acho que deveria informa qual era o padrão novo ao java mas nem tentei)

String command = "sh " + path + "executarjspell.sh";
Process proc = Runtime.getRuntime().exec(command);
InputStream input = proc.getInputStream();
BufferedInputStream reader = new BufferedInputStream(input);
Scanner sc = new Scanner(input);
while (sc.hasNext()){
     sc.next();
}   

Tudo “funfonando” porém quando eu executava várias vezes o S.O, por estar meio lerdo demorava mais que o normal para criar o arquivo, e o scrpt já tinha terminado, não tive escolha fiz uma POG, criei um sleep dentro do .sh e ficou assim:

#!/bin/bash  
jspell -d port -a < /home/geek/TCC/feilibras2/texto/arquivodeentrada.txt > /home/geek/TCC/feilibras2/texto/resposta.txt 2> /home/geek/TCC/feilibras2/texto/erros.txt  
sleep 2s
exit

LOOOOOLLLLLLL

Agora funcionou,

Obrigado a todos

Não sei se o post tá velho demais e se isto é gravedigging, mas cheguei aqui buscando e achei válido complementar.

Pelo que eu entendi, você pode usar o método waitFor() pra esperar o processo terminar antes de ir pra próxima linha (removendo a necessidade do seu POG hehe)

Ficando algo assim:

Runtime.getRuntime().exec("ffmpeg -i arquivo.wav arquivo1.mp3").waitFor();

Abraços!