博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
shell编程
阅读量:4978 次
发布时间:2019-06-12

本文共 30589 字,大约阅读时间需要 101 分钟。

什么是shell

Shell是一个命令解释器,就像是包裹在Linux内核外面的一层外壳,在Linux的终端中我们输入命令后计算机的内核并不能直接执行这些命令, 我们都知道计算机执行的是二进制的代码,而Shell的作用就正好是将这些命令解释成计算机可以执行的二进制代码,而内核就可以执行这些二进制代码, 内核可以控制计算机的硬件工作比如:声卡、网卡等计算机硬件。优势在于处理操作系统底层的业务,有大量的linux系统命令为它作支撑,特别是grep awk sed等。 学好 shell编程并实现通过shell脚本自动化管理系统必备基础  1、vi/vim编辑器的熟练使用,ssh终端及“vimrc”的设置等要搞熟练  2、命令基础  3、linux正则表达式及三剑客grep sed awk  4、常见linux网络部署、优化及排错。例:crond nfs rsync inotify lannmp sersync ssh memcache [root@shell ~]# cat /etc/shells /bin/sh/bin/bash/sbin/nologin/bin/dash/bin/tcsh/bin/csh[root@shell ~]# echo $SHELL/bin/bash[root@shell script]# bash --versionGNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu) shell 脚本开发基本规范及习惯   1、开头指定脚本解释器#!/bin/sh或#!/bin/sh      2、版权信息  可以通过~/.vimrc    #Date   #Author #Mail   #Function  #Version   3、英语注释   4、以.sh结尾   5、成对符号一次性写全,中括号内侧两边各留空格   6、流程语句一次性写完整   7、注意缩进 使用bash命令参数调试 sh [-nvx] scripts.sh -n 不会执行该脚本,仅查询脚本语法是否有问题,并给出错误提示 -v 在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也会给出错误提示 -x 将执行的脚本内容及输出显示到屏幕上,这个是对调试很游泳的参数 提示 1、同bash命令参数功能 2、开启调试功能通过set -x命令,关闭用set +x 优点:和bash -x相比,set -x可以缩小调试的作用域 脚本中需要调试的代码前后 set -x diff /tmp/a /tmp/b set +x

 

 shell脚本的执行

当shell脚本以非交互式方式运行时,它会先查找系统环境变量(通常是.bachrc .bash_profile /etc/bashrc /etc/profile等), 从该环境变量文件开始执行脚本,当读取ENV文件后,shell才会执行文本中的内容.例如定时任务脚本,调用系统变量建议重新定义,以免这些变量不被加载 shell执行方式   1、sh script-name  或 bash  script-name    (推荐方式)   2、/path/script-name或 ./script-name       需要加x权限   3、sh

 

变量

