Considere o seguinte código:
String commandf = "ls /etc | grep release";
try {
// Execute the command and wait for it to complete
Process child = Runtime.getRuntime().exec(commandf);
child.waitFor();
// Print the first 16 bytes of its output
InputStream i = child.getInputStream();
byte[] b = new byte[16];
i.read(b, 0, b.length);
System.out.println(new String(b));
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
O resultado do programa é:
/etc:
adduser.co
Quando executo a partir do shell, é claro, funciona conforme o esperado:
poundifdef@parker:~/rabbit_test$ ls /etc | grep release
lsb-release
As internets me dizem que, devido ao fato de que o comportamento do pipe não é multiplataforma, as mentes brilhantes que trabalham na fábrica Java produzindo Java não podem garantir que o pipe funcione.
Como posso fazer isso?
Não vou fazer toda a minha análise usando construções Java em vez de grep
e sed
, porque se eu quiser alterar a linguagem, serei forçado a reescrever meu código de análise nessa linguagem, o que é totalmente impossível.
Como posso fazer o Java fazer piping e redirecionamento ao chamar comandos shell?
java
exec
runtime.exec
poundifdef
fonte
fonte
command | grep foo
você, é muito melhor apenas executarcommand
e filtrar nativamente em Java. Isso torna seu código um pouco mais complexo, mas também reduz significativamente o consumo geral de recursos e a superfície de ataque.Respostas:
Escreva um script e execute-o em vez de comandos separados.
Pipe é uma parte da casca, então você também pode fazer algo assim:
fonte
ls
iels -lrt
?android
versão aqui, então usar/system/bin/sh
vezEncontrei um problema semelhante no Linux, exceto que era "ps -ef | grep someprocess".
Pelo menos com "ls" você tem uma substituição Java independente da linguagem (embora mais lenta). Por exemplo.:
Com "ps", é um pouco mais difícil, porque Java não parece ter uma API para isso.
Ouvi dizer que Sigar pode nos ajudar: https://support.hyperic.com/display/SIGAR/Home
A solução mais simples, entretanto, (conforme apontado por Kaj) é executar o comando piped como um array de string. Aqui está o código completo:
Por que o array String funciona com pipe, enquanto uma única string não ... é um dos mistérios do universo (especialmente se você não leu o código-fonte). Suspeito que seja porque quando exec recebe uma única string, ele a analisa primeiro (de uma maneira que não gostamos). Em contraste, quando exec recebe uma matriz de string, ele simplesmente a passa para o sistema operacional sem analisá-la.
Na verdade, se tirarmos um tempo do dia agitado e olharmos o código-fonte (em http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/ Runtime.java # Runtime.exec% 28java.lang.String% 2Cjava.lang.String []% 2Cjava.io.File% 29 ), descobrimos que é exatamente o que está acontecendo:
fonte
Crie um Runtime para executar cada um dos processos. Obtenha o OutputStream do primeiro Runtime e copie-o para o InputStream do segundo.
fonte
A resposta aceita @Kaj é para linux. Este é o equivalente para Windows:
fonte