Shell 程式設計(實戰篇)

2020-08-08 11:53:46

一、shell實現100台伺服器的公鑰的批次分發;LLD規劃:100台伺服器ip爲:192.168.42.101-201,root密碼:123456

考慮因素:
1.如何建立祕鑰
2.檢查與伺服器之間的通訊
3.分發祕鑰

[root@backup ~]# cat keypir.sh 
#!/bin/bash
password=123456

#建立祕鑰對---(ssh-keygen),寫入指定檔案
CreateKeyPair(){                         
ssh-keygen -f /root/.ssh/id_rsa -P ""    #-P:建立的祕鑰是否設定密碼,此處不設定密碼。
}

#檢查100台伺服器網路是否暢通
CHECK(){                                 
ping -c 1 192.168.42.$i &>/dev/null
if [ $? -eq 0 ]                          #$? 返回爲0時,說明網路暢通
then
return 1
else
return 0
fi
}

#分發祕鑰
TRACE(){
which sshpass &>/dev/null     #確定sshpass是否安裝,對方伺服器可能沒有安裝
if [ $? -ne 0 ]               #通過which命令判斷sshpass是否安裝,安裝了echo $?則返回0
then                          #$?不爲0時,則說明沒有安裝
yum install sshpass -y
#sshpass -p $password ssh-copy-id -o StrictKeyHostChecking  192.168.42.$i
sshpass -p $password scp -p -o StrictHostKeyChecking=no /root/.ssh/id_rsa.pub 192.168.42.$i:/tmp/               
 #使用sshpass工具和-o參數實現避免互動輸入yes和密碼
 #將本地/root/.ssh/id_rsa.pub(生成的祕鑰檔案),傳輸到對應伺服器上/tmp/目錄下,此時不能直接傳到/root/.ssh目錄下,避免其他機器同樣操作覆蓋檔案。
sshpass -p $password ssh -o StrictHostKeyChecking=no 192.168.42.$i "cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys"           
#ssh連線伺服器,將/tmp/下密碼檔案寫如入/root/.ssh/authorized_keys
sshpass -p $password ssh -o StrictHostKeyChecking=no 192.168.42.$i "chmod 600 /root/.ssh/authorized_keys"           #修改檔案許可權
sshpass -p $password ssh -o StrictHostKeyChecking=no 192.168.42.$i "rm -rf /tmp/id_rsa.pub"                      #由於是祕鑰檔案,爲了安全起見,用完刪除

else                                  #如果sshpass工具安裝,則直接執行。
#sshpass -p $password ssh-copy-id 192.168.42.$i
sshpass -p $password scp -p -o StrictHostKeyChecking=no /root/.ssh/id_rsa.pub 192.168.42.$i:/tmp/
sshpass -p $password ssh -o StrictHostKeyChecking=no 192.168.42.$i "cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys" 
sshpass -p $password ssh -o StrictHostKeyChecking=no 192.168.42.$i "chmod 600 /root/.ssh/authorized_keys"
sshpass -p $password ssh -o StrictHostKeyChecking=no 192.168.42.$i "rm -rf /tmp/id_rsa.pub"
fi
}

#主函數,呼叫上方定義的函數,實現功能
MAIN(){                
for i in {101..201}
do
CHECK
if [ $? -eq 1 ]                     #呼叫CHECK檢查網路是否暢通,return=1時(暢通)
then
    if [ -f /root/.ssh/id_rsa.pub ]  #暢通的話,檢查祕鑰檔案是否存在
    then
       TRACE                         #執行TRACE函數,分發祕鑰
    else
       CreateKeyPair                  #建立祕鑰
       TRACE                          #分發祕鑰
    fi
else                  #不通時
echo " 192.168.42.$i is unreachable..."

fi
done 
}

MAIN

二、設計一個shell 程式,在每天凌晨壓縮打包/etc 目錄下的所有內容,存放在/root/bak 目錄裡,且檔名爲如下形式yymmdd_etc.tar.gz(yy爲年,mm爲月,dd爲日),該目錄儲存7天內容;每天凌晨3點增量同步到備份伺服器/backup目錄下,每週六凌晨3點全量同步到備份服務的/backup目錄下;備份伺服器/backup下保留一個月的備份檔案。

考慮因素:
(1)打包/etc目錄,並存放在/root/bak目錄裡,按要求命名。
(2) /root/backup中只儲存7天內容。
(3)增量備份,全量備份。
(4)備份伺服器儲存一個月檔案。

#!/bin/bash
#定義變數
back_file_name=`date +%Y%m%d`.tar.gz     //檔名
back_file_dir=/root/bak                  //壓縮打包路徑
backup_server_user=rsync_backup			 //備份伺服器使用者
backup_server_pass=123456				 //備份伺服器密碼
root_pass=123456						 //備份主機root密碼
backup_server_IP=192.168.42.159			 //備份伺服器IP
mail_owner=ljwenjie66@163.com			 //郵箱地址
mail_topic="web data backup"			// 

