লুপ চলাকালীন এতে ভুল কী?


3

পটভূমি

আমি এখানে একটি স্ক্রিপ্ট তৈরি করেছি:

  • একবারে আইপির একটির তালিকা পড়ুন
  • স্থানীয় হোস্ট থেকে দূরবর্তী হোস্টে একটি কনফিগার ফাইল অনুলিপি করুন
  • রিমোট হোস্ট পুনরায় বুট করুন
  • বর্তমান ssh অধিবেশন বন্ধ করুন

লিপির উপাদানসমূহ:

#!/bin/bash

SSHPASS="OMITTED"
FILE_TO_COPY=/opt/someConfigFile.conf
TARGET_FOLDER=/opt/

echo "Reading ip list..."
cat $1 | while read ip
do
    echo "Copying file to $ip"
    sshpass -p $SSHPASS scp -o StrictHostKeyChecking=no -o ServerAliveInterval=3 $FILE_TO_COPY root@$ip:$TARGET_FOLDER
    echo "Sending reboot command to $ip"
    sshpass -p $SSHPASS ssh -o StrictHostKeyChecking=no -o ServerAliveInterval=3 'nohup reboot > /dev/null & exit'
    echo "Done for $ip"
done
echo "Done for all"

আমার স্ক্রিপ্ট কোনও পাঠ্য ফাইল থেকে প্রবেশের পাঠাগুলি পড়বে যেখানে প্রতিটি এন্ট্রি একটি নতুন লাইনের দ্বারা পৃথক করা হয়, এরকম কিছু:

192.168.XXX.XX1
192.168.XXX.XX2
192.168.XXX.XX3
192.168.XXX.XX4

আমি যখন এই স্ক্রিপ্টটি চালাব, ./ConfigSender.sh /host_list.txtআমি নিম্নলিখিত আউটপুটটি দেখতে পাচ্ছি:

$> ./ConfigSender.sh /host_list.txt
Rading ip list...
Copying file to 192.168.XXX.XX1
Sending reboot command to 192.168.XXX.XX1
Done for 192.168.XXX.XX1
Done for all
$>

আমি ফাইলের সমস্ত এন্ট্রিগুলির জন্য আউটপুটটি দেখতে আশা করি। আমি সন্দেহ করেছিলাম যে কমান্ডগুলি ভিতরে whileকোনওভাবে কার্যকর হয়েছিল। সুতরাং আমি আমার স্ক্রিপ্টটি সম্পাদনা করে আউটপুটে রিড আইপি মানটি প্রিন্ট করতে পারি:

#...
echo "Reading ip list..."
cat $1 | while read ip
do
    echo "Copying file to $ip"
done
echo "Done for all"

এটি আউটপুট:

$> ./ConfigSender.sh /host_list.txt
Rading ip list...
Copying file to 192.168.XXX.XX1
Copying file to 192.168.XXX.XX2
Copying file to 192.168.XXX.XX3
Copying file to 192.168.XXX.XX4
Done for all
$>

প্রশ্ন

এটা স্পষ্ট যে মূল আদেশের ভিতরে আদেশগুলি whileএই আচরণের কারণ হয়। লুপ করার সময় কী দোষ হয়? আমি এখানে কি মিস করছি?

সম্পাদনা

@Harrymc এবং @ কামিল ম্যাকোরিওস্কি উত্তর উভয়ই আমার সমস্যাটি সমাধান করছে, অনেক ধন্যবাদ। আমি @ হরিমিকের উত্তরটি আরও বর্ণনামূলক বলে গ্রহণ করার সিদ্ধান্ত নিয়েছি।

উত্তর:


3

sshpassএটি মিথস্ক্রিয় ব্যবহারকারীর কাছ থেকে পাসওয়ার্ড পাচ্ছে ভেবে stdinবোকা বানাতে কাজ করে ssh। আপনি যখন ... | whileস্টাইলের লুপটি ব্যবহার করেন, লুপটি আগত প্রতিটি লাইনের জন্য পুনরাবৃত্তি করে stdinযা sshpassপ্রথম কলের পরে মুছে যায়। এজন্য কেবল প্রথম লাইনটি কার্যকর হয়।

বেশ কয়েকটি সমাধান সম্ভব:

  • স্ট্যান্ডার্ড ইনপুটটি এসএসপাসের জন্য পুনর্নির্দেশ করুন /dev/null
  • স্ট্যাডিনকে আলাদা করতে পুরো লুপের বডিটি ব্রেসগুলিতে আবদ্ধ করুন ( {})
  • লুপের আগে একটি অ্যারেরে বরাদ্দ করুন যাতে আপনি স্ট্ডিন ব্যবহার করছেন না
    readarray a < file
    for ip in "${a[@]}"; do
  • স্টিডিন ব্যতীত অন্য কোনও ফাইল বর্ণনাকারীর উপর লুপ করুন
    while read -u 5 -r ip; do
    ...
    done 5<file

2

আমি কিছু পরীক্ষা করেছি। আমার মনে হয় আপনার লাইনের মত

sshpass 

পড়ুন stdin, তারা সরবরাহ করে অতিরিক্ত আইপি "খাওয়া" করে cat। আপনি তদন্ত করতে পারি কেন ঘটনাচক্রে কিন্তু এটা জানাতে চাই যে এটা যথেষ্ট না ঘটে।

সমাধানটি তাদেরকে আরও কিছু ইনপুট দেওয়া:

</dev/null sshpass 

অথবা আপনি আপনার লুপটি পুনরায় এটি তৈরি করতে পারেন:

for ip in `cat $1`
do
 
done

0

নিশ্চিত না যে এটি সমস্যার সমাধান করবে, তবে আপনি আপনার ssh রিবুট কমান্ড লাইনে ব্যবহারকারী এবং হোস্টনাম সরবরাহ করেন নি।

sshpass -p $SSHPASS ssh -o StrictHostKeyChecking=no -o ServerAliveInterval=3 root@$ip 'nohup reboot > /dev/null & exit'

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