shell函数
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
posted on 2018-09-01 17:29 yinshoucheng 阅读(2319) 评论(0) 编辑 收藏 举报