सबसे पहले, मैं लाइन की जगह लेने की सलाह दूंगा
Process process = Runtime.getRuntime ().exec ("/bin/bash");
लाइनों के साथ
ProcessBuilder builder = new ProcessBuilder("/bin/bash");
builder.redirectErrorStream(true);
Process process = builder.start();
ProcessBuilder जावा 5 में नया है और बाहरी प्रक्रियाओं को चलाना आसान बनाता है। मेरी राय में, इसका सबसे महत्वपूर्ण सुधार Runtime.getRuntime().exec()
यह है कि यह आपको अपने मानक आउटपुट में बच्चे की प्रक्रिया की मानक त्रुटि को पुनर्निर्देशित करने की अनुमति देता है। इसका मतलब है कि आपके पास InputStream
पढ़ने के लिए केवल एक ही है । इससे पहले, आपको मानक त्रुटि बफ़र भरने से बचने के लिए दो अलग-अलग थ्रेड्स, एक रीडिंग stdout
और एक रीडिंग की आवश्यकता थी stderr
, जबकि मानक आउटपुट बफर खाली था (जिससे बच्चे की प्रक्रिया को लटका दिया गया था), या इसके विपरीत।
अगला, छोरों (जिनमें से आपके पास दो हैं)
while ((line = reader.readLine ()) != null) {
System.out.println ("Stdout: " + line);
}
केवल तभी बाहर निकलें reader
, जो प्रक्रिया के मानक आउटपुट से पढ़ता है, एंड-ऑफ-फाइल लौटाता है। यह केवल तब होता है जब bash
प्रक्रिया से बाहर निकलता है। यदि प्रक्रिया से अधिक उत्पादन नहीं होता है, तो यह एंड-ऑफ-फाइल वापस नहीं आएगा। इसके बजाय, यह प्रक्रिया से आउटपुट की अगली पंक्ति की प्रतीक्षा करेगा और तब तक वापस नहीं आएगा जब तक कि यह अगली पंक्ति न हो।
चूंकि आप इस लूप तक पहुंचने से पहले प्रक्रिया को इनपुट की दो लाइनें भेज रहे हैं, इसलिए इन दो लूपों में से पहला लटक जाएगा यदि इनपुट के इन दो लाइनों के बाद प्रक्रिया बाहर नहीं निकली है। यह वहां दूसरी पंक्ति के पढ़ने की प्रतीक्षा में बैठेगा, लेकिन इसे पढ़ने के लिए दूसरी पंक्ति कभी नहीं होगी।
मैं अपने स्रोत कोड (मैं, इस समय विंडोज पर हूँ तो मैं प्रतिस्थापित संकलित /bin/bash
साथ cmd.exe
है, लेकिन सिद्धांतों ही होना चाहिए), और मुझे लगता है कि पाया:
- दो लाइनों में टाइप करने के बाद, पहले दो कमांड से आउटपुट दिखाई देता है, लेकिन फिर प्रोग्राम हैंग हो जाता है,
- यदि मैं टाइप करता हूं,
echo test
तो, और फिर exit
, प्रोग्राम इसे पहले लूप से बाहर कर देता है क्योंकि cmd.exe
प्रक्रिया से बाहर निकल गया है। फिर प्रोग्राम इनपुट की एक और लाइन (जिसे अनदेखा कर दिया जाता है) के लिए पूछता है, दूसरे लूप पर सीधे स्किप हो जाता है क्योंकि चाइल्ड प्रोसेस पहले ही निकल चुका होता है, और फिर खुद बाहर निकल जाता है।
- यदि मैं टाइप करता हूं
exit
और फिर echo test
, मुझे एक IOException मिलती है, जिसमें एक पाइप बंद होने की शिकायत होती है। यह अपेक्षित है - इनपुट की पहली पंक्ति के कारण प्रक्रिया से बाहर निकल गया, और दूसरी पंक्ति भेजने के लिए कहीं नहीं है।
मैंने एक तरकीब देखी है, जो आप चाहते हैं कि आप जिस कार्यक्रम में काम करते थे, उसके समान कुछ करता है। यह कार्यक्रम कई प्रकार के गोले रखता है, उनमें कमांड चलाता है और इन कमांड से आउटपुट पढ़ता है। उपयोग की गई ट्रिक हमेशा एक 'मैजिक' लाइन को लिखने के लिए होती थी जो शेल कमांड के आउटपुट के अंत को चिह्नित करती है, और शेल को भेजे गए कमांड से आउटपुट समाप्त होने पर यह निर्धारित करने के लिए उपयोग करती है।
मैंने आपका कोड लिया और मैंने उस पंक्ति के बाद सब कुछ बदल दिया writer
जो निम्न लूप के साथ काम करता है :
while (scan.hasNext()) {
String input = scan.nextLine();
if (input.trim().equals("exit")) {
// Putting 'exit' amongst the echo --EOF--s below doesn't work.
writer.write("exit\n");
} else {
writer.write("((" + input + ") && echo --EOF--) || echo --EOF--\n");
}
writer.flush();
line = reader.readLine();
while (line != null && ! line.trim().equals("--EOF--")) {
System.out.println ("Stdout: " + line);
line = reader.readLine();
}
if (line == null) {
break;
}
}
ऐसा करने के बाद, मैं मज़बूती से कुछ कमांड चला सकता था और प्रत्येक से आउटपुट व्यक्तिगत रूप से मेरे पास वापस आ सकता था।
echo --EOF--
शेल को भेजी गई पंक्ति में दो कमांड यह सुनिश्चित करने के लिए हैं कि कमांड से आउटपुट कमांड --EOF--
से एक त्रुटि के परिणामस्वरूप भी समाप्त हो गया है।
बेशक, इस दृष्टिकोण की अपनी सीमाएं हैं। इन सीमाओं में शामिल हैं:
- यदि मैं एक कमांड दर्ज करता हूं जो उपयोगकर्ता इनपुट की प्रतीक्षा करता है (उदाहरण के लिए एक और शेल), तो प्रोग्राम लटका हुआ प्रतीत होता है,
- यह मानता है कि शेल द्वारा संचालित प्रत्येक प्रक्रिया एक नई रेखा के साथ अपने उत्पादन को समाप्त करती है,
- यह थोड़ा गड़बड़ हो जाता है अगर शेल द्वारा चलाई जा रही कमांड लाइन लिखने के लिए होती है
--EOF--
।
bash
एक वाक्यविन्यास त्रुटि की रिपोर्ट करता है और यदि आप किसी बेजोड़ के साथ कुछ पाठ दर्ज करते हैं तो बाहर निकलता है )
।
ये बिंदु आपके लिए कोई मायने नहीं रखते अगर आप जो कुछ भी सोच रहे हैं उसे एक निर्धारित कार्य के रूप में चलाने की आज्ञा या एक छोटे से आदेश तक ही सीमित रहने जा रहे हैं जो कभी भी इस तरह के रोग संबंधी तरीकों से व्यवहार नहीं करेगा।
EDIT : लिनक्स पर इसे चलाने के बाद निकास से निपटने और अन्य छोटे बदलावों में सुधार करें ।