Perhatikan kode berikut:
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);
}
Keluaran program adalah:
/etc:
adduser.co
Ketika saya lari dari shell, tentu saja, ini berfungsi seperti yang diharapkan:
poundifdef@parker:~/rabbit_test$ ls /etc | grep release
lsb-release
Internet memberi tahu saya bahwa, karena perilaku pipa tidak lintas platform, para pemikir brilian yang bekerja di pabrik Jawa yang memproduksi Java tidak dapat menjamin bahwa pipa berfungsi.
Bagaimana saya bisa melakukan ini?
Saya tidak akan melakukan semua parsing saya menggunakan konstruksi Java daripada grep
dan sed
, karena jika saya ingin mengubah bahasa, saya akan dipaksa untuk menulis ulang kode parsing saya dalam bahasa itu, yang sama sekali tidak boleh digunakan.
Bagaimana saya bisa membuat Java melakukan piping dan redirection saat memanggil perintah shell?
java
exec
runtime.exec
poundifdef.dll
sumber
sumber
command | grep foo
Anda jauh lebih baik dengan hanya menjalankancommand
dan melakukan pemfilteran secara native di Java. Itu membuat kode Anda agak lebih kompleks tetapi Anda juga mengurangi konsumsi sumber daya secara keseluruhan dan permukaan serangan secara signifikan.Jawaban:
Tulis skrip, dan jalankan skrip, bukan perintah terpisah.
Pipa adalah bagian dari cangkang, jadi Anda juga bisa melakukan sesuatu seperti ini:
sumber
ls
iels -lrt
?android
versi di sini, gunakan/system/bin/sh
sajaSaya mengalami masalah serupa di Linux, kecuali itu adalah "ps -ef | grep someprocess".
Setidaknya dengan "ls" Anda memiliki pengganti Java yang tidak bergantung pada bahasa (meskipun lebih lambat). Misalnya.:
Dengan "ps", ini sedikit lebih sulit, karena Java tampaknya tidak memiliki API untuk itu.
Saya pernah mendengar bahwa Sigar mungkin dapat membantu kami: https://support.hyperic.com/display/SIGAR/Home
Solusi paling sederhana, bagaimanapun, (seperti yang ditunjukkan oleh Kaj) adalah dengan menjalankan perintah piped sebagai string array. Ini kode lengkapnya:
Tentang mengapa array String bekerja dengan pipa, sementara satu string tidak ... itu salah satu misteri alam semesta (terutama jika Anda belum membaca kode sumbernya). Saya curiga itu karena ketika exec diberi satu string, itu menguraikannya terlebih dahulu (dengan cara yang tidak kita sukai). Sebaliknya, ketika exec diberi larik string, ia hanya meneruskannya ke sistem operasi tanpa menguraikannya.
Sebenarnya, jika kita meluangkan waktu dari hari yang sibuk dan melihat kode sumbernya (di 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 ), kami menemukan bahwa itulah yang terjadi:
sumber
Buat Runtime untuk menjalankan setiap proses. Dapatkan OutputStream dari Runtime pertama dan salin ke InputStream dari yang kedua.
sumber
Jawaban diterima @kaj adalah untuk linux. Ini yang setara untuk Windows:
sumber