set nocompatible set history=100 filetype on filetype plugin on filetype indent on set autoread set mouse=c syntax enable set cursorline hi cursorline guibg=#00ff00 hi CursorColumn guibg=#00ff00 set foldenable set foldmethod=manual set foldcolumn=0 setlocal foldlevel=3 set foldclose=all nnoremap <space> @=((foldclosed(line('.')) < 0) ? 'zc' : 'zo')<CR> set expandtab set tabstop=4 set shiftwidth=4 set softtabstop=4 set smarttab set ai set si set wrap set sw=4 set wildmenu set ruler set cmdheight=1 set lz set backspace=eol,start,indent set whichwrap+=<,>,h,l set magic set noerrorbells set novisualbell set showmatch set mat=4 set hlsearch set ignorecase set encoding=utf-8 set fileencodings=utf-8 set termencoding=utf-8 set smartindent set cin set showmatch set guioptions-=T set guioptions-=m set vb t_vb= set laststatus=4 set pastetoggle=<F9> set background=dark highlight Search ctermbg=black ctermfg=white guifg=white guibg=black autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()" func SetTitle() if expand("%:e") == 'sh' call setline(1, "#!/bin/bash") call setline(2, "##############################################################") call setline(3, "# File Name: ".expand("%")) call setline(4, "# Version: V1.0") call setline(5, "# Author: neo") # 做者 call setline(6, "# Organization: anonymous") # 公司名 call setline(7, "# Created Time : ".strftime("%F %T")) call setline(8, "# Description:") call setline(9, "##############################################################") endif endfunc
# 一、单分支if条件句语法: if 条件表达式 then 指令 fi # 二、双分支if条件句语法: if 条件表达式 then 指令 else 指令 fi # 三、多分支if条件句语法: if 条件表达式1 then 指令1 elif 条件表达式2 then 指令2 else 指令3 fi # if条件单分支与条件测试编程对比实践: # 例1:若是不存在 /backup 目录就建立 #!/bin/bash path="/backup" [ -d $path ] || mkdir /backup -p if [ -d $path ] then : # shell 中 , : 表示什么都不作 else mkdir $path -p fi [ ! -d $path ] && mkdir $path -p if [ ! -d $path ] then mkdir $path -p fi # 例2:开发shell脚本判断系统剩余内存的大小,若是低于 100MB 就提示内存不足,不然提示内存充足 # 分析: 1)提取系统内存 2) if进行判断 # 获取内存的命令: free -m [root@m01 ~]# free -m total used free shared buffers cached Mem: 474 214 259 0 78 33 -/+ buffers/cache: 102 371 Swap: 767 0 767 [root@m01 ~]# # linux默认把剩余的内存都看成 buffers/cache 对待,因此上面的 371 就表示剩余的内存(单位是 MB) # 取出 剩余内存371的方法以下: [root@m01 ~]# free -m|awk 'NR==3{print $4}' 371 [root@m01 ~]# free -m|awk 'NR==3{print $NF}' # $NF 表示的最后一个Field(列),即输出最后一个字段的内容 371 # 例题2的示例: [root@m01 practice]# cat get_memory_size.sh #!/bin/bash ############################################################## # File Name: get_memory_size.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-06-27 23:38:55 # Description: ############################################################## mem=`free -m|awk 'NR==3{print $NF}'` if [ $mem -lt 100 ] then echo "memory insufficient" else echo "memory is sufficient" fi [root@m01 practice]# bash get_memory_size.sh memory is sufficient # 注意: read 读入没办法用 $#
函数的概念与做用:java
函数的做用就是将程序里屡次被调用的相同代码组合起来(函数体),并为其取个名字(即函数名),其它全部想重复调用这部分代码的地方都只 须要调用这个名字就能够了。当须要修改这部分重复代码时,也只须要改变函数体内的一部分代码便可实现全部调用的修改,也能够把函数独立写 到文件里,当须要调用函数时,再加载进来使用。 # shell函数的优点: 1. 把相同的程序段定义成函数,能够减小整个程序的代码量,提高开发效率 2. 增长程序的可读、易读性,提高管理效率 3. 能够实现程序功能模块化,使得程序具有通用性(可移植性) # 对于shell来讲,Linux系统里面的近2000个命令均可以说是shell的函数
# 语法1: function 函数名(){ 指令集 return 返回值 } # 语法2: function 函数名 { # 这种定义方式时, 函数名 和 { 之间必需要有一个空格 指令集 return 返回值 } # 语法3:(推荐) 函数名(){ 指令集 return 返回值 }
shell函数的执行:linux
带参数的函数的执行:面试
注意: 上图中的第3条表示,$0 依然是脚本的名字,而不是函数所在脚本的名字shell
[root@m01 func]# cat func_04.sh #!/bin/bash ############################################################## # File Name: func_04.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-06-28 10:25:16 # Description: ############################################################## function func01(){ local i="local neo" # local 变量名 ---> 定义局部变量,该变量只能在函数内部使用 echo "I am $i" return 120 # 函数的返回值 } echo "local var val:$i" # 局部变量在函数外部不能被调用 func01 [root@m01 func]# sh func_04.sh local var val: I am local neo [root@m01 func]# echo $? # exit [<n>] 状态码n能够不指定,默认是上一条命令的退出状态码。 120 [root@m01 func]# # 在函数内的变量最好加上 local ,即把函数内的变量定义成 局部变量,避免变量冲突
# 方法一、 wget 命令: --spider # 模拟爬虫 -q # 安静访问 -o /dev/null # 不输出 -T # --timeout 超时时间 -t # --tries 重试次数 [root@m01 func]# wget --spider -T 5 -q -o /dev/null -t 2 www.baidu.com [root@m01 func]# echo $? # 经过 echo $? 检测 wget 的URL是否正常 0 [root@m01 func]# # 方法二、 curl 命令: -I # 看响应头 -s # 安静访问 -o /dev/null # 不输出 -w %{http_code} # 返回状态码;200为正常 -m01 # 超时时间 [root@m01 func]# curl www.baidu.com -s &>/dev/null [root@m01 func]# echo $? # 也是经过查看 curl 的执行结果来判断 URL 是否正常 0 [root@m01 func]# curl -I -m 5 -s -w "%{http_code}\n" -o /dev/null www.baidu.com 200 # 也可经过查看 状态码 查看 URL 是否正常 # 示例代码: [root@m01 func]# cat checkurl.sh #!/bin/bash ############################################################## # File Name: checkurl.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-06-29 09:19:34 # Description: ############################################################## function usage(){ # 输入有误时的函数 echo "Usage:$0 url" exit 1 } function checkurl(){ # 检测网站是否正常的函数 wget -q -o /dev/null -t 2 -T 5 $1 if [ $? -eq 0 ] then echo "$1 is ok" else echo "$1 failed" fi } function main(){ # 至关于 入口函数 if [ $# -ne 1 ] then usage # 若是输入的参数个数不为1,则调用 usage 函数 fi checkurl $1 # 调用检测url的函数 } main $* # $* :把全部的参数都传给 main 函数 [root@m01 func]# sh checkurl.sh Usage:checkurl.sh url [root@m01 func]# sh checkurl.sh www.baidu.com 2 Usage:checkurl.sh url [root@m01 func]# sh checkurl.sh www.baidu.com www.baidu.com is ok
case结构条件句至关于多分支的 if/elif/else 条件句,可是它比这些条件句看起来更规范工整,常被用于实现系统服务启动脚本等企业应用场景中。 # case语句的语法: case "变量" in 值1) 指令1... ;; 值2) 指令2... ;; 值3) 指令3... ;; *) 指令4... esac # 示例代码: [root@m01 func]# cat case01.sh #!/bin/bash cat <<EOF 1. install lamp 2. install lnmp 3. exit EOF read -p "pls input an integer from above:" num # 1. 判断是否为数字 expr 2 + $num &>/dev/null if [ $? -ne 0 ] then echo "Usage:$0 {1|2|3}" exit 1 fi # 判断执行处理 case $num in 1) echo "install lamp..." ;; 2) echo "install lnmp..." ;; 3) echo "bye" exit ;; *) echo "Uage:$0 {1|2|3}" exit 1 esac [root@m01 func]# sh case01.sh 1. install lamp 2. install lnmp 3. exit pls input an integer from above:1 install lamp... [root@m01 func]# sh case01.sh 1. install lamp 2. install lnmp 3. exit pls input an integer from above:3 bye [root@m01 func]# sh case01.sh 1. install lamp 2. install lnmp 3. exit pls input an integer from above:6 Uage:case01.sh {1|2|3}
示例1:给不一样内容加不一样的颜色编程
[root@m01 func]# cat case02.sh #!/bin/bash ############################################################## # File Name: case02.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-06-30 23:38:25 # Description: ############################################################## red="\033[31m" green="\033[32m" yellow="\033[33m" blue="\033[34m" tail="\033[0m" function color(){ case $1 in red) echo -e "${red}$2${tail}" ;; green) echo -e "${green}$2${tail}" ;; yellow) echo -e "${blue}$2${tail}" ;; blue) echo -e "${blue}$2${tail}" ;; *) echo {Usage:$0 colorfunction color char} exit 1 esac } cat <<EOF 1.apple 2.pear 3.banana 4.cherry EOF read -p "pls input a number:" num case $num in 1) color red apple ;; 2) color green pear ;; 3) color yellow banana ;; 4) color blue cherry ;; *) echo "Usage:$0 {1|2|3|4}" exit 1 esac [root@m01 func]# sh case02.sh 1.apple 2.pear 3.banana 4.cherry pls input a number:1 apple [root@m01 func]#
示例2:开发网络服务rsync服务的启动脚本实践vim
利用case语句开发Rsync服务启动中止脚本,本例采用case语句以及新的思路来实现。数组
# 分析: 1. 启动命令: rsync --daemon 2. 中止进程: pkill rsync killall rsync kill 进程号 # 推荐这种方式 [root@m01 ~]# rsync --daemon Failed to parse config file: /etc/rsyncd.conf # 这台主机上没有 rsync 环境 [root@m01 ~]# touch /etc/rsyncd.conf # 建立一个 rsyncd.conf 的空文件,就能建立一个最简单的 rsync 环境,此时 rsync 就能启动 [root@m01 ~]# rsync --daemon [root@m01 ~]# [root@m01 ~]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 15961 root 4u IPv4 89573 0t0 TCP *:rsync (LISTEN) # rsync 已经启动 rsync 15961 root 5u IPv6 89574 0t0 TCP *:rsync (LISTEN) [root@m01 ~]# pkill rsync [root@m01 ~]# lsof -i:873 [root@m01 ~]# rsync --daemon [root@m01 ~]# killall rsync [root@m01 ~]# lsof -i:873 [root@m01 ~]# rsync --daemon [root@m01 ~]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 16068 root 4u IPv4 90215 0t0 TCP *:rsync (LISTEN) rsync 16068 root 5u IPv6 90216 0t0 TCP *:rsync (LISTEN) [root@m01 ~]# kill 16068 [root@m01 ~]# lsof -i:873 [root@m01 ~]#
示例代码1:基本的 rsync 启动脚本bash
[root@m01 func]# cat rsyncd.sh #!/bin/bash ############################################################## # File Name: rsyncd.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-07-01 23:34:57 # Description: ############################################################## case "$1" in start) rsync --daemon if [ $? -eq 0 ] then echo "rsync startup ok" else echo "rsync startup failed" fi ;; stop) killall rsync if [ $? -eq 0 ] then echo "rsync stop ok" else echo "rsync stop failed" fi ;; restart) killall rsync && sleep 1 && rsync --daemon # sleep 1 ---> 中止1秒 (注意:重启中间要停一下) if [ $? -eq 0 ] then echo "rsync restart ok" else echo "rsync restart failed" fi ;; *) echo "Usage:$0 {start|stop|restart}" exit 1 esac [root@m01 func]# bash rsyncd.sh start rsync startup ok [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 16228 root 4u IPv4 91096 0t0 TCP *:rsync (LISTEN) rsync 16228 root 5u IPv6 91097 0t0 TCP *:rsync (LISTEN) [root@m01 func]# bash rsyncd.sh stop rsync stop ok [root@m01 func]# lsof -i:873 [root@m01 func]# bash rsyncd.sh start rsync startup ok [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 16259 root 4u IPv4 91271 0t0 TCP *:rsync (LISTEN) rsync 16259 root 5u IPv6 91272 0t0 TCP *:rsync (LISTEN) [root@m01 func]# bash rsyncd.sh restart rsync restart ok [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 16265 root 4u IPv4 91312 0t0 TCP *:rsync (LISTEN) # 重启以后 进程号发生了改变 rsync 16265 root 5u IPv6 91313 0t0 TCP *:rsync (LISTEN) [root@m01 func]#
示例代码2:完善实用的 rsync 启动脚本网络
[root@m01 func]# cp rsyncd.sh rsyncd2.sh # 作备份 [root@m01 func]# cat rsyncd2.sh #!/bin/bash # chkconfig: 2345 20 80 # description: rsync start and stop script # 上面两行的做用是让脚本开机自启动 (这两行必须写在脚本开头) ############################################################## # File Name: rsyncd.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-07-01 23:34:57 # Description: ############################################################## function start(){ rsync --daemon retval=$? # 获取上一条命令的执行结果做为返回值; 外部须要调用这个 retval ,因此定义成全局变量 if [ $retval -eq 0 ] then echo "rsync startup ok" return $retval # 专业的脚本函数须要给 返回值 else echo "rsync startup failed" return $retval fi } function stop(){ killall rsync retval=$? if [ $retval -eq 0 ] then echo "rsync stop ok" return $retval else echo "rsync stop failed" return $retval fi } case "$1" in start) start retval=$? # 接收 start 的执行结果并赋值给 retval 做为返回值 ;; stop) stop retval=$? ;; restart) stop && sleep 1 && start retval=$? ;; *) echo "Usage:$0 {start|stop|restart}" exit 1 esac exit $retval # 把上面的执行结果返回给脚本外面 [root@m01 func]# lsof -i:873 [root@m01 func]# sh rsyncd2.sh start rsync startup ok [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 16731 root 4u IPv4 93672 0t0 TCP *:rsync (LISTEN) rsync 16731 root 5u IPv6 93673 0t0 TCP *:rsync (LISTEN) [root@m01 func]# sh rsyncd2.sh restart rsync stop ok rsync startup ok [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 16737 root 4u IPv4 93713 0t0 TCP *:rsync (LISTEN) # 重启以后 pid 发生了变化 rsync 16737 root 5u IPv6 93714 0t0 TCP *:rsync (LISTEN) [root@m01 func]# sh rsyncd2.sh stop rsync stop ok [root@m01 func]# sh rsyncd2.sh restart rsync: no process killed rsync stop failed [root@m01 func]# echo $? 1 [root@m01 func]# [root@m01 func]# cp rsyncd2.sh /etc/init.d/rsyncd [root@m01 func]# chmod +x /etc/init.d/rsyncd # 加上执行权限 [root@m01 func]# chkconfig --list rsyncd # 此时 rsync服务 没在开机启动管理里面 service rsyncd supports chkconfig, but is not referenced in any runlevel (run 'chkconfig --add rsyncd') [root@m01 func]# chkconfig --add rsyncd # 把 rsyncd 服务添加到开机启动管理里面 [root@m01 func]# chkconfig --list rsyncd rsyncd 0:off 1:off 2:on 3:on 4:on 5:on 6:off # 此时 rsyncd 在2345级别开机自启动 [root@m01 func]# # 加载系统函数库作输出提示 [root@m01 func]# cp /etc/init.d/rsyncd{,.1} # 作备份 [root@m01 func]# cat /etc/init.d/rsyncd #!/bin/bash # chkconfig: 2345 20 80 # description: rsync start and stop script ############################################################## # File Name: rsyncd.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-07-01 23:34:57 # Description: ############################################################## . /etc/init.d/functions # 调用系统函数库(用于输出提示) function start(){ rsync --daemon retval=$? # 获取上一条命令的执行结果做为返回值; 外部须要调用这个 retval ,因此定义成全局变量 if [ $retval -eq 0 ] then action "rsync startup ok" /bin/true # 用于输出提示 return $retval # 专业的脚本函数须要给 返回值 else action "rsync startup failed" /bin/false return $retval fi } function stop(){ killall rsync &>/dev/null # &>/dev/null 不要输出(只看返回值) retval=$? if [ $retval -eq 0 ] then action "rsync stop ok" /bin/true return $retval else action "rsync stop failed" /bin/false return $retval fi } case "$1" in start) start retval=$? # 接收 start 的执行结果并赋值给 retval 做为返回值 ;; stop) stop retval=$? ;; restart) stop && sleep 1 && start retval=$? ;; *) echo "Usage:$0 {start|stop|restart}" exit 1 esac exit $retval # 把上面的执行结果返回给脚本外面 [root@m01 func]# [root@m01 func]# lsof -i:873 [root@m01 func]# /etc/init.d/rsyncd start rsync startup ok [ OK ] [root@m01 func]# /etc/init.d/rsyncd restart rsync stop ok [ OK ] rsync startup ok [ OK ] [root@m01 func]# /etc/init.d/rsyncd stop rsync stop ok [ OK ] [root@m01 func]# /etc/init.d/rsyncd restart rsync stop failed [FAILED] [root@m01 func]#
示例代码3:和系统脚本相似的 rsync 启动脚本app
# 分析: 1. 系统脚本启动的时候一般会定义一个锁文件 lockfile,当系统启动时建立一个锁文件(能够一般查看有没有这个锁文件来判断服务有没有成功) 2. 当服务中止成功时,两把锁文件删除 [root@m01 func]# cp /etc/init.d/rsyncd{,.2} # 先备份 [root@m01 subsys]# cat /etc/rsyncd.conf # 在 rsyncd.conf 文件中定义一个获取 rsync服务 进程号 pid 的文件 pid file = /var/run/rsyncd.pid [root@m01 subsys]# rsync --daemon [root@m01 subsys]# cat /var/run/rsyncd.pid # 在 rsyncd.conf 中添加了 pid file 以后,启动 rsync 服务以后,pid file 中就会保存 rsync 服务的 pid 18082 [root@m01 func]# cat /etc/init.d/rsyncd #!/bin/bash # chkconfig: 2345 20 80 # description: rsync start and stop script ############################################################## # File Name: rsyncd.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-07-01 23:34:57 # Description: ############################################################## lockfile=/var/lock/subsys/rsync # 先定义一个锁文件 rsyncd_pid_file_path="/var/run/rsyncd.pid" # 定义 rsync 进程号的路径 . /etc/init.d/functions function start(){ rsync --daemon &>/dev/null retval=$? if [ $retval -eq 0 ] then action "rsync startup ok" /bin/true touch $lockfile # 启动成功后,就建立一个锁文件 return $retval else action "rsync startup failed" /bin/false return $retval fi } function stop(){ if test -s $rsyncd_pid_file_path # -s ---> 判断文件是否存在且不为空 then rsyncd_pid=`cat $rsyncd_pid_file_path` if (kill -0 $rsyncd_pid &>/dev/null) # kill -0 进程号 ---> 判断该进程号对应的服务是否存在;存在则echo $?返回0,不存在返1 then kill $rsyncd_pid retval=$? if [ $retval -eq 0 ] then action "rsync stop ok" /bin/true \rm -f $lockfile # 中止成功后就删除锁文件 return $retval else action "rsync stop failed" /bin/false return $retval fi else # 此种状况是:$rsyncd_pid 对应的 rsyncd 服务不存在 action "rsyncd service is not running" return 2 fi else # 此种状况是: $rsyncd_pid_file_path 对应的路径不存在 action "$rsyncd_pid_file_path not exist, or rsyncd not startup" /bin/false return 3 fi } case "$1" in start) start retval=$? # 接收 start 的执行结果并赋值给 retval 做为返回值 ;; stop) stop retval=$? ;; restart) stop && sleep 1 && start retval=$? ;; *) echo "Usage:$0 {start|stop|restart}" exit 1 esac exit $retval # 把上面的执行结果返回给脚本外面 [root@m01 subsys]# lsof -i:873 [root@m01 func]# /etc/init.d/rsyncd stop /var/run/rsyncd.pid not exist, or rsyncd not startup [FAILED] [root@m01 func]# /etc/init.d/rsyncd restart /var/run/rsyncd.pid not exist, or rsyncd not startup [FAILED] [root@m01 func]# /etc/init.d/rsyncd start rsync startup ok [ OK ] [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 18740 root 4u IPv4 102100 0t0 TCP *:rsync (LISTEN) rsync 18740 root 5u IPv6 102101 0t0 TCP *:rsync (LISTEN) [root@m01 func]# /etc/init.d/rsyncd restart rsync stop ok [ OK ] rsync startup ok [ OK ] [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 18764 root 4u IPv4 102183 0t0 TCP *:rsync (LISTEN) rsync 18764 root 5u IPv6 102184 0t0 TCP *:rsync (LISTEN) [root@m01 func]# /etc/init.d/rsyncd stop rsync stop ok [ OK ] [root@m01 func]#
case条件句使用总结:
# while 循环的语法: while 条件表达式 do 指令... done # 示例1:每隔2秒输出一次系统负载(负载是系统性能的基础重要指标)状况 [root@m01 loop]# cat loop01.sh while true do uptime >>/tmp/uptime.log sleep 2 done # 后台运行的命令: & 、nohup 、screen (运维人员经常使用) 常见命令: kill killall pkill ---> 杀掉进程 ps ---> 查看进程 pstree ---> 显示进程状态树 top ---> 显示进程 renice ---> 改变优先权 nohup ---> 用户退出系统以后继续工做(后台运行) pgrep ---> 查找匹配条件的进程 strace ---> 跟踪一个进程的系统调用状况 ltrace ---> 跟踪进程调用库函数的状况
while循环可能会涉及到的一些命令:
示例2:使用while循环对下面的脚本进行修改,使得当执行脚本时,每次执行完脚本之后不退出脚本了,而是继续提示用户输入。
[root@m01 loop]# cat loop02.sh while true do read -p "pls input two numbers:" a b if [ -z "$b" ] then echo "pls input two numbers:" continue # continue 表示结束本次循环 fi expr 10 + $a + $b &>/dev/null if [ $? -ne 0 ] then echo "pls input two numbers:" continue fi echo "a-b=$(($a-$b))" echo "a+b=$(($a+$b))" echo "a*b=$(($a*$b))" echo "a/b=$(($a/$b))" echo "a**b=$(($a**$b))" echo "a%b=$(($a%$b))" done [root@m01 loop]#
示例3:猜数字游戏:首先让系统随机生成一个数字,给这个数字定一个范围(1-60),让用户输入猜的数字,对输入进行判断,若是不符合要求,就给予高或低的提示,猜对后则给出猜对用的次数,用while语句实现。
# 分析: 1. 随机数 ---> $RANDOM # $RANDOM 随机数的范围: 0~32767 [root@m01 loop]# echo $RANDOM 15258 [root@m01 loop]# echo $(($RANDOM%60)) # 取 0~60 之间的随机数 10 [root@m01 loop]# cat loop03.sh #!/bin/bash ############################################################## # File Name: loop03.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-07-02 23:18:45 # Description: ############################################################## val="$((RANDOM%60))" count=0 while true do read -p "pls input one number:" num ((count++)) if [ -z "$num" ] then read -p "pls input one number:" num continue fi expr 10 + $num &>/dev/null if [ $? -ne 0 ] then read -p "pls input one number:" num continue fi if [ $val -gt $num ] then echo "try bigger" elif [ $val -lt $num ] then echo "try smaller" else echo "guess right" echo "count:$count" exit fi done [root@m01 loop]#
示例4: 分析Apache访问日志(access_2010-12-8.log),把日志中每行的访问字节数对应字段数字相加,计算出总的访问量。给出实现程序,用while循环实现。
# while 循环读取文件有3种方式(经常使用下面的前2种方式): # 方式1:在while循环结尾done经过输入重定向指定读取的文件。 while read line # 读取文件内容时,是从文件由上到下读取 do cmd # 对 line 进行处理 done<FILE # 方式2:使用cat读取文件内容,而后经过管道进入while循环处理。 cat FILE_PATH|while read line do cmd done # 方式3:采用exec读取文件后,而后进入while循环处理。 exec <FILE sum=0 while read line do cmd done # 读取文件内容示例 [root@m01 ~]# seq 10 >neo.log [root@m01 ~]# cat neo.log 1 2 3 4 5 6 7 8 9 10 [root@m01 loop]# vim while-read-from-file.sh while read line do echo "$line" done</root/neo.log [root@m01 loop]# sh while-read-from-file.sh 1 2 3 4 5 6 7 8 9 10 # 示例代码以下: [root@m01 loop]# cat loop04.sh #!/bin/bash awk '{print $10}' /root/access_2010-12-8.log|grep -v - >/tmp/count_bytes.log num=0 while read line do ((num+=line)) done</tmp/count_bytes.log echo $num [root@m01 loop]#
while循环涉及的一些命令:
for循环语句和 while 循环语句相似,但 for 循环语句主要用于执行次数有限的循环,而不是用于守护进程以及无限循环。for 循环语句常见的语法有两种 # for循环的语法: 1)普通语法 for 变量名 in 变量取值列表 do 指令... done 2)C语言型for循环语法 for((exp1;exp2;exp3)) do 指令... done # 示例1:经过开发脚本实现仅设置 sshd rsyslog crond network sysstat 服务开机自启动 [root@m01 loop]# cat for01.sh #!/bin/bash for service in `chkconfig |awk '!/crond|network|rsyslog|sshd|sysstat/{print $1}'` do chkconfig $service off done [root@m01 loop]# # 示例2:计算从1加到100之和 [root@m01 loop]# cat for02.sh #!/bin/bash for ((i=1;i<=100;i++)) # C语言型的 for 循环 do ((sum+=i)) done echo $sum echo =================================== for n in {1..100} do ((total+=n)) done echo $total echo =================================== for n in `seq 100` do ((amount+=n)) done echo $amount echo ================================== while ((j<=100)) do ((vol+=j)) ((j++)) done echo $vol [root@m01 loop]# echo $((100*(100+1)/2)) 5050 [root@m01 loop]# # 示例3:在Linux下批量修改文件名,将文件名中的“_finished”去掉。 # 准备测试数据: mkdir /neo -p cd /neo touch stu_102999_1_finished.jpg stu_102999_2_finished.jpg stu_102999_3_finished.jpg touch stu_102999_4_finished.jpg stu_102999_5_finished.jpg ls -l # 以下: [root@m01 ~]# mkdir /neo -p [root@m01 ~]# cd /neo [root@m01 neo]# touch stu_102999_1_finished.jpg stu_102999_2_finished.jpg stu_102999_3_finished.jpg [root@m01 neo]# touch stu_102999_4_finished.jpg stu_102999_5_finished.jpg [root@m01 neo]# ls -l total 0 -rw-r--r-- 1 root root 0 Jul 3 12:06 stu_102999_1_finished.jpg -rw-r--r-- 1 root root 0 Jul 3 12:06 stu_102999_2_finished.jpg -rw-r--r-- 1 root root 0 Jul 3 12:06 stu_102999_3_finished.jpg -rw-r--r-- 1 root root 0 Jul 3 12:06 stu_102999_4_finished.jpg -rw-r--r-- 1 root root 0 Jul 3 12:06 stu_102999_5_finished.jpg # for循环脚本: [root@m01 loop]# cat loop05.sh #!/bin/bash file_path="/neo/*.jpg" for file in `ls $file_path` do mv $file ${file/_finished/} done # awk 操做 [root@m01 neo]# ls *.jpg|awk -F "_finished" '{print "mv",$0,$1$2}'|sh [root@m01 neo]# ll total 0 -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_1.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_2.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_3.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_4.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_5.jpg [root@m01 neo]# # rename 操做 # rename语法: rename [from] [to] file [root@m01 neo]# rename _finished "" *.jpg # 把文件名中的 "_finished" 改成 空 [root@m01 neo]# ll total 0 -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_1.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_2.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_3.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_4.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_5.jpg [root@m01 neo]#
条件与循环控制及程序返回值相关知识点:
数组也是一个变量;Shell的数组就是把有限个元素(变量或字符内容)用一个名字命名,而后用编号对它们进行区分的元素集合。 这个名字就称为数组名,用于区分不一样内容的编号就称为数组下标。组成数组的各个元素(变量)称为数组的元素,有时也称为下标变量。 # 数组的本质仍是变量,是特殊的变量形式,如: array=(1 2 3 4 5)
# 方法1:推荐 array=(one two three four) # 方法2: array=([0]=one [1]=two [2]=three [3]=four) # 方法3: [root@m01 ~]# array[0]=one [root@m01 ~]# array[1]=2 [root@m01 ~]# array[2]=3 [root@m01 ~]# echo ${array[@]} one 2 3 [root@m01 ~]# echo ${array[*]} # 获取全部的数组元素 one 2 3 [root@m01 ~]# 方法4:命令的结果放到数组里,推荐。 array=(`ls /server/scripts`) # 操做数组元素 # 读取数组内容 *** [root@m01 ~]# array=(1 2 3) [root@m01 ~]# echo ${array[0]} 1 [root@m01 ~]# echo ${array[*]} 1 2 3 [root@m01 ~]# echo ${array[@]} 1 2 3 [root@m01 ~]# echo ${#array[@]} # 数组的长度 3 [root@m01 ~]# echo ${array[4]} [root@m01 ~]# # 给数组添加内容 [root@m01 ~]# array[3]=neo [root@m01 ~]# echo ${array[*]} 1 2 3 neo [root@m01 ~]# array[3]=four # 会把数组的元素覆盖 [root@m01 ~]# echo ${array[*]} 1 2 3 four # 会把数组的元素覆盖 [root@m01 ~]# # 删除数组内容 [root@m01 ~]# unset array[1] # 删除数组下标为1的数组元素 [root@m01 ~]# echo ${array[*]} 1 3 four [root@m01 ~]# echo ${array[2]} 3 [root@m01 ~]# # for循环数组: [root@m01 loop]# cat array_for.sh #!/bin/bash array=(1 2 3 4 5) for n in ${array[*]} do echo $n done echo ======================= for ((i=0;i<${#array[*]};i++)) # C语言型的for 循环数组;数组的下标从0开始 do echo ${array[i]} # i 是下标 done [root@m01 loop]# sh array_for.sh 1 2 3 4 5 ======================= 1 2 3 4 5 [root@m01 loop]#
# (1)定义命令 静态数组: array=(1 2 3) 动态数组: array=($(ls)) 或 array=(`ls`) 给数组赋值: array[3]=4 (2)打印命令 打印全部元素: ${array[@]} 或 ${array[*]} 打印数组长度: ${#array[@]}或${#array[*]} 打印单个元素: ${array[i]} #<==i是数组下标
企业实践:利用bash for循环打印下面这句话中字母数不大于6的单词(某企业面试真题)。
I am oldboy teacher welcome to oldboy training class
[root@m01 loop]# cat loop06.sh #!/bin/bash array=(I am oldboy teacher welcome to oldboy training class) for word in ${array[*]} do if [ ${#word} -le 6 ] then echo ${word} fi done echo =================== for ((i=0;i<${#array[*]};i++)) do if [ ${#array[i]} -le 6 ] then echo ${array[i]} fi done [root@m01 loop]# sh loop06.sh I am oldboy to oldboy class =================== I am oldboy to oldboy class [root@m01 loop]#