首先繼續上次的內容看一下另一個案例
案例:持續檢查服務器負載
uptime查看負載情況(也可以用top命令)
[root@localhost ~]# uptime22:11:26 up 7:05, 3 users, load average: 0.00, 0.00, 0.00
#!/bin/bash
#Function:持續檢查服務器負載,如果負載過高則發送警告郵件
while true
doload=$(uptime | awk '{print $10}' | tr -s "," ' ')if [ $(echo "$load > 1.0" | bc) -eq 1 ];thenecho "Warning:Server load is high:$load" | mail -s "Server load warning" admin@example.comfisleep 300
done
(該代碼可能執行不成功)
案例:持續監控應用日志
[root@localhost ~]# grep -i "error" /var/log/messages
Aug 26 19:30:52 localhost /usr/sbin/irqbalance[1044]: Cannot change IRQ 73 affinity: Input/output error
Aug 26 19:30:52 localhost /usr/sbin/irqbalance[1044]: Cannot change IRQ 63 affinity: Input/output error
案例:逐行讀取文件
[root@localhost ~]# vim test.sh
#!/bin/bash
while read line
dousername=$(echo $line | cut -d':' -f1)time=$(echo $line | cut -d':' -f3)time=$(date -d @$[time*24*3600])echo ${username}-$time
done < /root/shadow
[root@localhost ~]# ./test.sh
root-2025年 09月 08日 星期一 08:00:00 CST
bin-2024年 12月 24日 星期二 08:00:00 CST
daemon-2024年 12月 24日 星期二 08:00:00 CST
adm-2024年 12月 24日 星期二 08:00:00 CST
lp-2024年 12月 24日 星期二 08:00:00 CST
sync-2024年 12月 24日 星期二 08:00:00 CST
shutdown-2024年 12月 24日 星期二 08:00:00 CST
halt-2024年 12月 24日 星期二 08:00:00 CST
mail-2024年 12月 24日 星期二 08:00:00 CST
operator-2024年 12月 24日 星期二 08:00:00 CST
games-2024年 12月 24日 星期二 08:00:00 CST
ftp-2024年 12月 24日 星期二 08:00:00 CST
nobody-2024年 12月 24日 星期二 08:00:00 CST
systemd-coredump-2025年 08月 26日 星期二 08:00:00 CST
dbus-2025年 08月 26日 星期二 08:00:00 CST
polkitd-2025年 08月 26日 星期二 08:00:00 CST
saslauth-2025年 08月 26日 星期二 08:00:00 CST
dhcpd-2025年 08月 26日 星期二 08:00:00 CST
sshd-2025年 08月 26日 星期二 08:00:00 CST
rpc-2025年 08月 26日 星期二 08:00:00 CST
tss-2025年 08月 26日 星期二 08:00:00 CST
apache-2025年 08月 26日 星期二 08:00:00 CST
unbound-2025年 08月 26日 星期二 08:00:00 CST
libstoragemgmt-2025年 08月 26日 星期二 08:00:00 CST
cockpit-ws-2025年 08月 26日 星期二 08:00:00 CST
cockpit-wsinstance-2025年 08月 26日 星期二 08:00:00 CST
pesign-2025年 08月 26日 星期二 08:00:00 CST
chrony-2025年 08月 26日 星期二 08:00:00 CST
tcpdump-2025年 08月 26日 星期二 08:00:00 CST
tom-2025年 09月 08日 星期一 08:00:00 CST
lynn-2025年 09月 08日 星期一 08:00:00 CST
user1-2025年 09月 08日 星期一 08:00:00 CST
循環控制語句continue
continue [N]:提前結束第N層的本輪循環,而直接進入下一輪判斷;最內層為第1層
用法示例:
[root@localhost ~]# vim continue.sh
#!/bin/bash
i=1
while [ $i -le 10 ]
doecho $ilet i++
done
[root@localhost ~]# chmod +x continue.sh
[root@localhost ~]# ./continue.sh
1
2
3
4
5
6
7
8
9
10
循環控制語句break
break [N]:提前結束第N層后的全部循環;最內層為第1層,默認為1
[root@localhost ~]# vim break.sh
for((i=0;i<10;i++));do[ $i -eq 5 ] && breakfor((j=0;j<10;j++));do[ $j -eq 5 ] && breakecho $jdoneecho ----------------------------
done
[root@localhost ~]# chmod +x break.sh
[root@localhost ~]# ./break.sh
0
1
2
3
4
----------------------------
0
1
2
3
4
----------------------------
0
1
2
3
4
----------------------------
0
1
2
3
4
----------------------------
0
1
2
3
4
----------------------------
shift技術
shift命令用于對參數的向左移動,通常用于在不知道傳入參數個數的情況下依次遍歷每個參數,然后進行相應的處理(常見與Linux中各種程序的啟動腳本)。在掃描處理腳本程序的參數時,經常要用到shift命令
shift命令每執行一次,參數序列順次左移一個位置,$#
的值減1,用于分別處理每個參數,移出去的參數不可再用
注意:$#
表示腳本后跟隨的參數總的個數,$n可以獲取腳本后跟隨的第n個參數的值
示例:
[root@localhost ~]# vim shift.sh
#!/bin/bashwhile [ $# -ne 0 ]
doecho "一共$#個參數,內容分別是:"for i in `seq $#`;doecho -n -e "$i\t"doneechoshift
done
[root@localhost ~]# ./shift.sh 1 2
一共2個參數,內容分別是:
1 2
一共1個參數,內容分別是:
1
案例:累加1-100
[root@localhost ~]# vim sum.sh
#!/bin/bash
sum=0
for((i=0;i<=100;i++))
dolet sum+=$i
done
echo $sum
[root@localhost ~]# ./sum.sh
5050
Shell中的數組
1.(1)Shell數組的定義
數組的基本定義
在Shell
中,用小括號()
來表示數組,數組元素之間用空格來分隔
[root@localhost ~]# array1=(1 2 3 4 5 6)
[root@localhost ~]# echo ${array1[*]} #輸出數組的所有元素
1 2 3 4 5 6
[root@localhost ~]# echo ${array1[@]} #輸出數組的所有元素
1 2 3 4 5 6
[root@localhost ~]# echo ${array1[0]} #輸出數組的第N個數(由0代表第一個數開始)
1
[root@localhost ~]# echo ${array1[2]} #輸出數組的第3個數
3
(2)采用鍵值對的形式賦值
在Shell
中用小括號將變量括起來,同時采用鍵值對的形式賦值
[root@localhost ~]# array2=([1]=one [2]=two [3]=three)
[root@localhost ~]# echo ${array2[*]} #輸出數組的所有元素
one two three
[root@localhost ~]# echo ${array2[@]} #輸出數組的所有元素
one two three
[root@localhost ~]# echo ${#array2[@]} #輸出數組的元素個數
3
(3)動態定義數組數量
動態地定義數組變量,并使用命令的輸出結果作為數組的內容
[root@localhost ~]# array3=($(ls /boot))
[root@localhost ~]# echo ${#array3[*]} #輸出定義數組的元素個數
13
[root@localhost ~]# echo ${array3[0]}
config-6.6.0-72.0.0.76.oe2403sp1.x86_64
2.Shell數組的打印
打印單個數組元素: ${數組名[下標]} 。當未指定數組下標時,下標默認從0開始
打印全部數組內容:${數組名[@]}或 ${數組名[*]}
打印數組元素的個數:${#數組名[@]}或 ${#數組名[*]}
3.Shell數組的賦值
如果下標不存在,則自動添加一個新的元素;如果下標存在,則覆蓋原來的值
4.Shell數組的拼接合并
所謂Shell
數組拼接(數組合并),就是將兩個數組連接成一個數組
拼接數組的思路是:先利用@
或者*
,將數組擴展成列表,然后再合并到一起,具體格式如下:
[root@localhost ~]# array1=(1 2 3 4 5 6)
[root@localhost ~]# array2=(7 8 9 10 11 12)
[root@localhost ~]# array3=(${array1[@]} ${array2[@]})
[root@localhost ~]# echo ${array3[*]}
1 2 3 4 5 6 7 8 9 10 11 12
5.Shell刪除數組元素
在Shell
中,使用unset關鍵字來刪除數組元素,具體格式如下:
[root@localhost ~]# unset array3[2]
[root@localhost ~]# echo ${array3[*]}
1 2 4 5 6 7 8 9 10 11 12
[root@localhost ~]# unset array3
[root@localhost ~]# echo ${array3[*]}[root@localhost ~]#
6.獲取數組某范圍的元素
在Shell
中直接通過${數組名[@/*]:起始位置:長度}
獲取數組給定范圍內元素,返回字符串,中間用空格分開
[root@localhost ~]# arr1=(1 2 3 4 5)
[root@localhost ~]# echo ${arr1[*]:1:2}
2 3
[root@localhost ~]# echo ${arr1[@]:0:4}
1 2 3 4
mapfile命令
mapfile直接用一個指令交互式的生成一個數組
[root@localhost ~]# ls /boot/ > boot.txt
[root@localhost ~]# mapfile arr6 < boot.txt
[root@localhost ~]# echo ${arr6[*]}
config-6.6.0-72.0.0.76.oe2403sp1.x86_64 dracut efi grub2 initramfs-0-rescue-5a44ea1f344449c0863349ae24820f72.img initramfs-6.6.0-72.0.0.76.oe2403sp1.x86_64.img initramfs-6.6.0-72.0.0.76.oe2403sp1.x86_64kdump.img loader lost+found symvers-6.6.0-72.0.0.76.oe2403sp1.x86_64.gz System.map-6.6.0-72.0.0.76.oe2403sp1.x86_64 vmlinuz-0-rescue-5a44ea1f344449c0863349ae24820f72 vmlinuz-6.6.0-72.0.0.76.oe2403sp1.x86_64
shell中的函數
shell函數的定義
注意:在shell里不支持函數的參數傳入,只支持腳本的參數傳入,所以name()內不能寫任何東西。
本質的作用就是;將一段重復的代碼編入腳本中,放在指定位置,使用時直接調用。
示例
[root@localhost ~]# vim sum.sh
#!/bin/bash
c1=$1
c2=$2
c3=$3
sum() {
sum1=0
for i in $(seq $c1 $c2 $c3)
dolet sum1+=$i
done
echo $sum1
}
sum
[root@localhost ~]# chmod +x sum.sh
[root@localhost ~]# ./sum.sh 1 100
5050
案例;在子shell里調用的函數在父shell里不能輸出
[root@localhost ~]# vim sum.sh
#!/bin/bash
c1=$1
c2=$2
c3=$3
sum() {
sum1=0
for i in $(seq $c1 $c2 $c3)
dolet sum1+=$i
done
return $sum1
}
sum
[root@localhost ~]# ./sum.sh 1 100
[root@localhost ~]# echo $sum1[root@localhost ~]# source sum.sh 1 100
[root@localhost ~]# echo $sum1
5050
return的效果:把結果存儲在一個位置上
Shell函數的調用
調用 Shell 函數時可以給它傳遞參數,也可以不傳遞。如果不傳遞參數,直接給出函數名字即可
Shell的八大擴展功能(不重要)
花括號
在shell腳本中,可以使用括號對字符串進行擴展,我們可以在一對花括號中包含一組以分號分隔的字符串或者字符串序列組成一個字符串擴展,注意最終輸出結果以空格分隔,使用該擴展花括號不可以被引號引用,花括號的數量必須是偶數個
[root@localhost ~]# echo {1,5} #對字符串進行擴展
1 5
[root@localhost ~]# echo {hello,world} #對字符串進行擴展
hello world
[root@localhost ~]# echo {a..z} #對字符串序列進行擴展
a b c d e f g h i j k l m n o p q r s t u v w x y z
#字符串后面可以跟一個步長整數,默認為1或-1
[root@localhost ~]# echo {a..z..2}
a c e g i k m o q s u w y
[root@localhost ~]# echo {a..z..3}
a d g j m p s v y
[root@localhost ~]# echo {1..9..3}
1 4 7
[root@localhost ~]# echo {1..9..2}
1 3 5 7 9
[root@localhost ~]# echo "{a..z}" #花括號擴展不能使用引號
{a..z}
[root@localhost ~]# echo t{i,o}p #花括號前后都可以添加可選字符串
tip top
[root@localhost ~]# echo t{o,e{a,m}}p #花括號支持嵌套
top teap temp
#花括號批量操作
[root@localhost ~]# mkdir -p t{o,e{a,m}}p
[root@localhost ~]# touch t{o,e{a,m}}p/{a,b,c,d}e.txt
波浪號
波浪號在Shell腳本中默認代表當前用戶家目錄
[root@localhost /]# echo ~ #顯示當前用戶的家目錄 /root [root@localhost /]# echo ~/elk /root/elk [root@localhost /]# echo ~elk #顯示特定用戶的家目錄,該用戶必須存在 /home/elk [root@localhost /]# echo ~+ #顯示當前工作目錄 / [root@localhost /]# echo ~- #顯示前一個工作目錄 /root
變量替換
在Shell腳本中我們會使用 對變量進行擴展替換,變量字符可以放到花括號中,這樣可以防止需要擴展的變量字符與其他不需要擴展的字符混淆,如果 對變量進行擴展替換,變量字符可以放到花括號中,這樣可以防止需要擴展的變量字符與其他不需要擴展的字符混淆,如果 對變量進行擴展替換,變量字符可以放到花括號中,這樣可以防止需要擴展的變量字符與其他不需要擴展的字符混淆,如果后面是位置變量且多余一個數字,必須使用{}
[root@localhost ~]# a="hello word" [root@localhost ~]# echo $a hello word [root@localhost ~]# echo ${a} hello word [root@localhost ~]# b=a [root@localhost ~]# echo ${b} #直接返回變量的值 a [root@localhost ~]# echo ${!b} #間接引用a變量的值 hello word [root@localhost ~]# c=b [root@localhost ~]# echo ${!c} #盡可以實現一層簡介引用 a
變量替換操作還可以測試變量是否存在及是否為空,若變量不存在或為空,則可以為變量設置一個默認值
Shell腳本支持多種形式的變量測試與替換功能,如下表所示
語法格式 | 功能描述 |
---|---|
${變量:-關鍵字} | 如果變量未定義或為空,則返回關鍵字,否則返回變量值 |
${變量:=關鍵字} | 如果變量未定義或為空,則將關鍵字賦值給變量,并返回結果,否則直接返回變量值 |
${變量:?關鍵字} | 如果變量未定義或為空,則通過標準錯誤顯示包含關鍵字的錯誤信息,否則返回變量值 |
${變量:+關鍵字} | 如果變量未定義或為空,則直接返回空,否則返回關鍵字 |
唯一要了解basename和dirname,其余的都不重要。
basename
和dirname
:
basename
:可以獲取一個路徑中的文件名
dirname
:僅保留路徑,刪除文件名