Linux階段總結shell腳本
阿新 • • 發佈:2018-05-27
bash環境 if for while grep sed awk shell腳本知識儲備匯總
語言類型
強類型:定義變量必須指定類型;
參與的運算必須要符合類型要求(字符串不能和數值相加等);
調用未聲明變量會報錯
弱類型:定義變量無需指定類型;
默認為字符型參與運算時會自動進行類型轉換;
變量無需事先定義也可調用(空)
解釋器:
shell是解釋器bash是可用的具體解釋器(shell是車這個概念bash是寶馬車) bash sh ksh(需自己安裝) tcsh csh等 bash的基本特性:快捷鍵;Tab補齊命令和路徑;history;命令別名;標準輸入輸出;重定向;管道; Redhat6選項不可Tab 需要裝bash-completion這個包才能Tab 更改用戶shell環境(解釋器): useradd -s 創建用戶時 usermod -s 改已存在用戶 vim /etc/passwd 改配置 history:查看條數: grep HISTSIZE /etc/profile echo $HISTSIZE history | wc -l history | tail 調用: !1028 !cat 清空(兩條命令必須同時執行): history -c > ~/.bash_history 空重定向到HISTFILE文件 別名alias: grep ‘^alias‘ ~/.bashrc 家目錄下的隱藏文件 unalias 取消
重定向:
> (正確覆蓋輸出); >> (正確追加輸出); 2> (錯誤覆蓋輸出); 2>> (錯誤覆蓋輸出); &> (正確錯誤覆蓋輸出); &>> (正確錯誤追加輸出); >&2 把正確變成錯誤輸出 <; (導入文件) tips: 寫腳本可以上來就date >(>>) xx.log 再在裏面把命令執行錯誤的信息2>(>>) xx.log以執行時間 進行區分了方便查看某次執行時的錯誤 非交互式寫郵件三種: mail -s biaoti user <<EOF XX YY EOF echo haha | mail -s biaoti user 管道 mail -s biaoti user < mail.txt 導入寫好文件
腳本的執行方式:
/root/first.sh ./first.sh 絕對路徑(相對)執行 需+x
bash、sh /root/first.sh 解釋器執行(相當於作為參數)不需+x 開了子進程pstree可以驗證
source、./root/first.sh 解釋器執行(相當於作為參數) 不需+x 當前進程執行
(用於使改的配置馬上生效而不重啟,相當於重讀配置文件。
shell變量:
變量的類型 儲值類型: 數值型 :整數型;浮點型;復數。。。 字符型 : 生效範圍: 本地變量:當前Shell環境中有效,而在子Shell環境中無法直接使用 局部變量: 全局變量: 使用類型: 自定義變量: a=1 echo ${a}10 110 本地變量 TIPS:查看變量時,若變量名稱與後面要輸出的字符串連在一起,則應該以{}將變量名括起來以便區分 環境變量: PWD、USER、HOME、SHELL、HISTSIZE、HISTFILE、PATH、PS1一級提示符、 PS2二級提示符、LOGNAME登錄名 RANDOM HOSTNAME TERM記錄終端類型 環境變量相關文件:(註意開機時讀取文件順序) 全局文件為/etc/profile,對所有用戶有效 用戶文件為~/.bash_profile,僅對指定的用戶有效 env可查看所有環境變量: set可查看所有變量 位置變量: $1、$2、$10、…… 預定義變量: $0、$$、$?、$#、$*、$@ #!/bin/bash echo $0 //腳本的名稱 echo $1 //第一個參數 echo $2 //第二個參數 echo $* //所有參數 當成一個整體字符串 echo $@ //所有參數 每個參數為獨立字符串 echo $# //所有的綜合 echo $$ //當前進程的進程號 echo $? //上一個命令執行狀態返回值 shift 3 //換崗 踢掉參數(默認為一個) 使用read命令從鍵盤讀取變量值 read -p "請輸入。。:" i 用戶輸入的值賦予變量i 將回顯功能關閉(stty -echo) 輸password時 將回顯功能恢復(stty echo) 輸完password時 使用export發布全局變量 export PATH="$PATH:/usr/local/haha/bin"臨時加了個可執行路徑。 export XX="1234" 變量的定義: 名稱只能為字母數字下劃線且只能以數字和下劃線開頭 a=123 字符串 a=$b 引用其他變量的值為自己的值 a=$(date) 命令結果引用為自己的值 三種引號對賦值的影響: 強引用: 單引號 界定一個完整字符串 弱引用: 雙引號 界定一個完整的字符串且屏蔽特殊符號 命令結果引用: 反撇號或$() 引用命令執行的結果賦予變量 變量的調用 調用變量時,若變量名稱與後面輸出的字符串連在一起,以{}將變量名括起來以便區分
shell的數值運算
整數運算:
expr \*
$[]或$(()) 運算符兩側可以無空格 引用變量可省略 $
let 不顯示結果
expr或$[]、$(())方式只進行運算,並不會改變變量的值;而let命令可以直接對變量值做運算再保存新的值
let X++ X-- X+=7 X-=7 X*=7 X/=7 X%=7 強大!!
小數運算:
bc scale=N 小數位的長度
echo ‘scale=4;12.34-5.678‘ | bc
6.662 雖然小數位長為4但運算數值最長為3 也只顯示3位。
tips:bc支持條件測試正確返回1錯誤返回0 與$?相反
條件測試
“test 表達式”或者[ 表達式 ]都可以,表達式兩邊至少要留一個空格。註意空格空格空格!
[ $USER == "root" ] 等號兩邊有空格(沒有就相當字符串a) 表達式和[]間有空格!!!
字符串匹配
== != -z 檢查變量的值是否為空 -n或!-z 檢查變量的值是否非空
比較整數值的大小
eq
ne
gt
ge
lt
le
識別文件/目錄的狀態
-e
-d
-f
-r
-w
-x
多個條件/操作的邏輯組合
&&,邏輯與 第一個為假後面都不用執行
||,邏輯或 第一個為真後面都不用執行
!,邏輯非
短路運算:[ $X -gt 10 ] && echo "YES" || echo "NO"
第一個為真必須yes而不會No了,因為前面整體為真了||運算已經結束。
if選擇結構
單分支就直接: [ $X -gt 10 ] && echo "YES"
雙分支: [ $X -gt 10 ] && echo "YES" || echo "NO"
if [ 條件測試 ];then
命令序列1
else 命令序列2
fi
多分支:
if [ 條件測試 ];then
命令序列1 執行完就exit
elif
命令序列2 執行完就exit
else
命令序列3 執行完就exit
fi
案例:
檢測/media/cdrom目錄,若不存在則創建
檢測並判斷指定的主機是否可ping通
ping -c 3 -i 0.2 -W 3 192.168.4.5
-c 3(3次)-i0.2間隔0.2秒-W 3反饋的超時秒數3
從鍵盤讀取一個論壇積分,判斷論壇用戶等級
被閹割的選擇結構case
case分支屬於匹配執行的方式,它針對指定的變量預先設置一個可能的取值,判斷該變量的實際取值是否與 預設的某一個值相匹配,如果匹配上了,就執行相應的一組操作,如果沒有任何值能夠匹配,就執行預先設 置的默認操作。
case 變量值 in
模式1)
命令序列1 ;;
模式2)
命令序列2 ;; 註意格式!!!必須是雙分號。。
.. ..
*)
默認命令序列
esac
#!/bin/bash
case $1 in
redhat) //可以換成-n-i來代表選項做一個功能強大的命令出來
echo "fedora";;
fedora)
echo "redhat";;
*) //默認輸出腳本用法
echo "用法: $0 {redhat|fedora}"
esac
循環結構
for循環
for 變量名 in 值列表或 {1..5} 或 `seq 5` 或((i=1;i<=5;i++))
do
命令序列
done
幾個循環造數工具
{1..n}
seq 5(1開始到5) seq 2 10(2開始到10)seq 2 2 10(2開始中間跳2;即偶數)seq 1 2 10(奇數)
[$RANDOM%10+1] 隨機產生1-10的數
((i=1;i<=5;i++)) 初值1;條件<=5;步長為1
案例:
利用for循環來檢測多個主機的存活狀態
while循環
while [條件測試]
do
命令序列
done
死循環一般格式 while :
do
命令序列
done
通常會寫成死循環加退出的格式
while :
do
if[條件判斷];then
命令序列 && break
done
案例: 提示用戶猜測一個隨機數,直到才對為止
檢測192.168.4.0/24網段,列出不在線的主機地址
shell函數
將一些需重復使用的操作,定義為公共的語句塊,即可稱為函數。通過使用函數,可以使腳本代碼更加簡潔,增強易 讀性,提高Shell腳本的執行效率
相當於一段代碼(一串命令)取了一個名字類似定義了alias
定義錯了直接重新定義會覆蓋,類似a=1;a=2後會覆蓋前。
function 函數名 {
命令序列
.. ..
}
函數名() {
命令序列
.. ..
}
mycd(){ //定義函數
> mkdir $1
> cd $1
> }
案例:顏色輸出的命令:echo -e "\033[32;41mOK\033[0m"。3X為字體顏色分號隔開4X為背景顏色。
#!/bin/bash
cecho() {
echo –e "\033[$1m$2\033[0m"
}
cecho 32 OK
cecho 33 OK
cecho 34 OK
cecho 35 OK
中斷和退出
break可以結束整個循環;
continue結束本次循環,進入下一次循環;
exit結束整個腳本、
#!/bin/bash
for i in {1..5}
do
[ $i -eq 3 ]&& break
//這裏將break替換為continue,exit分別測試腳本執行效果
echo $i
done
echo Over
break 12Over continue1245Over exit12
案例:求輸入數的和輸0退出
#!/bin/bash
while read -p "請輸入待累加的整數(0表示結束):" x
do
[ $x -eq 0 ] && break
SUM=$[SUM+x]
done
echo "總和是:$SUM"
案例:求1-20內所有數的平方跳過非6的倍數
#!/bin/bash
i=0
while [ $i -le 20 ]
do
let i++
[ $[i%6] -ne 0 ] && continue
echo $[i*i]
done
exit 2
文本處理
字符串截取及切割
echo $變量名 | cut -b 起始位置-結束位置
echo $phone | cut -b 1-6 1-6
echo $phone | cut -b 8- 8到最後
echo $phone | cut -b 9 第9個
echo $phone | cut -b 3,5,8 第3 5 8個
expr substr "$變量名" 起始位置 長度
${變量名:起始位置:長度} 截取 (索引位置) ${phone:0:6} ${phone::6}
${變量名/old/new} 替換第一個
${變量名//old/new} 替換全部
${變量名#*關鍵詞} (關鍵詞也刪)左向右 最短匹配刪除 ${A#*:} 從左側到第一個:的所有
${變量名##*關鍵詞} 左向右 最長匹配刪除 ${A##*:}從左側到最後一個:的所有
${變量名%關鍵詞*} 右向左 最短匹配刪除 ${A%:*} 從右側到第一個:的所有
${變量名%%關鍵詞*} 右向左 最長匹配刪除 ${A##*:}從右側到最後一個:的所有
${變量名:-初值} 有初值就用初值 無初值就用賦予的初值
${XX:-123}xx無初值就賦予123為初值
隨機密碼 #!/bin/bash
x=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
//所有密碼的可能性是26+26+10=62(0-61是62個數字)
for i in {1..8}
do
num=$[RANDOM%62]
tmp=${x:num:1}
pass=${pass}$tmp 字符串相加
done
echo $pass
改擴展名 touch {a,b,c,d,e,f,g,h,i}.doc
#!/bin/bash
for FILE in `ls *.doc($1)`
do
mv $FILE ${FILE%.*}.txt("$2") (${FILE/doc/txt}) $1換成$2的擴展名
done
初值的處理 #!/bin/bash
read -p "請輸入一個正整數:" x
x=${x:-1}
i=1; SUM=0
while [ $i -le $x ]
do
let SUM+=i
let i++
done
echo "從1到$x的總和是:$SUM"
#!/bin/bash
read -p "請輸入用戶名:" user
read -p "請輸入用戶名:" pass
[ -z $user ] && exit //如果無用戶名,則腳本退出
pass=${pass:-123456} //如果用戶沒有輸入密碼,則默認密碼為123456
useradd $user
echo "$pass" | passwd --stdin $pass
expect預期交互 :模擬人機交互過程(要提前對交互過程非常熟悉)
install expect
#!/bin/bash
for i in 10 11 {1..245} seq 1 254
do
expect << EOF
spawn ssh -o StrictHostKeyChecking=no 172.25.0.$i #//創建交互式進程
expect "password:" { send "123456\r" } #//自動發送密碼
expect "# { send "pwd > /tmp/$user.txt \r" } #//發送命令
expect "#" { send "exit\r" }
EOF
done
expect腳本的最後一行默認不執行
如果不希望ssh時出現yes/no的提示,遠程時使用如下選項:
# ssh -o StrictHostKeyChecking=no server0
shell數組
整體賦值:a=(haha xixi hehe ) a[0]=haha 0是索引值為0的量
單個賦值:a[0]=haha
a[1]=xixi
a[2]=hehe
文本處理三劍客grep
三劍客都用‘‘單引號!
正則表達式
字符匹配(單個字符).點 任意單個字符
[] [xyz] 集合,裏面的任意單個字符
[a-z] [:lower:]
[A-Z] [:upper:]
[a-Z] [:alpha:]
[0-9] [:digit:]
[0-9a-Z][:alnum:]
[:space:]
[^] [^xyz] 集合取反
[^a-z]
[^A-Z]
[^a-Z]
[^0-9]
[^0-9a-Z]
|(擴展)x|y 或者
匹配次數 * 前一個字符出現任意次
\{n,m\} 前一字符出現n到m次
\{n} 前一字符出現n次
\{n,\} 前一字符至少出現n次
\(\) 保留(復制)後向引用
次數匹配(擴展) + 至少出現1次
? 出現0次或1次
{n} 出現n次
{n,} 至少出現n次
{n,m} 出現n到m次
{0,m} 至多出現m次
位置錨定 ^ 匹配行首(以什麽開頭)
$ 匹配行尾(以什麽結尾)
\> 詞尾
\< 詞首
\b(擴展) 單詞邊界
^$
^[[:space:]]*$
後向引用 () 組合為整體,保留(復制)
分組(復制) ( )復制 \1 \2 \3 粘貼
\B 匹配非單詞邊界“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
? 當該字符緊跟在任何一個其他限制符(*,+,?,{n},{n,},{n,m})後面時,匹配模式是非貪婪的
非貪婪模式盡可能少地匹配所搜索的字符串,而默認的貪婪模式則盡可能多地匹配所搜索的字符串
例如,對於字符串“oooo”,“o+”將盡可能多地匹配“o”,得到結果[“oooo”]
而“o+?”將盡可能少地匹配“o”,得到結果 [‘o‘, ‘o‘, ‘o‘, ‘o‘]
正則表達式過濾案例:
egrep -c ‘/sbin/nologin$‘ /etc/passwd = egrep ‘/sbin/nologin$‘ /etc/passwd | wc -l 內置了統計功能
egrep -vc ‘/sbin/nologin$‘ /etc/passwd
egrep -cv ‘.‘ /etc/rc.local 統計空行
egrep -c ‘^$‘ /etc/rc.local 統計空行
egrep -c ".*" /etc/httpd/conf/httpd.conf //總行數
egrep -c "#" /etc/httpd/conf/httpd.conf //含註釋的行數
egrep -c -v ‘#|^$‘ /etc/httpd/conf/httpd.conf 有效配置行(多數配置文件適用)
egrep -v ‘#|^$‘ /etc/httpd/conf/httpd.conf > httpd.conf.min 保存有效配置行
egrep ‘^ .+|^[^#]‘ test5-19-1.sh 腳本裏真正的有效配置的行?具體情況具體分析啊
egrep -m 2 ‘/sbin/nologin$‘ /etc/passwd 只顯示匹配到的前2行
egrep ‘.*‘ /etc/rc.local 匹配所有
egrep ‘exec(ution)*‘ /etc/rc.local 包含exec 和execution的行
ifconfig | egrep ‘[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}‘ 包含MAC地址
MAC03="20:69:74:R2:C5:27"
判斷mac地址是否有效
echo $MAC03 | egrep -q ‘[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}‘ && echo "有效" || echo "無效"
過濾有效的郵箱地址
egrep ‘[0-9a-zA-Z_.]{3,}@[0-9a-zA-Z.-]{2,}(\.[0-9a-zA-Z-]{2,})+‘ mail.txt
sort -t: -k3 -n /etc/passwd |tail -1 | cut -d: -f3 UID最大的用戶名
精確匹配root用戶(3種方式)
egrep ‘^\broot\b‘ /etc/passwd
egrep ‘^\<root\>‘ /etc/passwd
awk -F: ‘$1=="root"‘ /etc/passwd
如果root存在顯示它的解釋器
id root &> /dev/null && egrep ‘^\broot\b‘ /etc/passwd | cut -d: -f7
id root &> /dev/null && awk -F: ‘$1=="root"{print $NF}‘ /etc/passwd
egrep ‘\b[0-9]{2,3}\b‘ /etc/passwd 2-3位數字
某個腳本的有效語句:
egrep ‘^[^#]‘ test5-19-1.sh | egrep ‘[^[:space:]]+.*#.*‘ 這個好惱火啊
egrep ‘^[^#]|[^[:space:]]+.*#.*‘ test5-19-1.sh
用戶名同shell名的:
egrep ‘(^\b[a-Z0-9]+\b).*\1$‘ /etc/passwd
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
bash:x:1005:1025::/home/bash:/bin/bash
nologin:x:1008:1028::/home/nologin:/sbin/nologin
案例:傳遞兩個文件作為參數給腳本計算這兩個文件所有空白行之和
k1=$(egrep "^[[:space:]]*$" $1 | wc -l
k2=$(egrep "^[[:space:]]*$" $2 | wc -l
echo "$[k1+k2]"
root centos user1用戶的默認shell和uid
/etc/grub2.cfg文件中某單詞後面跟一個小括號的行
使用echo輸出一個絕對路徑egrep找出其基名和目錄名
ifconfig結果中1-255之間的數值(大量用|或者)
ifconfig結果中的IP地址
文本處理三劍客sed:
逐行處理軟件 讀一行處理一行 逐行處理讀一行處理一行。
sed [選項] ‘條件指令‘ 文件
選項:
-n 屏蔽默認輸出
-r 支持擴展正則
-i 修改源文件
條件:
行號 4 4;5 4,5 4,+10
4~2(第4行和後面步長為2的行)
sed -n ‘2~2P‘ sed.txt 偶數行
sed -n ‘1~2P‘ sed.txt 奇數行
sed -n ‘$=‘ a.txt //輸出文件的行數
/正則/
sed -n ‘p‘ a.txt //輸出所有行,等同於cat a.txt
sed -n ‘4p‘ a.txt //輸出第4行
sed -n ‘4,7p‘ a.txt //輸出第4~7行
sed -n ‘4,+10p‘ a.txt //輸出第4行及其後的10行內容
sed -n ‘/^bin/p‘ a.txt //輸出以bin開頭的行
sed ‘/xml/!d‘ a.txt //刪除不包含xml的行,!符號表示取反
sed ‘$d‘ a.txt //刪除文件的最後一行
sed ‘/^$/d‘ a.txt //刪除所有空行
tips: sed ‘s/xml//g‘ a.txt //將所有的xml都刪除(替換為空串)
sed -n ‘s/2017/xxxx/gp‘ sed.txt //替換所有並打印
sed ‘s/xml/XML/‘ a.txt //將每行中第一個xml替換為XML
sed ‘s/xml/XML/3‘ a.txt //將每行中的第3個xml替換為XML
sed ‘s/xml/XML/g‘ a.txt //將所有的xml都替換為XML
sed ‘s/xml//g‘ a.txt //將所有的xml都刪除(替換為空串)
sed ‘s#/bin/bash#/sbin/sh#‘ a.txt //將/bin/bash替換為/sbin/sh
(涉及到路徑時用其他符合分隔)
sed ‘4,7s/^/#/‘ a.txt //將第4~7行註釋掉(行首加#號)
sed ‘s/^#an/an/‘ a.txt //解除以#an開頭的行的註釋(去除行首的#號)
sed -n ‘s/.//2;s/.$//p‘ sed.txt 刪除文件中每行的第二個、最後一個字
互換:(後向引用)
sed -rn ‘s/^(.)(.*)(.)$/\3\2\1/p‘ sed.txt 第一個、倒數第1個字符互換
sed -rn ‘s/^(.)(.)(.*)(.)(.)$/\1\4\3\2\5/p‘ sed.txt 第二第四互換
sed ‘s/[0-9]//‘ nssw.txt 刪除文件中所有的數字
sed -r ‘s/[0-9]//g;s/^( )+//‘ nssw2.txt 刪除所有數字、行首空格
sed -rn ‘s/([A-Z])/[\1]/gp‘ nssw.txt 為文件中每個大寫字母添加括號
sed -rn ‘s/([a-Z0-9])/[\1]/gp‘ sed.txt 為文件中每個字母和數字添加括號
sed -rn ‘s/([a-Z0-9 ])/(\1)/gp‘ sed.txt 為文件中每個字母和數字空格添加括號
指令:
p 打印
d 刪除
s 替換s/舊/新/g
a 指定行之後追加
sed ‘2a XX‘ a.txt //在第二行後面,追加XX
i 指定行之前插入
sed ‘2i XX‘ a.txt //在第二行前面,插入XX
c 替換行
sed ‘2c XX‘ a.txt //將第二行替換為XX
sed ‘1c mysvr.tarena.com‘ /etc/hostname 修改主機名
腳本中修改配置文件時:
cp /etc/vsftpd/vsftpd.conf{,.bak} 給配置文件備份
/etc/hosts 這個文件非常有用:優先級比dns高 本地解析庫
sed -i ‘$a 192.168.4.20 D ‘ /etc/hosts
這一就可以ssh D 直接遠程這個ip了。
sed -i ‘$a 192.168.4.20 www.baidu.com ‘ /etc/hosts
這樣訪問百度就快些了不用去找dns解析了
文本處理三劍客awk:
awk [選項] ‘[條件]{指令}‘ 文件
多條編輯指令,可用分號分隔
默認將空格、制表符等作為分隔符
(cut sort 也是是默認空格Tab)
grep sed 不能直接打印某列要結合字符串的截取工具使用
-F 可指定分隔符 識別多種單個的字符
awk -F [:/] ‘{print $1,$10}‘ /etc/passwd
awk常用內置變量:
$0 文本當前行的全部內容
$1 文本的第1列
$3 文件的第3列,依此類推
NR 文件當前行的行號
NF 文件當前行的列數(有幾列
awk -F: ‘{print NR,NF}‘ passwd.txt
awk -F: ‘{print NR,$NF}‘ /etc/passwd 永遠打印最後一行!
awk -F: ‘{print NR,$NR}‘ /etc/passwd 第幾行的時候就打印第幾列!
可以打印常量:
awk -F: ‘{print $1,"的解釋器:",$7}‘ /etc/passwd
打印常量必須要加雙引號, 加逗號有空格,不加逗號無空格!
案例:
free |awk ‘/Mem/{print $NF}‘ 查看目前可用內存
ifconfig eth0 | awk ‘/RX p/{print $5}‘ 查看接收流量!
ifconfig eth0 | awk ‘/TX p/{print $5}‘ 查看發送流量!
df -h | awk ‘/\/$/{print $4}‘ #:\/$代表對/轉義!!看跟分區可用空間。
df | awk ‘/\/$/{print $4}‘ 故意不加單位 在腳本中好當成數值比較!!!
df -h / | tail -1 | awk ‘{print $4}‘ 第一個/ 代表要看/(根)的情況 提取最後一行 給awk
在網頁中查看腳本:遠程監控服務器網卡 內存等等情況(相當於動態頁面了)
rpm -qa | grep httpd
cp /root/share/test5-19-1.sh /var/www/cgi-bin/test5-19-1.html 必須放在腳本專用目錄下
chmod +x /var/www/cgi-bin/test5-19-1.html 必須要加X不然訪問不了要報404. 看到404就檢查有沒有X
systemctl stop firewalld
setenforce 0
ip/cgi-bin/test5-19-1.html 訪問驗證!!!
tips:
要想使訪問時換行顯示,要在/var/www/cgi-bin/test5-19-1.html 給這個文件加<br>然後再重啟服務!!
而不是改之前的腳本文件,思路一定要清晰啊小夥子。
tips:
如果cp -P test5-19-1.html /var/www/html/
http://192.168.4.20/test5-19-1.html
訪問到的就不是腳本執行的結果了,就是html 代碼執行的結果了。如下
#!/bin/bash echo "Content-type: text/html" echo "" ifconfig eth0 | awk ‘/netmask/{print "Ip:"$2}‘ echo "
" ifconfig eth0 | awk ‘/RX p/{print "接收流量:"$5}‘ echo "
" ifconfig eth0 | awk ‘/TX p/{print "發送流量:"$5}‘ echo "
" df | awk ‘/\/$/{print "根分區可用:"$4}‘ echo "
" free |awk ‘/Mem/{print "內存可用:"$NF}‘
路徑一定要是/var/www/cgi-bin/test5-19-1.html 才能訪問到腳步執行結果。(在未修改配置文件前提下)
格式化輸出:
awk處理的時機:
處理第一行之前做準備工作 只做預處理的時候,可以沒有操作文件
awk ‘BEGIN{print x+1}‘ #x可以不定義,直接用,默認值位0
中間進行逐行處理
處理完最後一行做總結
awk [選項] ‘ BEGIN{指令} {指令} END{指令}‘ 文件
BEGIN{ } 行前處理,讀取文件內容前執行,指令執行1次
{ } 逐行處理,讀取文件過程中執行,指令執行n次
END{ } 行後處理,讀取文件結束後執行,指令執行1次
統計系統中使用bash作為登錄Shell的用戶總個數
awk ‘BEGIN{x=0}/bash$/{x++} END{print x}‘ /etc/passwd
awk ‘/bash$/{x++} END{print x}‘ /etc/passwd 與上條命令等效 x未定義默認為0
格式化輸出/etc/passwd
awk -F: ‘BEGIN{print "User\tUID\tHome"}
{print $1 "\t" $3 "\t" $6} \ 使用“\t”顯示Tab制表位
END{print "Total",NR,"lines."}‘ /etc/passwd
awk -F: ‘BEGIN{print "用戶名 家目錄 UID"} {print $1,$6,$3 x++} END{print "總共"x"行"}‘ /etc/passwd
awk -F: ‘BEGIN{print "用戶名","家目錄","UID"} {print $1,$6,$3} END{print "總共"NR"行"}‘ /etc/passwd
awk -F: ‘BEGIN{print "用戶名","家目錄","UID"} {print $1,$6,$3 x++} END{print "總用戶量:"x }‘ /etc/passwd
END{print "總共"NR"行"} END{print "總共"x"行"} 打印最後的時候:註意變量不要引號,常量要引號,這是個坑啊!!!
awk -F: ‘BEGIN{print "用戶名\t家目錄\tUID"} {print $1"\t"$6"\t"$3 x++}END{print "總用戶量:"x }‘ /etc/passwd | column -t
column -t 自動排版對齊!!!awk -F: ‘{print $1,$2,$3 }‘ /etc/passwd | column -t
awk處理條件:
正則
awk -F: ‘/bash$/{print}‘ /etc/passwd
awk -F: ‘$1~/(zhangsan|root)/{print $7}‘ /etc/passwd (支持擴展的正則)
~代表匹配:$1匹配後面的正則。並且是包含就算,模糊匹配 #第一列包含root或zhangsan的打印第7列。
[root@D share]# awk -F: ‘$1~/^root/‘ /etc/passwd
root:x:0:0:root:/root:/bin/bash
roota:x:1004:1024::/home/roota:/bin/bash 模糊匹配
awk -F: ‘$7!~/nologin$/{print $1,$7}‘ /etc/passwd !~不匹配
使用數值/字符串比較設置條件
比較符號:== != > >= < <=
awk -F: ‘$1=="root"‘ /etc/passwd 常量要引號 精確匹配用戶是為root的 不包含aroot root arootb 等等。
awk -F: ‘NR==3‘ 打印第三行 不寫{指令}默認為打印整行(所有列)
awk -F: ‘$3>=1000‘ /etc/passwd 大於等於1000的都是普通用戶。
awk -F: ‘$3>10 && $3<5‘ /etc/passwd
tips:帶邏輯判斷的 要寫合理 不然的話不會報錯但是腳本執行結果不對,就不好排錯了。
seq 100 | awk ‘$1%6!=0‘ 不能被6整除的。
邏輯測試條件
seq 100 | awk ‘$1%6==0 && $1%5==0‘ 5和6的公倍數。
seq 100 | awk ‘$1%7==0 || $1~/7/‘ 7整除或者包含7
awk ‘/Failed/ && /invalid/‘ /var/log/secure
數學運算
awk ‘BEGIN{a++;print a}‘ 1
case:
[root@svr5 ~]# cat getupwd-awk.sh
#/bin/bash
A=$(awk -F: ‘/bash$/{print $1}‘ /etc/passwd) ## 提取符合條件的賬號記錄
for i in $A
do
grep $i /etc/shadow | awk -F: ‘{print $1,"-->",$2}‘
done
awk 命令內部不能直接調用shell中的外部變量 $1==$i 要用-v選項來重新定義調用 很麻煩。
awk流程控制(if,for,while)
if判斷:
單分支:if(判斷){命令} #第一個{表示命令開始 第二個}代表命令結束
多分支:if(判斷){命令}else{命令} #所有指令都要放在{}裏!!!!
awk -F: ‘{if($3<=1000) {i++}} END{print i} ‘ /etc/passwd #結構很重要哈!!不行就先把結構框架打出來再往裏面添加數據!!
awk -F: ‘{if($3<=1000){x++}else{y++}} END{print x,y}‘ /etc/passwd
for循環:
awk數組:
awk ‘BEGIN{a++;print a}‘ 1 未定義的變量對它++就是1!!!!a=a+1 a未出現過,為空 空+1=1
awk ‘BEGIN{a[0]++;print a[0]}‘
非常重要:awk ‘BEGIN{a[0]=00;a[1]=11;a[2]=22; for(i in a){print i,a[i]}}‘
0 0
1 11
2 22結果證明:i取值不是a的值而是a的下標。a[i]才是數組a的值。
awk數組的下標除了可以使用數字,也可以使用字符串,字符串需要使用雙引號:
awk ‘BEGIN{a["192.168.4.254"]=11;print a["192.168.4.254"]}‘ 11
awk ‘BEGIN{a[192.168.4.254]=11;print a[192.168.4.254]}‘ 11
案例:
背景:
awk 統計每一個ip的訪問次數來進行過濾
ls -lh /var/log/httpd/access_log 8.5k
wc -l /var/log/httpd/access_log 31行
ab -c 100 -n 100000 http://192.168.4.20/
dos攻擊:模擬100人訪問了網站10萬次,這時刷新頁面就會很卡。
tips:如果下標是變量就不能用引號;會把它當字符串的!先不加,結果不對了再加這樣就不會錯了.
awk ‘{IP["$1"]++}END{for (i in IP) {print IP[i],i}}‘ /var/log/httpd/access_log
63445 $1
awk ‘{IP[$1]++}END{for (i in IP) {print IP[i],i}}‘ /var/log/httpd/access_log |sort -n 從小到大排序
219 ::1
63226 192.168.4.254
awk腳本應用案例:
案例:
快速進行源碼包安裝
yum repolist | awk ‘/repolist/ {print $2}‘ |sed ‘s/,//g‘
源碼包裝的軟件不能用systemctl restart (enable) 來進行管理。
netstat -ntulp |grep httpd
tcp6 0 0 :::80 :::* LISTEN 8002/httpd
netstat -ntulp |grep :80
tcp6 0 0 :::80 :::* LISTEN 8002/httpd
netstat -ntulp |grep :80
[ $? -ne 0 ] && /usr/local/nginx/sbin/nginx
a=$(netstat -ntulp |awk ‘/:80/{print $7}‘|cut -d/ -f2)
[ $a == "httpd" ] && systemctl stop $a
b=(netstat -ntulp |awk ‘/:80/{print $7}‘|cut -d/ -f2|cut -d: -f1)
啟動腳本niginx(case)
看本機狀態信息
uptime |awk ‘{print$9,$10,$11}
ifconfig eth0 | awk ‘/RX p/{print $5}‘
ifconfig eth0 | awk ‘/TX p/{print $5}‘
free |awk ‘/Mem/{print $NF}‘
df | awk ‘/\/$/{print $4}‘
cat /etc/passwd |wc -l
who |wc -l
rpm -qa |wc -l
$!最後一個後臺進程的進程號。
防止遠程ssh暴力破解密碼
awk ‘/Failed/ && /invalid/{print $13}‘ /var/log/secure |awk ‘{a[$1]++}END{for (i in a){print i,a[i]}}‘
awk ‘/Failed/ && $9!~/invalid/{print $11}‘ /var/log/secure |awk ‘{a[$1]++}END{for (i in a){print i,a[i]}}‘
1 #!/bin/bash
2 a=$(awk ‘/Failed/ && $9!~/invalid/{print $11}‘ /var/log/secure |awk ‘{a[$1]++}END{for (i in a){print i,a[i]}}‘|awk ‘{if($2>5){print$1}}‘)
3
4 b=$(awk ‘/Failed/ && $9!~/invalid/{print $11}‘ /var/log/secure |awk ‘{a[$1]++}END{for (i in a){print i,a[i]}}‘|awk ‘{if($2>5){print$1}}‘)
5 echo $a
6 echo $b
Linux階段總結shell腳本