shell脚本进阶函数递归和信号捕捉
1.1)函数内部变量会和外部变量起冲突:
例:
[root@centos7 ~]# name=weilan [root@centos7 ~]# func1(){ name=bbb; echo $name ; } [root@centos7 ~]# func1 bbb [root@centos7 ~]# echo $name bbb
2)为了避免出现这种情况,我们函数内部的变量设置为本地变量
例:
[root@centos7 ~]# name=weilan [root@centos7 ~]# func(){ local name=bbb; echo $name; } [root@centos7 ~]# func bbb [root@centos7 ~]# echo $name weilan
local只影响函数内部的变量,不影响函数外部的变量,local变量只能在函数体内用
范例:初始化系统
[root@centos7 data]# vim functions disable_selinux(){ sed -i.bak 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config action "SELINUX已禁用,重新启动后才可生效" } disable_firewall(){ systemctl disable --now firewalld &> /dev/null action "防火墙已禁用" } set_ps1(){ echo "PS1='\[\e[1;35m\][\u@\h \w \!]\$\[\e[0m\]'" > /etc/profile.d/reset.sh action "提示符已修改成功,请重新登录生效" } set_eth(){ sed -i.bak '/GRUB_CMDLINE_LINUX=/s#"$# net.ifnames=0"#' /etc/default/grub grub2-mkconfig -o /boot/grub2/grub.cfg &> /dev/null action "网络名称已修改成功,请重新启动才能生效" } [root@centos7 data]# vim chushihua.sh #!/bin/bash . /data/functions PS3="请选择相应的编号(1-6):" MENU=' 禁用SELINUX 关防火墙 修改提示符 修改网卡名 以上全实现 退出 ' select M in $MENU; do case $REPLY in 1) disable_selinux ;; 2) distable_firewall ;; 3) set_ps1 ;; 4) set_eth ;; 5) disable_selinux disable_firewall set_ps1 set_eth ;; 6) break ;; *) echo "请输入正确数字!" esac done
[root@centos7 data]# ./chushihua.sh 1) 禁用SELINUX 3) 修改提示符 5) 以上全实现 2) 关防火墙 4) 修改网卡名 6) 退出 请选择相应的编号(1-6):5 SELINUX已禁用,重新启动后才可生效 防火墙已禁用 提示符已修改成功,请重新登录生效 网络名称已修改成功,请重新启动才能生效 请选择相应的编号(1-6):6
2.函数递归
函数自己调用自己,同时必须有结束函数的出口语句结束死循环
例:一个死循环递归
[root@centos7 data]# func(){ echo $i; echo "RUN func"; let i++; }
3.阶乘
例:用函数表达阶乘(bash)
#!/bin/bash fact(){ if [ $i -eq 0 -o $1 -eq 1 ]; then echo 1 else echo $[$1*$(fact $[$1-1])] fi
}
fact 3
例:fork炸弹
[root@centos7 data]# bomb(){ bomb|bomb& ; }; bomb
4.信号捕捉trap
1)所谓信号就是比如你使用ctrl+c时,命令被取消时,就会发出一种取消信号SIGINT,随着该信号的发出,命令结果就取消了
2)查看信号类型
trap -l
3)捕捉信号就是:避免外部干扰,捕获某一信号,将其自定义。
捕获信号用trap这个命令
语法:
trap '触发指令' 信号
这里的信号有三种写法:简写、全写、序号都可以
4)忽略信号的操作:
trap '' 信号
5)恢复原信号的操作
trap '-' 信号
6)列出自定义信号操作
trap -p
范例:
#!/bin/bash trap "echo 'Press ctrl + c or ctrl + \'" int quit trap -p for ((i=0;i<=10;i++)) do sleep 1 echo $i done trap ' ' int trap -p for((i=11;i<=20;i++)) do sleep 1 echo $i done trap '-' int trap -p for((i=21;i<=30;i++)) do sleep 1 echo $i done
7)当脚本退出时,执行finish函数
trap finish EXIT
例:
#!/bin/bash finish () { echo finish is at `date +%F-%T` | tee -a /root/finish.sh } trap finish exit while true; do echo running sleep 1 done
5.创建临时文件mktemp
1)我们在编脚本的时候,可能会临时创建一些文件或文件夹,脚本运行完后,这些文件夹也就不存在了,但是会引出一个问题,会和原系统文件冲突,从而导致数据丢失。为了解决此类问题,我们使用mktemp创建临时文件,可以避免冲突。
2)格式:
mktemp [OPTION]...[TEMPLATE](模板)
说明:TEMPLATE:filenameXXX,X至少要出现三个,两个会报错
例:用mktemp生成一个文件
[root@centos8 data]# mktemp fileXXX fileLJM
3)选项:
-d:生成文件夹
例:生成一个临时文件夹在/data/
[root@centos8 data]# mktemp -d /data/tmpXXX /data/tmpqGY
-p:指明临时文件或文件夹存放目录位置
例:
[root@centos8 data]# mktemp -d -p /data/ abcXXX /data/abcWi2
范例:实现文件垃圾箱功能
[root@centos7 data]# vim lajixiang.sh #!/bin/bash DIR=`mktemp -d /tem/trash-$(date +%E%H-%M-%S)XXXXXX` mv $* $DIR echo $* is move to $DIR
6.安装复制文件install
1)install功能强大,相当于cp、chmod、chown、chgrp、mkdir的结合
2)格式
install [OPTION]...[-T] SOURCE DEST #单文件 install [OPTION]..SOURCE...DIRECTORY install [OPTION]... -t DIRECTORY SOURCE install [OPTION]... -d DIRECTORY ... #创建空目录
3)选项:
-m MODE,默认755
-o OWNER 所属者
-g GROUP 所属组
-d DIRNAME 目录
例:复制/etc/issue 为权限700,所属者wang,所属组bin,绝对路径/data/名字为a.txt
[root@centos8 ~]# install -m 700 -o wang -g bin /etc/issue /data/a.txt [root@centos8 ~]# ll /data/a.txt -rwx------ 1 wang bin 23 Mar 7 21:32 /data/a.txt
例:创建一个770权限的文件夹
[root@centos8 ~]# install -m 770 -d /data/installdir/weilan [root@centos8 installdir]# ll /data/installdir/ total 0 drwxrwx--- 2 root root 6 Mar 7 21:35 weilan
这里需要注意的是:这里相当于mkdir -p也会将上级不存在的文件夹创建
记录于2022-3-7-21:39