Process process = Runtime.getRuntime().exec("tasklist");
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
process.waitFor();
java
runtime.exec
user590444
fonte
fonte
Respostas:
Existem muitos motivos que
waitFor()
não voltam.Mas geralmente se resume ao fato de que o comando executado não é encerrado.
Isso, novamente, pode ter muitas razões.
Um motivo comum é que o processo produz alguma saída e você não lê os fluxos apropriados. Isso significa que o processo é bloqueado assim que o buffer está cheio e espera que seu processo continue lendo. O seu processo, por sua vez, espera que o outro processo termine (o que não acontecerá porque espera pelo seu processo, ...). Esta é uma situação de impasse clássica.
Você precisa ler continuamente o fluxo de entrada dos processos para garantir que ele não bloqueie.
Há um bom artigo que explica todas as armadilhas
Runtime.exec()
e mostra maneiras de contorná-las, chamado "Quando Runtime.exec () não vai" (sim, o artigo é de 2000, mas o conteúdo ainda se aplica!)fonte
waitFor()
que não retorna.Parece que você não está lendo a saída antes de aguardar sua conclusão. Isso só funciona se a saída não preencher o buffer. Em caso afirmativo, ele esperará até que você leia a saída, catch-22.
Talvez você tenha alguns erros que não está lendo. Isso faria com que o aplicativo parasse e esperasse para sempre. Uma maneira simples de contornar isso é redirecionar os erros para a saída regular.
fonte
pb.redirectError(new File("/dev/null"));
redirectError
está disponível apenas a partir do Java 1.7Também do documento Java:
Experimente isto:
fonte
DefaultExecutor executor = new DefaultExecutor(); PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdoutOS, stderrOS); executor.setStreamHandler(pumpStreamHandler); executor.execute(cmdLine);
:, onde stoutOS e stderrOS sãoBufferedOutputStream
s que criei para gravar nos arquivos apropriados.process.close()
. Mas quando eu abro o fluxo de entrada conforme sugerido acima e fecho imediatamente - o problema desaparece. Portanto, no meu caso, a Spring estava esperando pelo sinal de fechamento do stream. Embora eu esteja usando o Java 8 que pode ser fechado automaticamente.Gostaria de acrescentar algo às respostas anteriores, mas como não tenho o representante para comentar, apenas acrescentarei uma resposta. Isso é direcionado para usuários de Android que estão programando em Java.
De acordo com a postagem de RollingBoy, este código quase funcionou para mim:
No meu caso, o waitFor () não estava liberando porque eu estava executando uma instrução sem retorno ("ip adddr flush eth0"). Uma maneira fácil de corrigir isso é simplesmente garantir que você sempre retorne algo em seu extrato. Para mim, isso significava executar o seguinte: "ip adddr flush eth0 && echo done". Você pode ler o buffer o dia todo, mas se nada for retornado, sua thread nunca irá liberar sua espera.
Espero que ajude alguém!
fonte
process.waitFor()
que trava, é oreader.readLine()
que trava se você não tiver saída. Tentei usar owaitFor(long,TimeUnit)
para timeout se algo desse errado e descobri que era o read que travava. O que faz com que a versão expirada exija outro thread para fazer a leitura ...Existem várias possibilidades:
stdout
.stderr
.stdin
.fonte
Como outros mencionaram, você deve consumir stderr e stdout .
Em comparação com as outras respostas, desde o Java 1.7 é ainda mais fácil. Você não precisa mais criar threads para ler stderr e stdout .
Basta usar
ProcessBuilder
e usar os métodosredirectOutput
em combinação comredirectError
ouredirectErrorStream
.fonte
Pelo mesmo motivo, você também pode usar
inheritIO()
para mapear o console Java com console de aplicativo externo como:fonte
Você deve tentar consumir a saída e o erro ao mesmo tempo
fonte
Acho que observei um problema semelhante: alguns processos foram iniciados, pareciam funcionar com sucesso, mas nunca foram concluídos. A função waitFor () estava esperando uma eternidade, exceto se eu encerrasse o processo no Gerenciador de Tarefas.
No entanto, tudo funcionou bem nos casos em que o comprimento da linha de comando era de 127 caracteres ou menos. Se nomes de arquivo longos forem inevitáveis, você pode querer usar variáveis ambientais, o que pode permitir que você mantenha a string da linha de comando curta. Você pode gerar um arquivo em lote (usando FileWriter) no qual define suas variáveis de ambiente antes de chamar o programa que realmente deseja executar. O conteúdo desse lote pode ser semelhante a:
A última etapa é executar este arquivo em lote usando o Runtime.
fonte
Aqui está um método que funciona para mim. NOTA: Há algum código neste método que pode não se aplicar a você, portanto, tente ignorá-lo. Por exemplo, "logStandardOut (...), git-bash, etc".
}
fonte
A leitura assíncrona do fluxo combinada com evitar a espera com um tempo limite resolverá o problema.
Você pode encontrar uma página explicando isso aqui http://simplebasics.net/.net/process-waitforexit-with-a-timeout-will-not-be-able-to-collect-the-output-message/
fonte