একাধিক সার্ভারে ssh করতে সময় লুপ ব্যবহার করে


75

servers.txtসার্ভারের তালিকা সহ আমার একটি ফাইল রয়েছে :

server1.mydomain.com
server2.mydomain.com
server3.mydomain.com

আমি যখন whileপ্রতিটি লাইনের সাথে লাইনে ফাইল লাইনটি পড়ি এবং প্রতিধ্বনি করি তখন সমস্ত প্রত্যাশা অনুযায়ী কাজ করে। সমস্ত লাইন মুদ্রিত হয়।

$ while read HOST ; do echo $HOST ; done < servers.txt
server1.mydomain.com
server2.mydomain.com
server3.mydomain.com

যাইহোক, যখন আমি সমস্ত সার্ভারে ssh করতে এবং একটি আদেশ প্রয়োগ করতে চাই, হঠাৎ আমার whileলুপ কাজ করা বন্ধ করে দেয়:

$ while read HOST ; do ssh $HOST "uname -a" ; done < servers.txt
Linux server1 2.6.30.4-1 #1 SMP Wed Aug 12 19:55:12 EDT 2009 i686 GNU/Linux

এটি কেবল তালিকার প্রথম সার্ভারের সাথে সংযোগ স্থাপন করে, তাদের সবার সাথে নয়। আমি বুঝতে পারছি না এখানে কী ঘটছে। কেউ দয়া করে ব্যাখ্যা করতে পারেন?

এটি এমনকি অপরিচিত, যেহেতু forলুপ ব্যবহার করা ভাল কাজ করে:

$ for HOST in $(cat servers.txt ) ; do ssh $HOST "uname -a" ; done
Linux server1 2.6.30.4-1 #1 SMP Wed Aug 12 19:55:12 EDT 2009 i686 GNU/Linux
Linux server2 2.6.30.4-1 #1 SMP Wed Aug 12 19:55:12 EDT 2009 i686 GNU/Linux
Linux server3 2.6.30.4-1 #1 SMP Wed Aug 12 19:55:12 EDT 2009 i686 GNU/Linux

এটি অবশ্যই নির্দিষ্ট কিছু হতে হবে ssh, কারণ অন্যান্য কমান্ডগুলি সূক্ষ্মভাবে কাজ করে যেমন ping:

$ while read HOST ; do ping -c 1 $HOST ; done < servers.txt

4
ব্যবহারansible
ম্যাট

উত্তর:


98

ssh আপনার বাকি স্ট্যান্ডার্ড ইনপুটটি পড়ছে।

while read HOST ; do … ; done < servers.txt

readস্টাডিন থেকে পড়া। <পুনঃনির্দেশ একটি ফাইল থেকে stdin।

দুর্ভাগ্যক্রমে, আপনি যে কমান্ডটি চালনার চেষ্টা করছেন তা স্টিডিনও পড়ে, তাই এটি আপনার বাকী ফাইলটি খেয়ে ফেলে। আপনি এটিকে পরিষ্কারভাবে দেখতে পাবেন:

$ while read HOST ; do echo start $HOST end; cat; done < servers.txt 
start server1.mydomain.com end
server2.mydomain.com
server3.mydomain.com

catবাকি দুটি লাইন কীভাবে খেয়েছে (এবং প্রতিধ্বনিত হয়েছে) তা লক্ষ্য করুন । (এটি যদি আশানুরূপ হয়ে যায় তবে প্রতিটি লাইনে হোস্টের চারপাশে "শুরু" এবং "শেষ" থাকবে have)

forকাজ করে কেন ?

আপনার forলাইন স্টিনে পুনর্নির্দেশ করে না। (আসলে, এটি servers.txtপ্রথম পুনরাবৃত্তির আগে ফাইলের সমস্ত বিষয়বস্তু মেমরির মধ্যে পড়ে)। সুতরাং sshটার্মিনাল থেকে এটির স্টিন পড়া চালিয়ে যান (বা সম্ভবত আপনার স্ক্রিপ্টটি কীভাবে ডাকা হবে তার উপর নির্ভর করে কিছুই নয়)।

সমাধান

কমপক্ষে ব্যাশে, আপনি readকোনও আলাদা ফাইল বর্ণনাকারী ব্যবহার করতে পারেন ।

while read -u10 HOST ; do ssh $HOST "uname -a" ; done 10< servers.txt
#          ^^^^                                       ^^

কাজ করা উচিত। 10আমি তোলা কেবল একটি স্বেচ্ছাসেবী ফাইল নম্বর। 0, 1 এবং 2 এর অর্থ সংজ্ঞায়িত হয়েছে এবং সাধারণত ফাইলগুলি খোলার জন্য প্রথম উপলব্ধ নম্বর থেকে শুরু হবে (সুতরাং 3 ব্যবহারের পরে)। 10 পথ থেকে দূরে থাকার জন্য এটি যথেষ্ট উচ্চ, তবে কয়েকটি শেলের মধ্যে সীমাবদ্ধ থাকার জন্য যথেষ্ট কম। এটি একটি দুর্দান্ত গোল সংখ্যা ...

বিকল্প সমাধান 1: -n

হিসাবে McNisse আউট পয়েন্ট তার / তার উত্তর , OpenSSH- র ক্লায়েন্ট একটি হয়েছে -nবিকল্প এটি stdin পড়া থেকে বিরত করব। এটি নির্দিষ্ট ক্ষেত্রে ভাল কাজ করে ssh, তবে অবশ্যই অন্যান্য কমান্ডের মধ্যে এর অভাব থাকতে পারে which অন্যান্য সমাধানগুলি কোনও কমান্ড আপনার স্টিডিন খাচ্ছে তা বিবেচনা না করেই কাজ করে।

