shell函數
為什么要使用shell函數
linux別的的作用
-
[root@lamp ~]# alias
-
alias cp='cp -i'
-
alias l.='ls -d .* --color=auto'
-
alias ll='ls -l --color=auto'
-
alias ls='ls --color=auto'
-
alias mv='mv -i'
-
alias rm='rm -i'
-
alias vi='vim'
-
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
設置別名與使用
-
[root@lamp ~]# alias cdone='cd /'
-
[root@lamp ~]# alias
-
alias cdone='cd /'
-
alias cp='cp -i'
-
alias l.='ls -d .* --color=auto'
-
alias ll='ls -l --color=auto'
-
alias ls='ls --color=auto'
-
alias mv='mv -i'
-
alias rm='rm -i'
-
alias vi='vim'
-
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
-
[root@lamp ~]# cdone
-
[root@lamp /]# pwd
-
/
函數也是具有和別名類似的功能。函數的作用就是把程序里多次調研相同的代碼部分定義成一份,然后為這一份代碼起個名字,其它所有的重復調用這部分代碼都只用調用這個名字就可以。當需要修改這部分重復代碼時,只需要改變函數體內的一份代碼即可實現調用修改。
使用函數的優勢:
1、把相同的程序段定義成函數,可以減少整個程序的代碼量。
2、增加程序的可讀性,以及便於管理。
3、可實現程序功能模塊化,不同的程序使用函數模塊化。
4、讓程序代碼結構更清晰。
shell函數語法
語法格式:
-
簡單語法格式
-
函數名(){
-
指令...
-
return n
-
}
-
規范語法格式
-
function 函數名(){
-
指令...
-
return n
-
}
注意:shell的返回值是exit,函數里用return輸出返回值。
shell函數的執行
調用函數
1)直接執行函數名即可(不帶括號)。
函數名
注意:1、執行函數時,函數后的小括號不需要。2、函數定義及函數體必須在要執行的函數名的前面定義,shell的執行從上到下按行執行。
2)帶參數的函數執行方法。
函數名 參數1 參數2
注意:函數的傳參和腳本的傳參類似,只是腳本名換成函數名即可。
函數后接的參數說明:1、shell的位置參數($1、$2、$3、$4、$5、$#、$*、$?、$@)都可以是函數的參數。2、此時父腳本的參數臨時地被函數參數所掩蓋或隱藏。3、$0比較特殊,它仍然是父腳本的名稱。4、當函數完成時,原來的命令行腳本的參數即恢復。5、在shell函數里面,return命令功能與shell里的exit類似,作用是跳出函數。6、在shell函數體里使用exit會退出整個shell腳本,而不是退出shell函數。7、return語句會返回一個退出值(返回值)給調用函數的程序。8、函數的參數變量是在函數體里面定義,如果是普通變量,一般使用local i定義。
shell函數范例
開發腳本建立兩個簡單函數並調用執行。
-
[root@lamp /]# cat fun01.sh
-
#!/bin/bash
-
test_fun(){
-
echo "i am shell fun."
-
}
-
test_fun
-
[root@lamp /]# sh fun01.sh
-
i am shell fun.
調用其它腳本文件中的函數。
-
[root@lamp /]# cat fun01.sh
-
#!/bin/bash
-
. /fun02.sh
-
test_fun(){
-
echo "i am shell fun."
-
}
-
test_fun
-
test_fun02
-
[root@lamp /]# cat fun02.sh
-
#!/bin/bash
-
test_fun02(){
-
echo "i am shell fun02."
-
}
-
[root@lamp /]# sh fun01.sh
-
i am shell fun.
-
i am shell fun02.
傳參
-
[root@lamp /]# cat fun01.sh
-
#!/bin/bash
-
. /fun02.sh
-
test_fun(){
-
echo "i am shell fun."
-
}
-
test_fun
-
test_fun02 $1
-
[root@lamp /]# cat fun02.sh
-
#!/bin/bash
-
test_fun02(){
-
echo "i am shell $1."
-
}
-
[root@lamp /]# sh fun01.sh golden
-
i am shell fun.
-
i am shell golden.
函數傳參轉成參數命令行傳輸,對任意指定url判斷是否異常。
-
[root@lamp /]# curl -I -m 3 -o /dev/null -s -w %{http_code} www.baidu.com
-I 僅測試HTTP頭
-m 3 最多查詢3秒
-o /dev/null 屏蔽原有輸出信息
-s silent 模式,不輸出任何東西
-w %{http_code} 控制額外輸出
-
[root@lamp ~]# cat check_url.sh
-
#!/bin/bash
-
[ -f /etc/init.d/functions ]&& . /etc/init.d/functions
-
usage(){
-
echo "USAGE:$0 url."
-
exit 1
-
}
-
RETVAL=0
-
check(){
-
wget -I 10 --spider -t 2 $1 &>/dev/null
-
RETVAL=$?
-
if [ $RETVAL -eq 0 ];then
-
action "$1 url" /bin/true
-
else
-
action "$1 url" /bin/false
-
fi
-
return $RETVAL
-
}
-
main(){
-
if [ $# -ne 1 ];then
-
usage
-
fi
-
check $1
-
}
-
main $*
-
[root@lamp ~]# sh check_url.sh www.baidu.com
-
www.baidu.com url [ OK ]
-
[root@lamp ~]# sh check_url.sh www.baiduxxxx.com
-
www.baiduxxxx.com url [FAILED]
給字符串加顏色。
-
[root@lamp ~]# cat color.sh
-
#!/bin/bash
-
RED_COLOR='\E[1;31m'
-
GREEN_COLOR='\E[1;32m'
-
YELLOW_COLOR='\E[1;33m'
-
BLUE_COLOR='\E[1;34m'
-
PINK='\E[1;35m'
-
RES='\E[0m'
-
echo -e "$RED_COLOR red $RES"
-
echo -e "$GREEN_COLOR GREEN $RES"
-
echo -e "$YELLOW_COLOR YELLOW $RES"
-
echo -e "$BLUE_COLOR BLUE $RES"
-
echo -e "$PINK PINK $RES"
輸出結果。
傳2個參數,顏色名稱和內容,輸出帶顏色的內容。
-
[root@lamp ~]# cat color_str.sh
-
#!/bin/bash
-
RED='\E[1;31m'
-
GREEN='\E[1;32m'
-
YELLOW='\E[1;33m'
-
BLUE='\E[1;34m'
-
PINK='\E[1;35m'
-
RES='\E[0m'
-
usage(){
-
echo "USAGE:$0 color contents."
-
exit 1
-
}
-
color(){
-
if [ "$1" = "red" ];then
-
echo -e "${RED}$2 $RES"
-
elif [ "$1" = "green" ];then
-
echo -e "${GREEN}$2 $RES"
-
elif [ $1 = "yellow" ];then
-
echo -e "${YELLOW}$2 $RES"
-
elif [ "$1" = "blue" ];then
-
echo -e "${BLUE}$2 $RES"
-
elif [ "$1" = "pink" ];then
-
echo -e "${PINK}$2 $RES"
-
else
-
echo "$2"
-
fi
-
}
-
main(){
-
if [ $# -ne 2 ];then
-
usage
-
fi
-
color $1 $2
-
}
-
main $*
輸出結果。
case結構條件句
case結構條件句語法
case語句實際上就是規范的多分支if語句。
-
case "字符串變量" in
-
值1) 指令1...
-
;;
-
值2) 指令2...
-
;;
-
*) 指令3...
-
esac
case結構條件句范例
根據用戶的輸入判斷是哪個數字。如果用戶輸入數字輸出對應輸入的數字,如果是其他內容返回不正確。
-
[root@lamp ~]# cat case.sh
-
#!/bin/bash
-
usage(){
-
echo "USAGE:$0 number."
-
exit 1
-
}
-
case_fun(){
-
case $1 in
-
[1-3])
-
echo $1
-
;;
-
*)
-
echo "input error."
-
esac
-
}
-
main(){
-
case $# in
-
1) case_fun $1
-
;;
-
*) usage
-
esac
-
}
-
main $*
輸出結果。
-
[root@lamp ~]# sh case.sh
-
USAGE:case.sh number.
-
[root@lamp ~]# sh case.sh 1
-
1
-
[root@lamp ~]# sh case.sh 2
-
2
-
[root@lamp ~]# sh case.sh 3
-
3
-
[root@lamp ~]# sh case.sh 4
-
input error.
執行腳本打印一個水果菜單:
1、apple
2、pear
3、banana
4、cherry
當用戶選擇水果的時候,打印選擇水果是什么,並給水果單詞加上顏色。
-
[root@lamp ~]# cat fruit.sh
-
#!/bin/bash
-
RED='\E[1;31m'
-
GREEN='\E[1;32m'
-
YELLOW='\E[1;33m'
-
BLUE='\E[1;34m'
-
PINK='\E[1;35m'
-
RES='\E[0m'
-
FLICKER='\E[31;5m'
-
usage(){
-
echo -e "${FLICKER}Pls select the exist num behind. ${RES}"
-
exit 1
-
}
-
choice(){
-
case $num in
-
1) echo -e "${BLUE}apple${RES}"
-
;;
-
2) echo -e "${GREEN}pear${RES}"
-
;;
-
3) echo -e "${YELLOW}banana${RES}"
-
;;
-
4) echo -e "${RED}cherry${RES}"
-
;;
-
*) usage
-
esac
-
}
-
main(){
-
choice $num
-
}
-
echo "
-
1、apple
-
2、pear
-
3、banana
-
4、cherry"
-
read -t 10 -p "Pls input a num:" num
-
main $num
echo輸出字符串顯示不同顏色。
-
[root@lamp ~]# echo -e "\033[30m 黑色 \033[0m"
-
[root@lamp ~]# echo -e "\033[31m 紅色 \033[0m"
-
[root@lamp ~]# echo -e "\033[32m 綠色 \033[0m"
-
[root@lamp ~]# echo -e "\033[33m 黃色 \033[0m"
-
[root@lamp ~]# echo -e "\033[34m 藍色 \033[0m"
-
[root@lamp ~]# echo -e "\033[35m 紫色 \033[0m"
-
[root@lamp ~]# echo -e "\033[36m 天藍色 \033[0m"
-
[root@lamp ~]# echo -e "\033[37m 白色 \033[0m"
-
[root@lamp ~]# echo -e "\033[40;37m 黑底白字 \033[0m"
-
[root@lamp ~]# echo -e "\033[41;37m 紅底白字 \033[0m"
-
[root@lamp ~]# echo -e "\033[42;37m 綠底白字 \033[0m"
-
[root@lamp ~]# echo -e "\033[43;37m 黃底白字 \033[0m"
-
[root@lamp ~]# echo -e "\033[44;37m 藍底白字 \033[0m"
-
[root@lamp ~]# echo -e "\033[45;37m 紫底白字 \033[0m"
-
[root@lamp ~]# echo -e "\033[46;37m 天藍底白字 \033[0m"
-
[root@lamp ~]# echo -e "\033[47;30m 白底黑字 \033[0m"
更多文字顏色及背景色查看:man console_codes
nginx啟動腳本。
-
[root@lamp ~]# cat nginx_control.sh
-
#!/bin/bash
-
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
-
nginx=/application/nginx/sbin/nginx
-
profile=/application/nginx/logs/nginx.pid
-
state() {
-
RETVAL=$?
-
if [ $RETVAL -eq 0 ];then
-
action "Nginx is $1" /bin/true
-
else
-
action "Nginx is $1" /bin/false
-
fi
-
return $RETVAL
-
}
-
start() {
-
if [ -f $pidfile ];then
-
echo "Nginx is running"
-
else
-
$nginx
-
RETVAL=$?
-
state started
-
fi
-
return $RETVAL
-
}
-
stop() {
-
if [ ! -f $pidfile ];then
-
echo "nginx is not running."
-
else
-
$nginx -s stop
-
state stoped
-
fi
-
return $RETVAL
-
}
-
reload() {
-
if [ -f $pidfile ];then
-
echo "Can't open $pidfile,no such file or directory."
-
else
-
$nginx -s reload
-
state reload
-
fi
-
return $RETVAL
-
}
-
case "$1" in
-
start)
-
start
-
RETVAL=$?
-
;;
-
stop)
-
stop
-
RETVAL=$?
-
;;
-
restart)
-
stop
-
sleep 2
-
restart
-
RETVAL=$?
-
;;
-
reload)
-
reload
-
RETVAL=$?
-
;;
-
*)
-
echo "USAGE:$0 {start|stop|reload|restart}"
-
esac
-
exit $RETVAL
case總結:
1、case語句就相當於多分支的if語句。case語句優勢是更規范、易讀。
2、case語句適合變量的值少,且為固定的數字或字符串集合。(start、stop、restart)。
3、系統服務啟動腳本傳參的判斷多用case語句。
當型循環和直到型循環
while循環工作中使用的不多,一般是守護進程程序或始終循環執行場景,其它循環計算,都會用for替換while。
當型和直到型循環語句
1、while條件句
語法:
-
while 條件
-
do
-
指令 …
-
done
2、until條件句
語法:
-
until 條件
-
do
-
指令 ...
-
done
不管條件是否成立都會執行一次。
當型和直到型基本范例
每隔2秒屏幕輸出負載值。
-
[root@lamp ~]# cat while.sh
-
#!/bin/bash
-
while true
-
do
-
uptime
-
sleep 2
-
done
防止客戶端執行腳本中斷的方法。
1、sh while.sh &
2、nohup while.sh &
3、screen保持回話。
ctl+c:停止執行當前腳本或任務
ctrl+z:暫停執行當前腳本或任務
bg:把當前腳本或任務放入后台執行
fg:當前腳本或任務進行前台執行,如果有多個任務,可以fg加任務編號調出
jobs:查看當前執行的腳本或任務
進程管理命令
bg:后台運行
fg:掛起程序
jobs:顯示后台程序
kill、killall、pkill:殺掉進程
crontab:設置定時
ps:查看進程
pstree:顯示進程狀態樹
top:顯示進程
nice:改變優先權
nohup:用戶退出系統之后繼續工作
pgrep:查找匹配條件的進程
strace:跟蹤一個進程的系統調用情況(strace + pid)
ltrace:跟蹤進程調用庫函數的情況
vmstat:報告虛擬內存統計信息
while實現1到100之和。
-
[root@lamp ~]# cat while_add.sh
-
#!/bin/bash
-
i=1
-
sum=0
-
while [ $i -le 100 ]
-
do
-
((sum+=$i))
-
((i++))
-
done
-
echo $sum
注意:在工作中多使用算法,代碼執行效率更高。
使用while循環豎向打印10、9、8…
-
[root@lamp ~]# cat while_seq.sh
-
#!/bin/bash
-
i=10
-
while [ $i -gt 0 ]
-
do
-
echo "$i"
-
((--i))
-
done
手機充值10元,每發一次短信花費0.15元,當前余額小於0.15元不能發短信,提示余額不足,請充值,可以允許用戶充值后繼續發短信。
-
[root@lamp ~]# cat messages.sh
-
#!/bin/bash
-
total=0
-
menu='
-
1:充值
-
2:發送信息
-
3:退出
-
'
-
pay(){
-
read -t 10 -p "Pls input pay money:" num
-
expr ${num} + 1 &>/dev/null
-
[ $? -ne 0 ]&&{
-
echo "Input error"
-
return 1
-
}
-
if [ ${num} -gt 0 ];then
-
total=$(( $total + $num * 100 ))
-
else
-
echo "Input error"
-
return 1
-
fi
-
}
-
-
send(){
-
if [ ${total} -gt 15 ];then
-
echo "send messages is ok."
-
total=$(( $total - 15 ))
-
else
-
echo "余額不足!"
-
fi
-
}
-
-
while true
-
do
-
echo "當前余額:${total}"
-
echo ${menu}
-
read -t 10 -p "Pls input a num:" choice
-
case ${choice} in
-
1) pay
-
;;
-
2) send
-
;;
-
3) exit 0
-
;;
-
*)
-
esac
-
done
while按行讀取文件的方式。
方式一
-
exec <FILE
-
sum=0
-
while read line
-
do
-
cmd
-
done
方式二
-
cat ${FILE_PATH} | while read line
-
do
-
cmd
-
done
方式三
-
while read line
-
do
-
cmd
-
done<FILE
計算apache一天的日志中所有行的各元素的訪問字節數的總和。
-
[root@lamp ~]# cat log_cmd.sh
-
#/bin/bash
-
exec access.log
-
while read line
-
do
-
i=`echo $line|awk '{print $10}'`
-
expr $i + 1 &>/dev/null
-
if [ $? -ne 0 ];then
-
continue
-
fi
-
((sum+=i))
-
done
-
[ -n "$sum" ] && echo $sum
while循環小結。
1、while循環的特長是執行守護進程以及我們希望循環不退出持續執行的場景,用頻率小於1分鍾的循環處理,其他的while循環幾乎都可以被for循環替代。
2、幾乎所有的case語句都可以用if語句替換,一般在系統啟動腳本傳入少量固定規則字符串,用case語句,其他普通判斷多用if。
3、工作中if和for最常用,其次while(守護進程)和case(服務啟動腳本)。
讀取一個文件,倒插入一個新的文件,清空原文件。
-
[root@lamp ~]# cat read_line.sh
-
#!/bin/bash
-
file=/root/read.sh
-
num=`wc -l ${file}|awk -F ' ' '{print $1}'`
-
while [ ${num} -gt 0 ]
-
do
-
line=`tail -1 ${file}`
-
echo ${line}
-
echo ${line}>>/root/read_bak.sh
-
sed -i '$d' ${file}
-
num=`wc -l ${file}|awk -F ' ' '{print $1}'`
-
done
for循環結構
for循環結構語法
1、for循環結構
語法
-
for 變量名 in 變量取值列表
-
do
-
指令…
-
done
在此結構中"in 變量取值列表"可省略,省略時相當於in $@,使用for i就相當於使用for i in $@。
2、C語言型for循環結構
語法
-
for((exp1;exp2;exp3))
-
do
-
指令...
-
done
for和while對比。
-
[root@lamp ~]# cat for.sh
-
#!/bin/bash
-
for((i=1;i<=5;i++))
-
do
-
echo $i
-
done
-
-
[root@lamp ~]# cat while.sh
-
#!/bin/bash
-
i=1
-
while((i<=5))
-
do
-
echo $i
-
((i++))
-
done
方法一:直接列出元素的方法。
-
[root@lamp ~]# cat for_02.sh
-
#!/bin/bash
-
for i in 1 2 3 4 5
-
do
-
echo ssh 192.168.1.${i}
-
done
-
[root@lamp ~]# sh for_02.sh
-
ssh 192.168.1.1
-
ssh 192.168.1.2
-
ssh 192.168.1.3
-
ssh 192.168.1.4
-
ssh 192.168.1.5
方法二:使用大括號的方法
-
[root@lamp ~]# cat for_02.sh
-
#!/bin/bash
-
for i in {1..5}
-
do
-
echo ssh 192.168.1.${i}
-
done
-
[root@lamp ~]# sh for_02.sh
-
ssh 192.168.1.1
-
ssh 192.168.1.2
-
ssh 192.168.1.3
-
ssh 192.168.1.4
-
ssh 192.168.1.5
方法三:使用命令結果。
-
[root@lamp ~]# cat for_03.sh
-
#!/bin/bash
-
for i in `seq 5`
-
do
-
echo ssh 192.168.1.${i}
-
done
-
[root@lamp ~]# sh for_03.sh
-
ssh 192.168.1.1
-
ssh 192.168.1.2
-
ssh 192.168.1.3
-
ssh 192.168.1.4
-
ssh 192.168.1.5
四位一行顯示的優化方法。
-
[root@lamp ~]# seq 10 >a.log
-
[root@lamp ~]# cat a.log
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
[root@lamp ~]# cat a.log|xargs -n4
-
1 2 3 4
-
5 6 7 8
-
9 10
-
[root@lamp ~]# xargs -n4 <a.log
-
1 2 3 4
-
5 6 7 8
-
9 10
-
[root@lamp ~]# cat a.log|grep 3
-
3
-
[root@lamp ~]# grep 3 a.log
-
3
顯示當前路徑的所有文件。
-
[root@lamp ~]# cat for_04.sh
-
#!/bin/bash
-
for i in `ls`
-
do
-
echo $i
-
done
批量生成隨機文件。
-
[root@lamp ~]# cat for_05.sh
-
#!/bin/bash
-
for((i=1;i<=10;i++))
-
do
-
mkdir -p ./test
-
touch ./test/`echo $RANDOM|md5sum|cut -c 1-8`_finished.jpg
-
done
批量改名。
-
[root@lamp ~]# cat for_06.sh
-
#!/bin/bash
-
for i in `ls /root/test`
-
do
-
cd /root/test
-
mv $i `echo $i|sed 's#_finished.jpg#.html#g'`
-
done
-
[root@lamp test]# ls|awk -F '[_]' '{print "mv " $0,$1".html"}'|bash
-
[root@lamp test]# rename "_finished.html" ".jpg" *.html
rename "改什么" "改成什么" 對誰進行修改
排除關閉某服務開機自啟動。
-
[root@lamp test]# chkconfig --list|grep 3:on|awk '{print $1}'|egrep -v "rsyslog|sshd|systat"|sed -r 's#(.*)#chkconfig \1 off#g'|bash
for實現1+2+3+…+100。
-
[root@lamp ~]# cat for_07.sh
-
#!/bin/bash
-
for ((i=1;i<=100;i++))
-
do
-
((sum+=$i))
-
done
-
echo "sum=${sum}"
-
[root@lamp ~]# cat for_08.sh
-
#!/bin/bash
-
for i in `seq 100`
-
do
-
let sum+=i
-
done
-
echo "sum=${sum}"
算法最快。
-
[root@lamp ~]# echo $((100*(100+1)/2))
chpasswd批量更新用戶口令工具。
建立指令文件passwd.txt(格式為[username:passwd])
# vi passwd.txt
username1:passwd1
username2:passwd2
將passwd.txt的內容傳輸到chpasswd指令來修改相應用戶的密碼
# chpasswd < doiido.txt
break continue exit return對比
break、continue、exit一般用於循環結構中控制循環(for、while、if)的走向。
break n:n表示跳出循環的層數,如果省略n表示跳出整個循環。
continue n:n表示退到第n層繼續循環,如果省略n表示跳過本次循環,忽略本次循環的剩余代碼,進入循環的下一次循環。
exit n:退出當前shell程序,n為返回值。n也可以省略,再下一個shell里通過$?接收這個n值。
return n:用於在函數里,作為函數的返回值,用於判斷函數執行是否正確。
-
[root@lamp ~]# cat for_09.sh
-
#!/bin/bash
-
for((i=0;i<=5;i++))
-
do
-
if [ $i -eq 3 ];then
-
#continue
-
#break
-
exit
-
fi
-
echo $i
-
done
-
echo "ok"
contine生效
-
[root@lamp ~]# sh for_09.sh
-
0
-
1
-
2
-
4
-
5
-
ok
break生效
-
[root@lamp ~]# sh for_09.sh
-
0
-
1
-
2
-
ok
exit生效
-
[root@lamp ~]# sh for_09.sh
-
0
-
1
-
2