public void execShellCmd(String cmd) {
try {
OutputStream output = process.getOutputStream();
DataOutputStream dataOutput = new DataOutputStream(output);
dataOutput.writeBytes(cmd);
dataOutput.flush();
output.close(); // 關鍵:關閉了進程的標準輸入流!
dataOutput.close();
} catch (Throwable t) { t.printStackTrace(); }
}
while (true) {
execShellCmd(str); // 第二次循環時,流已關閉,寫入失敗
sleep(time);
}
異常:java.io.IOException: write failed: EBADF (Bad file number)
首次調用 execShellCmd 結束時,output.close() 關閉了 Process 對象的標準輸入流(`stdin`)。 該流屬於進程級資源,**關閉後不可重新打開**,第二次循環寫入即報 `EBADF` (Bad file descriptor)。
// 1. 啟動進程時一次性獲取流,作為類成員持有
Process process = Runtime.getRuntime().exec("sh"); // 或 "cmd.exe"
OutputStream stdin = process.getOutputStream();
DataOutputStream dos = new DataOutputStream(stdin);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
// 2. 循環中僅寫入、刷新,不關閉
public void sendCommand(String cmd) {
try {
dos.writeBytes(cmd + "\n"); // 別忘換行符,shell 按行讀取
dos.flush();
} catch (IOException e) { /* 處理斷管 */ }
}
// 3. 程序退出/銷毀時統一關閉
public void shutdown() {
try { dos.close(); } catch (IOException ignored) {}
try { reader.close(); } catch (IOException ignored) {}
process.destroy();
}
process.getInputStream() 和 getErrorStream(),否則管道滿導致進程阻塞。ProcessBuilder:new ProcessBuilder("sh").redirectErrorStream(true).start() 合併錯誤流,簡化讀取。process.waitFor(timeout, TimeUnit.SECONDS) 避免死等。**核心原則:進程的標準流是長連接,隨進程生命周期開啟/關閉,不可在單次命令中反覆開關。**