বিকল্প সমাধান 2: দ্বিতীয় পুনর্নির্দেশ

আপনি আপাতদৃষ্টিতে (যেমন, আমি এটি চেষ্টা করেছি) এটি আমার বাশ সংস্করণে কমপক্ষে কাজ করে ...) দ্বিতীয় পুনর্নির্দেশ করতে পারে যা দেখতে এরকম কিছু দেখায়:

while read HOST ; do ssh $HOST "uname -a" < /dev/null; done < servers.txt

আপনি এটি কোনও কমান্ডের সাহায্যে ব্যবহার করতে পারেন, তবে আপনি যদি কমান্ডের কাছে টার্মিনাল ইনপুটটি চান তবে তা কঠিন হবে।


1
নম্বরটি 10কোথা থেকে আসে?
মার্টিন ভেজিটার

2
@ মার্টিনভেস্টার আমি এটি তৈরি করেছি 0/1/2 হ'ল স্টিডিন, স্টাডআউট এবং স্টার্ডার। আপনার পছন্দ মতো যে কোনও নম্বর বাছাই করতে পারেন — ব্যাশ আপনাকে বেশ উচ্চতায় যেতে দেয়, সম্ভবত ওএস সীমা পর্যন্ত। অন্যান্য শেলগুলি আপনাকে অল্প
পরিমাণে

@ মার্টিনভেস্টার আমি আপনার উভয় মন্তব্যের উত্তর দিতে সম্পাদনা করেছি।
ডারোবার্ট

অন্য বিকল্প: exec 3<&0; while read HOST; do ssh $HOST "uname -a" <&3; done <servers.txt; exec 3<&- এটি ফাইল বর্ণনাকারী 3টিকে মূল স্টিডিনের একটি ব্যাকআপ দেয়, তারপরে এটি এসএসএস এর স্টিডিনের জন্য ব্যবহার করে, তারপরে ব্যাকআপ এফডি বন্ধ হয়ে যায়। এটি কোনও পসিক্স-সামঞ্জস্যপূর্ণ শেলটিতে কাজ করে।
রিচার্ড হানসেন

8
-uবিকল্প POSIX দ্বারা সমর্থিত না, এবং এইভাবে জন্য ব্যবহার করা উচিত নয় #!/bin/shস্ক্রিপ্ট; read HOST <&10পরিবর্তে ব্যবহার করুন। এছাড়াও, পসিক্সের জন্য 0 থেকে 9 এর মধ্যে ফাইল বর্ণনাকারীদের সমর্থন করার জন্য শাঁস প্রয়োজন, সুতরাং 10<servers.txtস্ক্রিপ্টটি কঠোরভাবে মেনে চলতে থাকলে ব্যবহার করা যাবে না।
রিচার্ড হানসেন

28

যেমন ডারোবার্ট sshআপনার পাঠ করে বর্ণনা করে stdin

এই আচরণটি পরিবর্তন করতে আপনি স্টিডিন পড়তে বাধা দিতে কোনও ssh যোগ করতে পারবেন।

ssh -n $HOST "uname -a"

10

আপনি সম্ভবত প্যারালাল এসএস প্রকল্প থেকে পিএসএস ব্যবহার করা ভাল better

pssh -h $hostfile -t $timeout -i $commands

-iইন্টারেক্টিভ মানে। পিএসএসএচ সমান্তরাল স্কেপ এবং সমান্তরাল আরএসএনসিও সহ আসে। খুব সুন্দর এটি হ'ল এটি অবিচ্ছিন্নভাবে চালিত হয় এবং যতটা থ্রেড আপনি যা চান তেমন চলবে। ডিফল্ট (নন-আই / ইন্টারেক্টিভ) হল stdout / stderr এর জন্য পৃথক ডিরেক্টরি আউটপুট আউটপুট যা এটি to আউটপুটডির / $ হোস্টনাম দ্বারা করে।


3

আপনি যদি নিজেকে এই ধরণের কাজটি বেশিরভাগ সময় করতে দেখেন তবে আপনার ফ্যাব্রিকটি চেষ্টা করা উচিত

নির্দেশাবলী অনুসরণ করে ফ্যাব্রিক ইনস্টল করুন , বেশিরভাগ ক্ষেত্রে আপনার কেবল প্রয়োজনsudo apt-get install fabric

fabfile.pyনিম্নলিখিত কোড সহ একটি ফাইল তৈরি করুন :

from fabric.api import env, run

env.hosts = ['server1.mydomain.com',
             'server1.mydomain.com',
             'server1.mydomain.com']

def mytask():
    run('uname -a')

তারপরে রান fab mytaskআপনার পছন্দসই ফলাফলটি দেবে।


1

এই জাতীয় কমান্ড ব্যবহার করা আরও সহজ:

for f in `cat servers.txt`; do ssh $f uname -a; done

আমি সাধারণত এটি করি:

for f in `cat servers.txt`; do echo "### $f ###"; ssh $f uname -a; done

echoযা দেখতে সার্ভার আটকে, অথবা এটি সংযোগ করতে পারেন।


1

কারণ কোনও এসএস কম্যান্ড এবং স্ট্যান্ডার্ড ইনপুট থেকে সমস্ত স্ট্রিম গ্রহণ করে, যখন বিবৃতি দিয়ে খাওয়ানো হয়েছে,

আপনি ssh এর স্টিডিনকে অন্য উত্সে স্যুইচ করতে একটি পাইপ ব্যবহার করতে পারেন:

echo "" | ssh ...

উদাহরণ:

while read HOST ; do echo "" | ssh $HOST "uname -a" ; done < servers.txt

কিছুক্ষণের মধ্যে সমস্ত ssh কমান্ডের স্টিডিন ইনপুটটি অন্য উত্সে পরিবর্তন করতে হবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.