Process process = Runtime.getRuntime().exec("tasklist");
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
process.waitFor();
java
runtime.exec
pengguna590444
sumber
sumber
Jawaban:
Ada banyak alasan yang
waitFor()
tidak kembali.Tetapi biasanya intinya adalah fakta bahwa perintah yang dieksekusi tidak berhenti.
Ini, sekali lagi, dapat memiliki banyak alasan.
Salah satu alasan yang umum adalah bahwa proses tersebut menghasilkan beberapa keluaran dan Anda tidak membaca dari aliran yang sesuai. Ini berarti proses diblokir segera setelah buffer penuh dan menunggu proses Anda untuk melanjutkan membaca. Proses Anda pada gilirannya menunggu proses lainnya selesai (yang tidak akan terjadi karena menunggu proses Anda, ...). Ini adalah situasi kebuntuan klasik.
Anda perlu terus membaca dari aliran input proses untuk memastikan bahwa itu tidak memblokir.
Ada artikel bagus yang menjelaskan semua jebakan
Runtime.exec()
dan menunjukkan cara di sekitarnya yang disebut "When Runtime.exec () tidak mau" (ya, artikel ini dari tahun 2000, tetapi kontennya masih berlaku!)sumber
waitFor()
tidak kembali.Tampaknya Anda tidak membaca output sebelum menunggu hingga selesai. Ini bagus hanya jika output tidak memenuhi buffer. Jika ya, itu akan menunggu sampai Anda membaca output, catch-22.
Mungkin Anda memiliki beberapa kesalahan yang tidak Anda baca. Ini akan membuat aplikasi berhenti dan menunggu untuk menunggu selamanya. Cara sederhana untuk menyiasatinya adalah dengan mengarahkan kembali kesalahan ke keluaran biasa.
sumber
pb.redirectError(new File("/dev/null"));
redirectError
hanya tersedia sejak Java 1.7Juga dari dokumen Java:
Coba ini:
sumber
DefaultExecutor executor = new DefaultExecutor(); PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdoutOS, stderrOS); executor.setStreamHandler(pumpStreamHandler); executor.execute(cmdLine);
:, dengan stoutOS dan stderrOS yangBufferedOutputStream
saya buat untuk menulis ke file yang sesuai.process.close()
. Tetapi ketika saya membuka aliran input seperti yang disarankan di atas dan segera menutup - masalah hilang. Jadi dalam kasus saya Spring sedang menunggu sinyal tutup aliran. Meskipun saya menggunakan Java 8 auto closable.Saya ingin menambahkan sesuatu ke jawaban sebelumnya tetapi karena saya tidak memiliki perwakilan untuk berkomentar, saya hanya akan menambahkan jawaban. Ini ditujukan untuk pengguna android yang memprogram di Java.
Sesuai posting dari RollingBoy, kode ini hampir berhasil untuk saya:
Dalam kasus saya, waitFor () tidak merilis karena saya menjalankan pernyataan tanpa pengembalian ("ip adddr flush eth0"). Cara mudah untuk memperbaikinya adalah dengan memastikan Anda selalu mengembalikan sesuatu dalam pernyataan Anda. Bagi saya, itu berarti menjalankan yang berikut: "ip adddr flush eth0 && echo done". Anda dapat membaca buffer sepanjang hari, tetapi jika tidak ada yang dikembalikan, thread Anda tidak akan pernah melepaskan penantiannya.
Semoga itu bisa membantu seseorang!
sumber
process.waitFor()
yang hang itureader.readLine()
yang hang jika Anda tidak memiliki output. Saya mencoba menggunakanwaitFor(long,TimeUnit)
to timeout jika terjadi kesalahan dan menemukan bahwa itu adalah read the hung. Yang membuat versi timeout membutuhkan utas lain untuk melakukan pembacaan ...Ada beberapa kemungkinan:
stdout
.stderr
.stdin
.sumber
Seperti yang disebutkan orang lain, Anda harus mengonsumsi stderr dan stdout .
Dibandingkan dengan jawaban lain, karena Java 1.7 bahkan lebih mudah. Anda tidak perlu lagi membuat utas untuk membaca stderr dan stdout .
Cukup gunakan
ProcessBuilder
dan gunakan metode yangredirectOutput
dikombinasikan dengan salah saturedirectError
atauredirectErrorStream
.sumber
Untuk alasan yang sama, Anda juga dapat menggunakan
inheritIO()
untuk memetakan konsol Java dengan konsol aplikasi eksternal seperti:sumber
Anda harus mencoba mengkonsumsi output dan error pada saat yang bersamaan
sumber
Saya rasa saya mengamati masalah serupa: beberapa proses dimulai, tampaknya berjalan dengan sukses tetapi tidak pernah selesai. Fungsi waitFor () menunggu selamanya kecuali jika saya mematikan proses di Task Manager.
Namun, semuanya bekerja dengan baik jika panjang baris perintah 127 karakter atau lebih pendek. Jika nama file yang panjang tidak dapat dihindari, Anda mungkin ingin menggunakan variabel lingkungan, yang memungkinkan Anda membuat string baris perintah tetap pendek. Anda dapat membuat file batch (menggunakan FileWriter) di mana Anda menetapkan variabel lingkungan Anda sebelum memanggil program yang sebenarnya ingin Anda jalankan. Isi kumpulan seperti itu akan terlihat seperti:
Langkah terakhir adalah menjalankan file batch ini menggunakan Runtime.
sumber
Inilah metode yang berhasil untuk saya. CATATAN: Ada beberapa kode dalam metode ini yang mungkin tidak berlaku untuk Anda, jadi coba dan abaikan. Misalnya "logStandardOut (...), git-bash, dll".
}
sumber
Pembacaan aliran asinkron yang dikombinasikan dengan menghindari Tunggu dengan batas waktu akan menyelesaikan masalah.
Anda dapat menemukan halaman yang menjelaskan hal ini di sini http://simplebasics.net/.net/process-waitforexit-with-a-timeout-will-not-be-able-to-collect-the-output-message/
sumber