本章目錄:
12.21 FTP下載文件
#!/bin/bash if?[?$#?-ne?1?];?thenecho?"Usage:?$0?filename" fi dir=$(dirname?$1) file=$(basename?$1) ftp?-n?-v?<<?EOF???#?-n?自動登錄 open?192.168.1.10 user?admin?adminpass binary???#?設置ftp傳輸模式為二進制,避免MD5值不同或.tar.gz壓縮包格式錯誤 cd?$dir get?"$file" EOF
12.22 輸入五個100數之內的字符,統計和、最小和最大
COUNT=1 SUM=0 MIN=0 MAX=100 while?[?$COUNT?-le?5?];?doread?-p?"請輸入1-10個整數:"?INTif?[[?!?$INT?=~?^[0-9]+$?]];?thenecho?"輸入必須是整數!"exit?1elif?[[?$INT?-gt?100?]];?thenecho?"輸入必須是100以內!"exit?1fiSUM=$(($SUM+$INT))[?$MIN?-lt?$INT?]?&&?MIN=$INT[?$MAX?-gt?$INT?]?&&?MAX=$INTlet?COUNT++ done echo?"SUM:?$SUM" echo?"MIN:?$MIN" echo?"MAX:?$MAX"
12.23 將結果分別賦值給變量
方法1: for?i?in?$(echo?"4?5?6");?doeval?a$i=$i done echo?$a4?$a5?$a6 方法2:將位置參數192.168.18.1{1,2}拆分為到每個變量 num=0 for?i?in?$(eval?echo?$*);do???#eval將{1,2}分解為1?2let?num+=1eval?node${num}="$i" done echo?$node1?$node2?$node3 #?bash?a.sh?192.168.18.1{1,2} 192.168.18.11?192.168.18.12 方法3: arr=(4?5?6) INDEX1=$(echo?${arr[0]}) INDEX2=$(echo?${arr[1]}) INDEX3=$(echo?${arr[2]})
12.24 批量修改文件名
#?touch?article_{1..3}.html #?ls article_1.html??article_2.html??article_3.html 現在想把article改為bbs: 方法1: for?file?in?$(ls?*html);?domv?$file?bbs_${file#*_}#?mv?$file?$(echo?$file?|sed?-r?'s/.*(_.*)/bbs\1/')#?mv?$file?$(echo?$file?|echo?bbs_$(cut?-d_?-f2)? done 方法2: for?file?in?$(find?.?-maxdepth?1?-name?"*html");?domv?$file?bbs_${file#*_} done 方法3: #?rename?article?bbs?*.html
12.25 統計當前目錄中以.html結尾的文件總大小
方法1: #?find?.?-name?"*.html"?-maxdepth?1?-exec?du?-b?{}?\;?|awk?'{sum+=$1}END{print?sum}' 方法2: for?size?in?$(ls?-l?*.html?|awk?'{print?$5}');?dosum=$(($sum+$size)) done echo?$sum 遞歸統計: #?find?.?-name?"*.html"?-exec?du?-k?{}?\;?|awk?'{sum+=$1}END{print?sum}'
12.26 掃描主機端口狀態
#!/bin/bash HOST=$1 PORT="22?25?80?8080" for?PORT?in?$PORT;?doif?echo?&>/dev/null?>?/dev/tcp/$HOST/$PORT;?thenecho?"$PORT?open"elseecho?"$PORT?close"fi done
12.27 Expect實現SSH免交互執行命令
需要先安裝expect工具。
expect涉及用法說明:
命令描述
set可以設置超時,也可以設置變量
timeout超時等待時間,默認10s
spawn執行一個命令
expect ""匹配輸出的內容
exp_continue繼續執行下面匹配
\r回車
$argc統計位置參數數量
[lindex $argv 0]位置參數
puts打印字符串,類似于echo
expect{...}輸入多行記錄
方法1:EOF標準輸出作為expect標準輸入
#!/bin/bash USER=root PASS=123.com IP=192.168.1.120 expect?<<?EOF set?timeout?30 spawn?ssh?$USER@$IP??? expect?{"(yes/no)"?{send?"yes\r";?exp_continue}"password:"?{send?"$PASS\r"} } expect?"$USER@*"??{send?"$1\r"} expect?"$USER@*"??{send?"exit\r"} expect?eof? EOF
方法2:
#!/bin/bash USER=root PASS=123.com IP=192.168.1.120 expect?-c?"spawn?ssh?$USER@$IPexpect?{\"(yes/no)\"?{send?\"yes\r\";?exp_continue}\"password:\"?{send?\"$PASS\r\";?exp_continue}\"$USER@*\"?{send?\"df?-h\r?exit\r\";?exp_continue}}"
方法3:將expect腳本獨立出來
login.exp登錄文件:
#!/usr/bin/expect? set?ip?[lindex?$argv?0] set?user?[lindex?$argv?1] set?passwd?[lindex?$argv?2] set?cmd?[lindex?$argv?3] if?{?$argc?!=?4?}?{ puts?"Usage:?expect?login.exp?ip?user?passwd" exit?1 } set?timeout?30 spawn?ssh?$user@$ip expect?{"(yes/no)"?{send?"yes\r";?exp_continue}"password:"?{send?"$passwd\r"} } expect?"$user@*"??{send?"$cmd\r"} expect?"$user@*"??{send?"exit\r"} expect?eof
執行命令腳本:
#!/bin/bash HOST_INFO=user_info for?ip?in?$(awk?'{print?$1}'?$HOST_INFO) douser=$(awk?-v?I="$ip"?'I==$1{print?$2}'?$HOST_INFO)pass=$(awk?-v?I="$ip"?'I==$1{print?$3}'?$HOST_INFO)expect?login.exp?$ip?$user?$pass?$1 done
SSH連接信息文件:
# cat user_info?
192.168.1.120 root 123456
12.28 批量修改服務器用戶密碼
舊密碼SSH主機信息old_info文件:
# ? ? ip ? ? user ? ?passwd ? ?port
#--------------------------------------
192.168.18.217 ?root ? ?123456 ? ? 22
192.168.18.218 ?root ? ?123456 ? ? 22
修改密碼腳本:
#!/bin/bash OLD_INFO=old_info NEW_INFO=new_info for?IP?in?$(awk?'/^[^#]/{print?$1}'?$OLD_INFO);?doUSER=$(awk?-v?I=$IP?'I==$1{print?$2}'?$OLD_INFO)PASS=$(awk?-v?I=$IP?'I==$1{print?$3}'?$OLD_INFO)PORT=$(awk?-v?I=$IP?'I==$1{print?$4}'?$OLD_INFO)NEW_PASS=$(mkpasswd?-l?8)echo?"$IP???$USER???$NEW_PASS???$PORT"?>>?$NEW_INFOexpect?-c?"spawn?ssh?-p$PORT?$USER@$IPset?timeout?2expect?{\"(yes/no)\"?{send?\"yes\r\";exp_continue}\"password:\"?{send?\"$PASS\r\";exp_continue}\"$USER@*\"?{send?\"echo?\'$NEW_PASS\'?|passwd?--stdin?$USER\r?exit\r\";exp_continue}}" done
生成新密碼new_info文件:
192.168.18.217 ?root ? ?n8wX3mU% ? ? ? ?22
192.168.18.218 ?root ? ?c87;ZnnL ? ? ? ?22
12.29 打印乘法口訣
方法1: #?awk?'BEGIN{for(n=0;n++<9;){for(i=0;i++<n;)printf?i"x"n"="i*n"?";print?""}}' 方法2: for?((i=1;i<=9;i++));?dofor?((j=1;j<=i;j++));?doresult=$(($i*$j))echo?-n?"$j*$i=$result?"doneecho done
12.30 getopts工具完善腳本命令行參數
getopts是一個解析腳本選項參數的工具。
命令格式:getopts optstring name [arg]
初次使用你要注意這幾點:
1)腳本位置參數會與optstring中的單個字母逐個匹配,如果匹配到就賦值給name,否則賦值name為問號;
2)optstring中單個字母是一個選項,如果字母后面加冒號,表示該選項后面帶參數,參數值并會賦值給OPTARG變量;
3)optstring中第一個是冒號,表示屏蔽系統錯誤(test.sh: illegal option -- h);
4)允許把選項放一起,例如-ab
下面寫一個打印文件指定行的簡單例子,用于引導你思路,擴展你的腳本選項功能:
#!/bin/bash while?getopts?:f:n:?option;?docase?$option?in?f)FILE=$OPTARG[?!?-f?$FILE?]?&&?echo?"$FILE?File?not?exist!"?&&?exit;;n)sed?-n?"${OPTARG}p"?$FILE;;?)echo?"Usage:?$0?-f?<file_path>?-n?<line_number>"echo?"-f,?--file???????????specified?file"echo?"-n,?--line-number????print?specified?line"exit?1;;esac done
思路擴展:限定腳本參數,將參數保存變量,下面調用變量繼續操作。
本章寫的Shell腳本例子都比較實用,在面試題中也經常出現,希望大家多動手練習,不要復制粘貼就拿來跑,這樣是學不會的!有問題請加群交流:323779636(Shell/Python運維開發群)