data_tar(){                                           #定義用於壓縮函數
    [ -d $back_file_dir ] || mkdir -p $back_file_dir  #判斷/root/bak備份的目錄是否存在,不存在就建立。
    tar -czf $back_file_dir/$back_file_name /etc/*    #/etc下所有內容進行打包/root/bak/下以時間命名。
}

data_trace(){                                         #進行增量備份
rsync -avz $back_file_dir $backup_server_user@$backup_server_IP::backup --password-file=/etc/rsync.password
}       #rsync將本地/root/bak新增的檔案備份到備份主機上
        #--password-file中儲存了rsync的密碼,避免了互動輸入密碼

data_trace_all(){    #實現全量備份
    sshpass -p $root_pass scp -o StrictHostKeyChecking=no -rp $back_file_dir/* root@192.168.42.159:/backup
#sshappss -p 123456 scp -rp $back_file_dir root@192.168.42.138:/backup/
}        #sshpass工具實現了自動輸入密碼
         #-o StrictHostKeyChecking參數實現了自動輸入yes or no,避免了人機互動
         #利用scp將/root/bak下所有內容進行備份,以root身份備份到對應主機的/backup目錄下

clean_over_localdata(){   #清除本地7天前的的所有檔案
    find $back_file_dir -mtime +7 -exec rm {} -rf \;
}

clean_over_remodata(){ #利用ssh連線備份伺服器,將伺服器中一個月之前的檔案刪除
    sshpass -p $backup_server_pass ssh -o StrictHostKeyChecking=no $backup_server_IP "find /backup/ -mtime +30 -exec rm {} -rf \;"
}

case $1 in
    data_tar)
        data_tar
        ;;
    trace_all)
        data_trace_all
        ;;
    data_trace)
        data_trace
        ;;
    clean_over_localdata)
        clean_over_lcoaldata
        ;;
    clean_remodata)
        clean_over_remodata
        ;;
    *)
        echo "please input true paramater..."   #如果輸入的不是有效參數,則輸出*

esac

三、shell開發運維管理工具。

要求:使用者互動,當使用者輸入選單號時,列印相關內容。
選單

  1. 磁碟分割區
  2. CPU負載
  3. 剩餘記憶體
  4. 退出
    輸入:1
    輸出:(主機名,系統版本,分割區情況)
    hostname:
    system:系統版本
    ---------分割區一-----------(分割區變數輸出)
    path:分割區一
    size:大小
    file_os:分割區檔案系統型別
    mount_on:分割區掛載點
    ----------分割區二----------
    path:分割區二
    size:大小
    file_os:分割區檔案系統型別
    mount_on:分割區掛載點
    輸入:2
    輸出:
    1分鐘平均負載:
    5分鐘平均負載:
    15分鐘平均負載:
    輸入:3
    輸出:
    目前可用記憶體:
    可用Swap分割區:
    輸入:4
    輸出:
    Bey…
#!/bin/bash
while true
do
#格式化輸出以下選單
cat <<EOF        
              -------------------選單---------------------
              -              1.檢視磁碟分割區              -
              -              2.CPU負載                   -
              -              3.剩餘記憶體                  -
              -              4.退出                      -  
              --------------------------------------------
EOF
#接受使用者輸入的一個值
read -p "請輸入你要執行的操作:>>>" num
#實現第一個功能:檢視磁碟分割區
PART(){               
  echo "hostname:$HOSTNAME"                            #獲取主機名
  echo "system: `cat /etc/redhat-release`"             #獲取系統內核版本
  #定義陣列,獲取磁碟分割區放入其中。
  array1=(`lsblk -l |awk '/sd[a-z][0-9]/{print $1}'`)  #磁碟名
  array2=(`lsblk -l |awk '/sd[a-z][0-9]/{print $4}'`)  #大小
  array3=(`lsblk -l |awk '/sd[a-z][0-9]/{print $6}'`)  #型別
  array4=(`lsblk -l |awk '/sd[a-z][0-9]/{print $7}'`)  #掛載點
  #遍歷陣列
  num=`echo $((${#array1[@]}-1))`  #獲取陣列長度-1的值,給num(這裏是3
  for i in `seq 0 $num`            #i:0-3
  do
 #回圈輸出陣列103位置值
cat <<EOF
                                   ---------${array1[$i]}-----------
                                        path: ${array1[$i]}
                                        size: ${array2[$i]}
                                        file_os: ${array3[$i]}
                                        mount_on:${array4[$i]}
EOF
done
}
#實現第二個功能:檢視cpu負載
LOADING(){                          #通過uptime命令,和awk,獲取平均負載。
uptime |awk -F [:,] '{print "一分鐘平均負載:",$(NF-2)"\n""五分鐘平均分在:",$(NF-1)"\n""十五分鐘平均負載:",$NF}'
}                                  #$NF:從最後一列開始取。
#實現第三個功能:檢視記憶體和swap
MEM(){
var=("目前可用記憶體:" "可用swap分割區:")
n=0
for i in `free -h |awk '/^[^[:space:]]/ {print $4}'`    #取出記憶體和swap,進行遍歷
do
echo ${var[$n]} $i            #爲滿足題目要求,(說明+內容),將說明放入陣列依次輸出+內容
let n++                       #n從0開始自加,實現陣列依次輸出。
done
}
#利用case語句捕獲使用者鍵入的值。
#模式匹配成功,則執行相應函數。
case $num in
   1)        
   PART
   ;;
   2)
   LOADING
   ;;
   3)
   MEM
   ;;
   4)
   exit 0
   ;;
   *)
   echo "please input true list..."
esac

done