यहाँ forलूप ठीक है। लेकिन ध्यान दें कि ऐसा इसलिए है क्योंकि फ़ाइल में मशीन के नाम हैं, जिसमें कोई व्हाट्सएप वर्ण या ग्लोबिंग वर्ण नहीं हैं। सामान्य रूप for x in $(cat file); do …से लाइनों पर पुनरावृति करने के लिए काम नहीं करता है file, क्योंकि शेल पहले कमांड को आउटपुट को cat fileकहीं से भी व्हाट्सएप पर विभाजित करता है, और फिर प्रत्येक शब्द को एक ग्लोब पैटर्न के रूप में मानता है ताकि \[?*आगे विस्तार हो। for x in $(cat file)यदि आप इस पर काम करते हैं तो आप सुरक्षित बना सकते हैं :
set -f
IFS='
'
for x in $(cat file); do …
संबंधित पढ़ना: नामों में रिक्त स्थान के साथ फ़ाइलों के माध्यम से लूपिंग? ; मैं बैश में एक चर से लाइन द्वारा लाइन कैसे पढ़ सकता हूं? ; इसके बजाय अक्सर ऐसा क्यों while IFS= readकिया जाता है IFS=; while read..? ध्यान दें कि उपयोग करते समय while read, लाइनों को पढ़ने के लिए सुरक्षित सिंटैक्स है while IFS= read -r line; do …।
अब बारी आती है कि आपके while readप्रयास में क्या गलत है । सर्वर सूची फ़ाइल से पुनर्निर्देशन पूरे लूप पर लागू होता है। इसलिए जब sshचलता है, तो इसका मानक इनपुट उस फाइल से आता है। Ssh क्लाइंट को पता नहीं चल सकता है कि रिमोट एप्लीकेशन कब अपने स्टैंडर्ड इनपुट से पढ़ना चाहता है। इसलिए जैसे ही ssh क्लाइंट कुछ इनपुट को नोटिस करता है, वह उस इनपुट को रिमोट साइड में भेजता है। Ssh सर्वर तब दूरस्थ कमांड को उस इनपुट को खिलाने के लिए तैयार है, क्या उसे यह चाहिए। आपके मामले में, रिमोट कमांड कभी भी कोई इनपुट नहीं पढ़ता है, इसलिए डेटा समाप्त हो जाता है, लेकिन ग्राहक पक्ष को इसके बारे में कुछ भी पता नहीं है। echoकाम के साथ आपका प्रयास echoकभी भी किसी इनपुट को नहीं पढ़ता है, यह अपने मानक इनपुट को अकेला छोड़ देता है।
कुछ तरीके हैं जिनसे आप इससे बच सकते हैं। आप ssh को बता सकते हैं कि -nविकल्प के साथ मानक इनपुट से न पढ़ें ।
while read server; do
ssh -n $server "uname -a"
done < /home/kenny/list_of_servers.txt
-nवास्तव में विकल्प बताता sshसे अपने इनपुट रीडायरेक्ट करने के लिए /dev/null। आप ऐसा शेल स्तर पर कर सकते हैं, और यह किसी भी कमांड के लिए काम करेगा।
while read server; do
ssh $server "uname -a" </dev/null
done < /home/kenny/list_of_servers.txt
फाइल से आने वाले ssh के इनपुट से बचने के लिए एक आकर्षक तरीका है readकमांड पर रीडायरेक्शन डालना while read server </home/kenny/list_of_servers.txt; do …। यह काम नहीं करेगा, क्योंकि यह हर बार readकमांड के निष्पादित होने पर फ़ाइल को फिर से खोलने का कारण बनता है (इसलिए यह फ़ाइल की पहली पंक्ति को बार-बार पढ़ेगा)। लूप पर पुनर्निर्देशन पूरे समय पर होना चाहिए ताकि लूप की अवधि के लिए फ़ाइल एक बार खोली जाए।
सामान्य समाधान मानक इनपुट के अलावा फ़ाइल डिस्क्रिप्टर पर लूप को इनपुट प्रदान करना है । शेल में एक डिस्क्रिप्टर नंबर से दूसरे इनपुट और आउटपुट को फ़ेरी करने के लिए निर्माण होता है। यहां, हम फाइल डिस्क्रिप्टर 3 पर फाइल को खोलते हैं, और readकमांड डिस्क्रिप्टर के इनपुट को फाइल डिस्क्रिप्टर 3 से रीडायरेक्ट करते हैं । ssh क्लाइंट ओपन नॉन-स्टैंडर्ड डिस्क्रिप्टर को अनदेखा करता है, इसलिए सब ठीक है।
while read server <&3; do
ssh $server "uname -a"
done 3</home/kenny/list_of_servers.txt
बैश में, readकमांड के पास एक अलग फ़ाइल डिस्क्रिप्टर से पढ़ने के लिए एक विशिष्ट विकल्प होता है, जिससे आप लिख सकते हैं read -u3 server।
संबंधित पढ़ना: फ़ाइल विवरणकर्ता और शेल स्क्रिप्टिंग ; आप अतिरिक्त फ़ाइल डिस्क्रिप्टर का उपयोग कब करेंगे?