变量简单的说,变量就是用一个固定的字符串(也可能是字母数字等的结合),代替更多复杂的内容,这个内容里面可能还会包含变量和路径,字符串等其他内容,变量的定义是在内存中的。变量类型  环境变量(env,set):用于定义shell运行环境  全局配置地点 /etc/profile /etc/bashrc /etc/profile.d/*.sh     /etc/profile =>USER/LOGNAME/MAIL/PATH/HOSTNAME/HISTSIZE/umask/调用/etc/profile.d/*.sh文件    用户配置地点 ~下.bash_profile .bashrc  设置环境变量1、export LANG=en_US 或先定义再export  设置全局环境变量:写入/etc/profile,source生效  取消设置 unset 环境变量名 全局变量的定义     export VAR=value   VAR=value;export VAR      declare [+/-][option] VAR   -   给变量设定类型属性   +   取消变量类型属性   -i  将变量声明为整型   -x  将变量声明为环境变量   -p  显示指定变量被声明的类型    [root@node83 ~]# a=1 [root@node83 ~]# b=2 [root@node83 ~]# c=$a+$b [root@node83 ~]# echo $c 1+2 [root@node83 ~]# declare -x -i d=$a+$b [root@node83 ~]# echo $d 3  

 

局部变量本地变量:在用户当前shell生存周期的脚本中使用1、普通字符串变量定义    变量名=value   变量名='value'    变量名="value"2、变量名          由字母、数字、下划线,以字母开头默认类型都是字符串型 [root@shell ~]# a=111[root@shell ~]# b=222[root@shell ~]# c=333[root@shell ~]# echo "a=$a"      =>a=111[root@shell ~]# echo 'b=$b'      =>b=$b[root@shell ~]# echo c=$c       =>c=333[root@shell ~]# echo c=${c}      =>c=333 双引号    会解析双引号中的变量名,转义字符等,命令用反引号。简单的整体连续数字,字符串,路径名可以不加引号单引号    所见即所得反引号  一般用于命令,会被执行( 或 $() )  # echo $(date)   Sat Jun 24 07:06:58 CST 2017   # echo `date`   Sat Jun 24 07:07:06 CST 2017 以上内容可能不适用sed  awk(特殊)两个类似,引用变量用单引号  [root@shell script]# awk 'BEGIN {print "$ETT"}'    $ETT  [root@shell script]# awk 'BEGIN {print '$ETT'}'  123  [root@shell script]# awk 'BEGIN {print $ETT}'空tar zcvf etc_$(date +%F).tar.gz /etc/hoststar zcvf etc_`date +%F`.tar.gz /etc/hosts注意${WEEK}day若变量和其他字符组成新的变量就必须给变量加上{}[root@shell home]# a=hello [root@shell home]# echo $aworld [root@shell home]# echo $(a)world -bash: a: command not found world [root@shell home]# echo ${a}world helloworld 一道实用linux运维问题的9种shell解答方法!http://oldboy.blog.51cto.com/2561410/760192

 

位置变量

shell特殊变量(man bash  Parametre块)1、位置变量  $0    获取当前执行的shell脚本的文件名,如果执行脚本带路径,那么就包括脚本路径  $n    获取当前执行脚本的第n个参数,如果大于9,用花括号  $#    获取当前执行的shell脚本后面接的参数总个数  $?  返回命令执行状态值  $*  获取当前脚本所有传参的参数  $@  这个程序的所有参数 "$1" "$2" "$3 "$1"   常用来做case判断
*)        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"        exit 2[root@shell ~]# /etc/init.d/crond Usage:/etc/init.d/crond {start|stop|status|restart|condrestart|try-restart|reload|force-reload}[root@shell ~]# /etc/init.d/crond ddUsage: /etc/init.d/crond {start|stop|status|restart|condrestart|try-restart|reload|force-reload}

 

目录、文件名分离
[root@shell /]# cat /root/script/p.sh   dirname $0basename $0[root@shell /]# sh /root/script/p.sh    /root/script  脚本路径p.sh          脚本名
 
$n    获取当前执行脚本的第n个参数,当n=0时表示脚本的文件名,如果大于9用大括号括起来${
10},参数以空格分开
[root@shell script]# cat p.sh  echo $1[root@shell script]# sh p.sh start   start[root@shell script]# sh p.sh start stopstart[root@shell script]# sh p.sh "start stop"start stop [root@shell script]# cat p.sh echo $0 $1 $2 $3 $4 $# $*[root@shell script]# sh p.sh 1 2 3p.sh 1 2 3 3 1 2 3
$#    获取当前执行的shell脚本后面接的参数总个数,常用来进行参数控制
[root@shell script]# cat p.sh         ==>echo $0  $1 $2 $3 $4 $#[root@shell script]# sh p.sh 1 2 3    ==>p.sh 1 2 3 3[root@shell script]# cat test.sh #!/bin/sh[ $# -ne 2 ] && {  echo "$0 ARG1 AGR2"  exit 1}echo $0 [root@shell script]# sh test.sh a   test.sh ARG1 AGR2[root@shell script]# sh test.sh a btest.sh http://oldboy.blog.51cto.com/2561410/1175971runlevel=$(set -- $(runlevel); eval "echo \$$#" )1)这里的$#就是参数个数为2,即runlevel的结果, 所以\$$#就是$2,即runlevel结果的第二列3[root@G307 ~]# runlevelN 32)eval就是把echo的字符串,当做命令解析! http://oldboy.blog.51cto.com/2561410/1665163 18道Shell高级编程企业实战题及参考答案(一)http://oldboy.blog.51cto.com/2561410/1632876
 

 

$?  返回命令执行状态值     在脚本中exit 控制数字,函数中return 返回值给$?     0成功 非0不成功 一般情况可能--> 1或2权限拒绝  1-125失败 126找到命令,但是无权执行,命令找不到127  企业场景返回值用法     1、判断命令或脚本是否执行成功     2、脚本中函数中的exit 及return返回值给$?$*   获取当前脚本所有传参的参数,将所有的参数视为一个字符串,相当于"$1$2$3"...  注意与$#的区别    main $*取所有参数变成一个传给main $@  这个程序的所有参数 "$1" "$2" "$3" "..." 这是将参数传递给其他程序的最佳方式,因为会保留所有内嵌在每个参数里的任何空白。"$@"  "$*" 都要加双引号。  # set -- "I am" super gtms   # echo $#   3   # for i in "$*";do echo $i;done   I am super gtms   # for i in "$@";do echo $i;done   I am   super   gtms 进程状态变量  $$  当前执行shell进程号(方便以后管理)  $! 执行上一次指令的PID  $? 获取上一指令的返回值  $_ 在此之前执行的命令或脚本的最后一个参数 # mv a.pid pid.sh # cat pid.sh echo $$ > /tmp/a.pid sleep 300 # sh pid.sh & [2] 1813 # ps -ef | grep pid.sh | grep -v grep root       1813   1645  0 22:28 pts/0    00:00:00 sh pid.sh # cat /tmp/a.pid 1813 # kill `cat /tmp/a.pid`

 

bash变量子串的常用操作(一般了解即可)

${#string}   返回$string的长度 # GTMS="HELLO WORLD"
# echo $GTMS | wc -L     ==>11
# echo ${#GTMS}            ==>11
# expr length "$GTMS"   ==>11
[root@shell script]# cat p.sh
for n in I am gtms linux welcome to our training.
do
   if  [ ${#n} -lt 6 ]
       then
          echo $n
   fi
done
输出小于6个字符的单词
${string:position}   在$string中,从位置position之后开始提取子串 position从0开始 [root@shell script]# echo $GTMS
HELLO WORLD
[root@shell script]# echo ${GTMS:2}
LLO WORLD
${string:position:length}   在$string中,从位置position之后开始提取长度为length的子串 [root@shell script]# echo $GTMS    
HELLO WORLD
[root@shell script]# echo ${GTMS:2:3}
LLO
${string#substring}   从$string开头开始删除最短匹配substring的子串 # GTMS=abcABC123ABCabc
# echo ${GTMS#a*C}  /"*是通配符"
123ABCabc  /前面的被匹配删除
${string##substring}   从$string开头开始删除最长匹配substring的子串 [root@shell script]# GTMS=abcABC123ABCabc
[root@shell script]# echo ${GTMS##a*c}    ====删完了
 ${string%substring}   从$string结尾开始删除最短匹配substring的子串 [root@shell script]# echo $GTMS      
abcABC123ABCabc
[root@shell script]# echo ${GTMS%C*c}
abcABC123AB
${string%%substring}   从$string结尾开始删除最长匹配substring的子串 [root@shell script]# echo $GTMS      
abcABC123ABCabc
[root@shell script]# echo ${GTMS%%C*c}
abcAB
${string/pattern/replace}   使用replace来替换第一个匹配到的substring # echo $OLDBOY
I am oldboy oldboy oldgirl
# echo ${OLDBOY/oldboy/youngboy}   
I am youngboy oldboy oldgirl
# echo ${OLDBOY/#I*oldboy/youngboy}
youngboy oldgirl
# echo ${OLDBOY/%old*girl/youngboy}
I am youngboy
${string/#pattern/replace}   如果$string前缀匹配substring,就用replace来替换substring
${string/%pattern/replace}  如果$string后缀匹配substring,就用replace来替换substring
 

 

变量替换(了解即可)

${parameter:-word}   Use  Default  Values.  If parameter is unset or null, the expan-
sion of word is substituted.  Otherwise, the value of  parameter is substituted.
当变量未定义时,返回word内容,否则返回变量的值
[root@shell script]# result=${test:-UNSET}
[root@shell script]# echo $test     ==>空,因为test变量未定义
[root@shell script]# echo $result         ===>UNSET
${parameter:=word}  Assign Default Values. If parameter is unset or null,theexpansion of word is
assigned to parameter.The value of param-eter is then substituted.
Positional parameters and special parameters may not be assigned to in this way.变量未定义时,word赋给变量
[root@shell script]# test=ok
[root@shell script]# result=${test:-UNSET}
[root@shell script]# echo $result         ===>ok
rm -rf ${path:-/tmp} 防止path值为空,从根删除
${parameter:?word}   Display Error if Null or Unset.  If parameter is null or  unset,
the  expansion  of  word (or a message to that effect if word isnot present) is written
to the standard error and the shell, ifit is not interactive, exits.  
Otherwise, the value of parameter is substituted.
 
${parameter:+word}  Use Alternate Value.  If parameter is null or unset, nothing  is
substituted, otherwise the expansion of word is substituted.
 
 

 

变量计算常见命令  (())  let expr bc(小数) $[] 其他都是整数

变量的数值运算  id++ id--    variable post-increment and post-decrement  ++id --id    variable pre-increment and pre-decrement  - +    unary一元 minus and plus  ! ~      logical and bitwise negation非  **    exponentiation幂  * / %  multiplication, division, remainder余数  + -  addition, subtraction  << >>  left and right bitwise shifts  <= >= < >comparison  == !=  equality and inequality  &      bitwise AND  ^      bitwise exclusive OR 位的异或  |      bitwise OR  &&     logical AND  ||     logical ORexpr?expr:exprconditional operator       = *= /= %= += -= <<= >>= &= ^= |=      assignment       expr1 , expr2      comma 1、(()) 只支持整数 (效率高,建议使用)
[root@shell script]# ((a=1+2**3-4%3))      [root@shell script]# echo $a               ===>8[root@shell script]# ((a=a+1))       [root@shell script]# echo $a               ===>9[root@shell script]# echo $((1+2**3-4%3))  ===>8----------------------------[root@shell script]# ((a=1+2**3-4%3))[root@shell script]# echo $a           8[root@shell script]# echo $((a++))     8[root@shell script]# echo $((a++))     9[root@shell script]# echo $((a--))     10[root@shell script]# echo $((a--))     9[root@shell script]# echo $a           8----------------------------[root@shell script]# ((a=1+2**3-4%3))   [root@shell script]# echo $((++a))     9 [root@shell script]# echo $((++a))     10[root@shell script]# echo $((--a))     9[root@shell script]# echo $((--a))     8[root@shell script]# echo $a           8===================================================== [root@shell home]# cat test.sh #!/bin/bash a=6 b=2 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))" ======================================================一个坑[root@shell script]# i=1[root@shell script]# i=i+1[root@shell script]# echo $i    ===> i+1[root@shell script]# i=1[root@shell script]# i=$((i+1))[root@shell script]# echo $i      ===>2 [root@node83 ~]# a=$(( 1 && 1)) [root@node83 ~]# echo $a       1
 
2、let (整数计算) [root@shell script]# i=1 [root@shell script]# let i=i+1    ==>((i=i+1))效率高 [root@shell script]# echo $i      ==> 2 3、expr (整数) 计算符号左右空格  *(乘号)用\屏蔽
[root@shell script]# i=0[root@shell script]# i=`expr $i+1`  [root@shell script]# echo $i        0+1[root@shell script]# i=0[root@shell script]# i=`expr $i + 1` [root@shell script]# echo $i 1 SYNOPSIS  expr EXPRESSION    expr OPTION  Print  the  value of EXPRESSION to standard output.  A blank line below  separates increasing precedence groups.  EXPRESSION may be:       ARG1 | ARG2  ARG1 if it is neither null nor 0, otherwise ARG2       ARG1 & ARG2  ARG1 if neither argument is null or 0, otherwise 0       ARG1 < ARG2  ARG1 is less than ARG2       ARG1 <= ARG2  ARG1 is less than or equal to ARG2       ARG1 = ARG2  ARG1 is equal to ARG2       ARG1 != ARG2  ARG1 is unequal to ARG2       ARG1 >= ARG2  ARG1 is greater than or equal to ARG2       ARG1 > ARG2  ARG1 is greater than ARG2       ARG1 + ARG2  arithmetic sum of ARG1 and ARG2       ARG1 - ARG2  arithmetic difference of ARG1 and ARG2       ARG1 * ARG2  arithmetic product of ARG1 and ARG2       ARG1 / ARG2  arithmetic quotient of ARG1 divided by ARG2        ARG1 % ARG2  arithmetic remainder of ARG1 divided by ARG2     STRING : REGEXP  anchored pattern match of REGEXP in STRING 字符串匹配              /usr/bin/ssh-copy-id脚本中,扩展名判断    if [ -n "$2" ]; then            if expr "$1" : ".*\.pub" > /dev/null ; then            ID_FILE="$1"            else            ID_FILE="$1.pub"    fi     match STRING REGEXP       same as STRING : REGEXP     substr STRING POS LENGTH   substring of STRING, POS counted from 1     index STRING CHARS           index in STRING where any CHARS is found, or 0     length STRING                length of STRING #expr length "$char"计算字符串长度 利用expr进行整数判断   while true     do       read -p "pls input an int:" a       expr $a + 1  &> /dev/null       [ $? -eq 0 ] && echo "int " || echo "not int"     done   [root@shell ~]# chars=`seq -s" " 100` [root@shell ~]# time for i in $(seq 11111);do count=${#chars};done  (效率高) real    0m0.038s user    0m0.037s sys     0m0.000s [root@shell ~]# time for i in $(seq 11111);do count=`echo expr lenth "${chars}"`;done real    0m3.585s user    0m0.180s sys     0m0.867s [root@shell ~]# time for i in $(seq 11111);do count=`echo ${chars}| wc -L`;done; real    0m12.755s user    0m0.348s sys     0m0.870s

 

4、bc 可以整数也可以小数(直接bc回车计算)
  [root@shell script]# i=1.3
  [root@shell script]# i=`echo $i+1|bc`
 
[root@shell script]# echo $i     ===>2.3
  [root@shell script]# echo "1.1-1" | bc
  .1
 
[root@shell script]# echo "5.5 5.6" | awk '{print ($2-$1)}'  ===>0.1
 
[root@shell script]# echo "`seq -s '+' 10`="$((`seq -s "+" 10`))
  1+2+3+4+5+6+7+8+9+10=55
 
[root@shell script]# echo `seq -s '+' 10`=`seq -s "+" 10| bc`   
  1+2+3+4+5+6+7+8+9+10=55
 
[root@shell script]# echo `seq -s '+' 10`=`seq -s " + " 10| xargs expr`
  1+2+3+4+5+6+7+8+9+10=55
 
[root@shell script]# echo {1..9}"+" 10=`echo {1..9}"+" 10 |bc`|sed 's# ##g'
  1+2+3+4+5+6+7+8+9+10=55

 

5、$[]的用法 [root@shell script]# i=1 [root@shell script]# i=$[ i + 3] [root@shell script]# echo $i 4

 

 

条件测试与比较
语法形式  方法一   test <>  方法二   [空格 
<测试表达式>
空格] 建议此种  方法三 [[
<测试表达式>
]] 可以使用通配符进行模式匹配 文件测试表达式man test 常用的文件测试操作符(变量加双引号)   -d FILE        FILE exists and is a directory 文件存在且为目录则真   -e FILE        FILE exists  文件存在即为真   -f FILE        FILE exists and is a regular file 文件存在且为普通文件则真   -L FILE       FILE exists and is a symbolic link (same as -h)   -s FILE        FILE exists and has a size greater than zero 文件存在且大小不为0则真   FILE1 -nt FILE2   FILE1 is newer (modification date) than FILE2   FILE1 -ef FILE2        FILE1 and FILE2 have the same device and inode numbers   FILE1 -ot FILE2        FILE1 is older than FILE2   -z STRING     the length of STRING is zero   -b FILE        FILE exists and is block special   -c FILE        FILE exists and is character special   -g FILE        FILE exists and is set-group-ID   -G FILE        FILE exists and is owned by the effective group ID   -h FILE       FILE exists and is a symbolic link (same as -L)   -k FILE        FILE exists and has its sticky bit set   -O FILE        FILE exists and is owned by the effective user ID   -p FILE        FILE exists and is a named pipe   -r FILE       FILE exists and read permission is granted   -w FILE       FILE exists and write permission is granted   -x FILE      FILE exists and execute (or search) permission is granted   -S FILE        FILE exists and is a socket   -t FD          file descriptor FD is opened on a terminal   -u FILE        FILE exists and its set-user-ID bit is set test条件测试语法及实例 man test 语法格式 test -f (文件存在且为普通文件则表达式成立) [root@shell ~]# test -f /etc/hosts &&echo 1                  ==>1 [root@shell ~]# test -f /etc/hosts &&echo 1 || echo 0     ==>1 [root@shell ~]# test -f /etc/host &&echo 1 || echo 0      ==>0 [root@shell ~]# test ! -f /etc/hosts &&echo 1 || echo 0   ==>0 [root@shell ~]# test ! -f /etc/host &&echo 1 || echo 0    ==>1 [root@shell ~]# test -z "oldboy" && echo 1 || echo 0       ==>0    -z:string长度为0 [root@shell ~]# test -z "" && echo 1 || echo 0             ==>1 [root@shell ~]# [ -z "oldboy" ] && echo 1 || echo 0         ==>0 [root@shell ~]# [ -z ""] && echo 1 || echo 0                 ==>1 [root@shell ~]# [[ -e "/etc/hosts" || -f /etc/hosts ]] && echo 1 || echo 0   ==>1 [root@shell ~]# [ -e "/etc/hosts" || -f /etc/hosts ] && echo 1 || echo 0 -bash: [: missing `]' -bash: -f: command not found 0 [root@shell ~]# [ -e "/etc/hosts" -o  -f /etc/hosts ] && echo 1 || echo 0 1 逻辑连接符
[]              (())         [[]]     
-a && and
-o || or
! ! not
[root@shell ~]# f1=/etc/rc.local;f2=/etc/services [root@shell ~]# [ -f "$f1" -a -f "$f2"  ] && echo 1 || echo 0        ==>1 [root@shell ~]# [ -f "$f1" -a -f "$f3"  ] && echo 1 || echo 0        ==>0 [root@shell ~]# [ -f "$f1" -o -f "$f3"  ] && echo 1 || echo 0        ==>1 # vi /etc/init.d/rsyslog if [ -f /etc/sysconfig/$prog ] ; then     . /etc/sysconfig/$prog fi start() {
        [ -x $exec ] || exit 5 # vi /etc/init.d/nfs [ -x /usr/sbin/rpc.nfsd ] || exit 5 [ -x /usr/sbin/rpc.mountd ] || exit 5 [ -x /usr/sbin/exportfs ] || exit 5 文件测试表达式写法案例 [root@shell ~]# [ -f /etc/hosts ] &&{ echo 1;echo 2;echo 3; } || echo "bye"      1 2 3 ==>相当于if语句 if [ express ] then       命令1     命令2     命令3 fi 条件不成立时执行命令(用于脚本中,写在一行中,需要分号) [ 3 -ne 3] || {
    echo "aaaaaaa"     echo "bbbbbbb"     exit 1 } 字符串测试表达式(必须注意双引号,比较符号两端空格)man test   -n "STRING"        the length of STRING is nonzero  长度不为0为真   -z "STRING"        the length of STRING is zero    长度0为真   "STRING1" = "STRING2"        the strings are equal   "STRING1" != "STRING2"        the strings are not equal 实例 [root@shell ~]# sed -n '30,31p' /etc/init.d/network # Check that networking is up. [ "${NETWORKING}" = "no" ] && exit 6 [root@shell ~]# [ -n "abc" ] && echo 1 || echo 0   ==>1 [root@shell ~]# [ -z "abc" ] && echo 1 || echo 0   ==>0 [root@shell ~]# [ "abc" == "abcd" ] && echo 1 || echo 0   ==>0 [root@shell ~]# [ "abc" == "abc" ] && echo 1 || echo 0   ==>1 [root@shell ~]# test1=abc [root@shell ~]# test2=abd [root@shell ~]# [ "${#test1}" = "${#test2}" ] &&echo 1 || echo 0  (取长度) ==>1 [root@shell ~]# vim /etc/init.d/nfs   [ -z "$MOUNTD_NFS_V2" ] && MOUNTD_NFS_V2=default   [ -z "$MOUNTD_NFS_V3" ] && MOUNTD_NFS_V3=default   [ -z "$RPCNFSDCOUNT" ] && RPCNFSDCOUNT=8   # Set the ports lockd should listen on   if [ -n "$LOCKD_TCPPORT" -o -n "$LOCKD_UDPPORT" ]; then        [ -x /sbin/modprobe ] && /sbin/modprobe lockd $LOCKDARG        [ -n "$LOCKD_TCPPORT" ] && \         /sbin/sysctl -w fs.nfs.nlm_tcpport=$LOCKD_TCPPORT >/dev/null 2>&1        [ -n "$LOCKD_UDPPORT" ] && \         /sbin/sysctl -w fs.nfs.nlm_udpport=$LOCKD_UDPPORT >/dev/null 2>&1          fi    if [ -n "$RQUOTAD" -a "$RQUOTAD" != "no" ]; then        echo -n $"Starting NFS quotas:

整数测试表达式 man test

整数二元比较操作符在[]中及test使用   在(())及[[]]中使用
[]及test (()) [[]]
-eq  equal == 或=
-ne  not equal !=
-gt   greate than >
-ge   greate than >=
-lt   less than <
-le  leass equal <=
小结:整数比较推荐下面用法 [ $num1 -eq $num2 ]    ==>注意空格和比较符号 (($num1>$num2))        ==>无需空格,常规数学比较符号 [root@shell ~]# [ 2 -gt 3 ] && echo 1 || echo 0    ==>0 [root@shell ~]# [ 2 > 3 ] && echo 1 || echo 0     ==>1  错了 [root@shell ~]# [[ 2 > 3 ]] && echo 1 || echo 0    ==>0 [root@shell ~]# a1=10;a2=13 [root@shell ~]# [ $a1 -eq $a2 ] && echo 1 || echo 0  ==>0 整数比较方法推荐   [ $num1 -eq $num2 ]   (($num1 > $unm2)) 利用条件表达式完成,通过传参两个参数,比较两个整数大小 #!/bin/sh [ $# -ne 2 ] &&{
  echo "USAGE:"$0" num1 num2"   exit 1 } #judge int expr $1 + $2 &>/dev/null [ $? -ne 0 ]&&{
 echo "pls input two nums:"  exit 2 } =========================== expr $1 + 1 &>/dev/null RETVAL1=$? expr $2 + 1 &>/dev/null RETVAL2=$? [ $RETVAL1 -ne 0 ] && {
echo "the first num is not int,pls input two nums:" exit 2 } [ $RETVAL2 -ne 0 ] && {
echo "the second num is not int,pls input two nums:" exit 3 } =========================== #compare [ $1 -lt $2 ] &&{
echo "$1<$2" exit 0 } [ $1 -eq $2 ] &&{
echo "$1=$2" exit 0 } [ $1 -gt $2 ] &&{
echo "$1>$2" exit 0 }

 

变量输入及菜单打印

变量输入的3种方式  1、定义 a=1  2、传参方式 $1  3、read交互式读入[root@shell ~]# read -p "pls input:" a        pls input:aaaa[root@shell ~]# echo $aaaaa [root@shell ~]##!/bin.shread -p "pls input a character:" aecho "your input is: $a"综合实例:打印选择菜单,一键安装web服务
cat方式
cat >>menu.txt <<EOF
 1.
 2.
 3.
EOF
echo方式               
echo '
 1.
 2.
 3.
[root@shell ~]# cat menu.sh cat <

 

if条件句语法

单分支结构
if [condition]
    then
    指令
fi
if [condition];then
    指令
fi
if [ -f "$file1" ];then echo 1;fi [ -f "$file1"]&& echo 1
双分支结构
if [ condition ]
    then
          指令
    else
          指令
fi
if [ -f "$file1" ];then echo 1;else echo 0;fi [ -f "$file1"]&& echo 1 || echo 0
陷阱:过滤进程时,脚本名不要带有被过滤的进程名:g/$2/s//$b/g  替代多分支结构if [ condition1 ]  then    指令1  elif  [ condition2 ]  then    指令2  else      指令3fi
[root@shell ~]# cat comparebigsmall.sh
#!/bin/bash
if [ $# -ne 2 ]; then
        echo "USAGE:$0 arg1 arg2"
        exit 2
fi
expr $1 + 1 &>/dev/null
RETVAL1=$?
expr $2 + 1 &>/dev/null
RETVAL2=$?
if [ $RETVAL1 -ne 0 -a $RETVAL2 -ne 0 ];then
        echo "please input two int"
        exit 3
fi
if [ $RETVAL1 -ne 0 ];then
        echo "the first num is not int,pls input again"
        exit 4
fi
if [ $RETVAL2 -ne 0 ];then
        echo "the second num is not int,pls input again"
        exit 5
fi
if [ $1 -lt $2 ];then
        echo "$1<$2"
        exit
elif [ $1 -eq $2 ];then
        echo "$1=$2"
        exit
else
        echo "$1>$2"
        exit
fi
[root@shell ~]# cat comparebigsmall-chuancan.sh
#!/bin/bash
#read 方式
read -p "pls input two num:" a b
[ -z "$a" ]||[ -z "$b" ] && {
        echo "pls input  two num again"
        exit 1
}
#传参方式
a=$1
b=$2
if [ $# -ne 2 ]; then
        echo "USAGE:$0 arg1 arg2"
        exit 2
fi
expr $a + 1 &>/dev/null
RETVAL1=$?
expr $b + 1 &>/dev/null
RETVAL2=$?
if [ $RETVAL1 -ne 0 -a $RETVAL2 -ne 0 ];then
        echo "please input two int"
        exit 3
fi
if [ $RETVAL1 -ne 0 ];then
        echo "the first num is not int,pls input again"
        exit 4
fi
if [ $RETVAL2 -ne 0 ];then
        echo "the second num is not int,pls input again"
        exit 5
fi
if [ $a -lt $b ];then
        echo "$a<$b"
        exit
elif [ $a -eq $b ];then
        echo "$a=$b"
        exit
else
        echo "$a>$b"
        exit
fi
   
 

 

 

shell函数

优势:  1、把相同的程序段定义成函数,减少整个程序代码量  3、增加可读性、易读性  3、实现程序功能模块化shell函数语法  简单语法格式    函数名(){      指令集      return n    }  规范语法格式    function 函数名(){      指令集      return n    } 函数的调用 1、直接执行函数名(不带括号) [root@shell ~]# cat functest.sh boy(){  #先定义 echo "i am a boy" } function girl(){  #定义 echo "i am a girl" } boy  #后执行 girl 函数的引用 . functest.sh或source functest.sh 写程序时定义 bin  fun  log conf目录
2、带传参函数  函数名 参数1 参数2   后接参数     shell位置参数可用,除$0仍然是父脚本的     父脚参数临时被函数参数所掩盖或隐藏,函数完成时,恢复     函数中return与shell中exit类似     函数中exit会退出整个shell     函数的参数变量是在函数体里面的定义
函数传参
脚本传参传给函数传参
[root@shell ~]# cat functest.sh who() {
        echo "i am $1" } who gtms  ==>gtms即$1 [root@shell ~]# sh functest.sh i am gtms
[root@shell ~]# cat functest.sh who() {
        echo "i am $1" } who $1 [root@shell ~]# sh functest.sh gtms i am gtms
 
实例
[root@shell ~]# cat checkweb.sh #!/bin/bash check_url() {
wget -T 10 --spider -t 2 $1 &>/dev/null if [ $? -eq 0 ]     then         echo "$1 is ok"     else         echo "$1 is not ok" fi } check_url $1 [root@shell ~]# sh checkweb.sh www.baidu.com www.baidu.com is ok
[root@shell ~]# cat checkweb.sh
#!/bin/bash
usage() {
    echo "USAGE:$0 arg"
    exit 1
}
check_url() {
curl -s $1 &>/dev/null
if [ $? -eq 0 ]
    then
        echo "$1 is ok"
    else
        echo "$1 is not ok"
fi
}
main(){
    if [ $# -ne 1 ]
        then
          usage
    fi
    check_url $1
}
main $*
[root@shell ~]# sh  checkweb.sh  www.baidu.com    
www.baidu.com is ok
 

 

case结构语句

case语法 case 值 in  模式1)      command1      command2      command3      ;;  模式2|模式3)      command1      command2      command3      ;;  *)      command1      command2      command3      ;;  esac 使用示例 #!/bin/bash read -p "pls input a number in 10: " num     case $num in         1)         echo "number is 1"         ;;         2)         echo "number is 2"         ;;         [3-9])         echo "number is $num"         ;;         *)         echo "the number you input is not in 10"         exit;     esac case语句小结:   1、case语句就相当于多分支的if语句。       case语句优势更规范、易读。   2、case语句适合变量的值少,且为固定的数字或字符串集合。(1,2,3)或(start,stop,restart)。   3、系统服务启动脚本传参的判断多用case语句。多参考rpcbind/nfs/crond脚本。   小结:   1)所有的case语句都可以用if实现,但是case更规范清晰一些,   2)case一般适合于服务的启动脚本。   3)case的变量的值如果已知固定的start/stop/restart元素的时候比较适合一些。
已知nginx管理命令为:启动:/usr/local/nginx/sbin/nginx停止:/usr/local/nginx/sbin/nginx -s stop重新加载:/usr/locall/nginx/sbin/nginx -s reload请用case脚本模拟nginx服务启动关闭:/etc/init.d/nginx {start|stop|restart|reload} 并实现可通过chkconfig管理。[root@test88 script]# cat nginx.sh (未完工)#!/bin/sh[ -f /etc/init.d/functions ] && . /etc/init.d/functionsnginx="/usr/local/nginx/sbin/nginx"prog="nginx"RETVAL=0start() {        if [ ! -f /var/lock/subsys/$prog ];then                $nginx && RETVAL=$?        else                echo "nginx is running"                exit        fi        if [ $RETVAL -eq 0 ];then                touch /var/lock/subsys/$prog                action "starting nginx" /bin/true        else                 action "starting nginx" /bin/false        fi        return $RETVAL}stop() {        $nginx -s stop && RETVAL=$?        if [ $RETVAL -eq 0 ];then                rm -f  /var/lock/subsys/$prog                action "nginx is stopped"  /bin/true        else                action "nginx is stopped"  /bin/false        fi        return $RETVAL}reload() {if [ -f /var/lock/subsys/$prog ];then                $nginx reload && RETVAL=$?        else                echo "nginx is stopped"                exit        fi$nginx -s reload         return $RETVAL}case "$1" in        start)                start        ;;        stop)                stop        ;;        restart)                stop                start        ;;        reload)                reload        ;;        *)        echo "USAGE :$0 {start|stop|restart|reload}"esacexit $RETVALcp nginx.sh /etc/init.d/nginxchmod +x nginx.shnginx脚本中添加#!/bin/sh下#chkconfig: 2345 54 65chkconfig --add nginxchconfig nginx onchkconfig --list
nginx起停脚本参考
 

 

 case结构语句

while条件语法  while 条件     do       指令   done [root@shell ~]# cat  while-1.sh #!/bin/bash while true  表示条件永远为真     do         uptime         sleep 2     done ==>[root@shell ~]# while true;do uptime;sleep 2;done [root@shell ~]# cat sum100.sh #!/bin/sh sum=0 i=1 while [ $i -le 100 ] do   ((sum=sum+i))   ((i++)) done echo $sum ==>[root@shell ~]# echo $(( (1+100) * 100/2 )) while按行读文件的方式
方式1                              方式2 方式3                    
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
使用案例:读入文件,计算总流量 [root@shell ~]# cat sum-while.sh #!/bin/sh sum=0 while read line     do         value= `echo $line | awk '{print $10}'`         expr $value + 1 &>/dev/null         [ $? -ne 0 ] && continue         ((sum+=value))     done

 

 

for循环结构

for循环结构语法 for 变量名  in 取值列表  do    指令  donec语言型for循环结构 for ((expr1;expr2;expr3)) do    指令 doneseq -w 100102~~~~~#直接列出变量列表所有元素,打印5 4 3 2 1for num in 5 4 3 2 1   do   echo 10.0.0.$num  donefor ip in 192.168.0.1    192.168.0.2  {
1..5} `seq 10` do   echo $ip done 分库备份 [root@shell ~]# cat database_bak.sh #!/bin/sh MYUSER=root MYPASS=rootabcd MYCMD="mysql -u$MYUSER -p$MYPASS" MYDUMP="mysqldump -u$MYUSER -p$MYPASS" BACKPATH="/bak/database/$(date +%F)" [ ! -d $BACKPATH ] && mkdir -p $BACKPATH for dbname in `$MYCMD -e 'show databases;' | sed '1d' | grep -v "_schema"`     do         $MYDUMP -B -x --events $dbname | gzip > $BACKPATH/${dbname}.sql.gz if [ $? -eq 0 ];then     echo "$dbname">>$BACKPATH/${dbname}.log fi done 分表备份 root@shell ~]# cat database_tablebak.sh #!/bin/sh MYUSER=root MYPASS=rootabcd MYCMD="mysql -u$MYUSER -p$MYPASS" MYDUMP="mysqldump -u$MYUSER -p$MYPASS" BACKPATH="/bak/database/$(date +%F)" [ ! -d $BACKPATH ] && mkdir -p $BACKPATH for dbname in `$MYCMD -e 'show databases;' | sed '1d' | grep -v "_schema"`     do         for tname in `$MYCMD -e "show tables from $dbname;" | sed '1d'`     do         $MYDUMP  -x --events $dbname $tname | gzip > $BACKPATH/${dbname}_${tname}.sql.gz if [ $? -eq 0 ];then     echo "$dbname_$tname">>$BACKPATH/${dbname}.log fi done done

 

 

 

 

 

 

break n      跳出循环的层数,省略n表示跳出整个循环continue n    n表示退到n层继续循环,省略表示跳过本次循环exit n      退出shell程序,n为返回值return n      用于函数返回值

 

 

 

 

 

 

 

颜色的使用示例

#!/bin/shRED_COLOR='\E[1;31m'GREEN_COLOR='\E[1;32m'YELLOW_COLOR='\E[1;33m'BLUE_COLOR='\E[1;34m'RES='\E[0m'echo -e "$RED_COLOR boy $RES"echo -e "$YELLOW_COLOR girl $RES" man手册查看颜色man console_codes
前景色 echo -e "\033[30m 黑色字hello world \033[0m" echo -e "\033[31m 红色字hello world \033[0m" echo -e "\033[32m 绿色字hello world \033[0m" echo -e "\033[33m 黄色字hello world \033[0m" echo -e "\033[34m 蓝色字hello world \033[0m" echo -e "\033[35m 紫色字hello world \033[0m" echo -e "\033[36m 天蓝字hello world \033[0m"  ==等于# echo -e "\e[36m 天蓝字hello world \e[0m"     echo -e "\033[37m 白色字hello world \033[0m" 背景色 echo -e "\033[40;37m 黑底白字 welcome to shanghai\033[0m" echo -e "\033[41;37m 红底白字 welcome to shanghai\033[0m" echo -e "\033[42;37m 绿底白字 welcome to shanghai\033[0m" echo -e "\033[43;37m 黄底白字 welcome to shanghai\033[0m" echo -e "\033[44;37m 蓝底白字 welcome to shanghai\033[0m" echo -e "\033[45;37m 紫底白字 welcome to shanghai\033[0m" echo -e "\033[46;37m 天蓝白字 welcome to shanghai\033[0m" echo -e "\033[47;30m 白底黑字 welcome to shanghai\033[0m" 字背景颜色范围:40----49 40:黑 41:深红 42:绿 43:黄色 44:蓝色 45:紫色 46:深绿 47:白色 字颜色:30-----------39 30m:黑 31m:红 32m:绿 33m:黄 34m:蓝色 35m:紫色 36m:深绿 37m:白色 ==ANSI控制码的说明 \33[0m 关闭所有属性 \33[1m 设置高亮度 \33[4m 下划线 \33[5m 闪烁 \33[7m 反显 \33[8m 消隐 \33[30m -- \33[37m 设置前景色 \33[40m -- \33[47m 设置背景色 \33[nA 光标上移n行 \33[nB 光标下移n行 \33[nC 光标右移n行 \33[nD 光标左移n行 \33[y;xH设置光标位置 \33[2J 清屏 \33[K 清除从光标到行尾的内容 \33[s 保存光标位置 \33[u 恢复光标位置 \33[?25l 隐藏光标 \33[?25h 显示光标 使用示例:将颜色定义为函数 [root@shell home]# cat colour.sh add_colour() {
RED_COLOR='\E[1;31m' GREEN_COLOR='\E[1;32m' YELLOW_COLOR='\E[1;33m' BLUE_COLOR='\E[1;34m' RES='\E[0m' case "$1" in     red|RED)     echo -e "$RED_COLOR $2 $RES"         ;;     green|GREEN)     echo -e "$GREEN_COLOR $2 $RES"         ;;     yellow|YELLOW)     echo -e "$YELLOW_COLOR $2 $RES"          ;;     blue|BLUE)     echo -e "$BLUE_COLOR $2 $RES"          ;;          *)     echo "please use:{red|green|yellow|blue}"      exit esac } add_colour red "hello world" add_colour green "hello world" 批量创建用户 [root@shell ~]# cat  adduser.sh for n in `seq -w 10`   do         useradd gtms$n         pass=`echo $RANDOM | md5sum| cut -c 2-9`         echo $pass | passwd --stdin gtms$n         echo -e "gtms$n \t $pass" >>/tmp/user   done 批量创建密码 [root@shell ~]# useradd test1 [root@shell ~]# useradd test2 [root@shell ~]# useradd test3 [root@shell ~]# cat user.pass test1:123456 test2:123456 test3:123456 [root@shell ~]# chpasswd

 

 

随机数

RANDOM随机数echo $RANDOM    随机数0-32767echo "$RANDOM gtms" | md5sum 通过openssl产生随机数openssl rand -base64 8openssl rand -base64 10通过时间函数获得随机数date +%s%N通过uuid[root@shell ~]# cat /proc/sys/kernel/random/uuidf69ee9b7-fe0c-4173-b07c-5a881f7a739a[root@shell ~]# cat /proc/sys/kernel/random/uuidcbd8b0e9-24cc-44dd-9d96-dec53d7624a4使用mkpasswd 生成随机数yum install expect -y[root@test88 script]# mkpasswd -l 8yWG8u\6a[root@test88 script]# mkpasswd -l 9vq18MapV-对于长短不一的随机数 使用md5sum | cut -c 1-9 格式化

 

转载于:https://www.cnblogs.com/gtms/p/6752150.html

你可能感兴趣的文章