一:逻辑运算    

    true(1), false(0)

    与运算:

        1 与 1 = 1 

        1 与 0 = 0 

        0 与 1 = 0     

        0 与 0 = 0

    或运算:

        1 或1 = 1

        1 或0 = 1

        0 或1 = 1

        0 或0 = 0

    非运算: 

        ! 1 = 0

        ! 0 = 1

    短路与:&& 

        第一个为0,结果必定为0

        第一个为1,第二个必须要参与运算

    短路或:|| 

        第一个为1,结果必定为1

        第一个为0,第二个必须要参与运算

    异或:^

        异或的两个值,相同为假,不同为真

二:条件测试(test与[])

    条件测试是指判断某需求是否满足,需要由测试机制来实现。专用的测试表达式需要由测试命令辅助完成测试过程

    评估布尔声明,以便用在条件性执行中

        若真,则返回0

        若假,则返回1

    测试命令:(test与[]是等价的)

        test EXPRESSION

        [ EXPRESSION ]

        [[ EXPRESSION ]]

    注意:EXPRESSION前后必须有空白字符

    当我们要测试数值大小时,我们要用一下的表达式

        -gt是否大于

        -ge是否大于等于

        -eq是否等于

        -ne是否不等于

        -lt是否小于

        -le是否小于等于

    例子:

        test 11 -eq 011 && echo "相同"

        [ 11 -eq 011 ] && echo "相同"(两式等价)

        [ "$A"=="$B" ]&& echo "相同" ||echo "不同"(当前面的测试通过时,执行&&后的命令,测试不通过时,执行||之后的命令)

    当我们测试的内容是字符串时,我们要用以下的表达式:

        == 是否等于

        > ascii码是否大于ascii码

        < 是否小于

        ! =是否不等于

        =~ 左侧字符串是否能够被右侧的PATTERN所匹配

        注意: 此表达式一般用于[[ ]]中;扩展的正则表达式

        -z "STRING“字符串是否为空,空为真,不空为假

        -n "STRING“字符串是否不空,不空为真,空为假

        注意:用于字符串比较时的用到的操作数都应该使用引号

    例子:

        1.编写脚本/root/bin/argsnum.sh,接受一个文件路径作为参数;如果参数个数不等于1,则提示用户“应该给一个参数”,并立即退出;如果参数个数等于1,则显示所指向的文件中的空白行数

#!/bin/bash

[ $# -ne 1 ] &&  echo "应该给一个参数" || echo "$(cat $1 |egrep -c "^[[:space:]]*$")"

        2.编写脚本/root/bin/hostping.sh,接受一个主机的IPv4地址做为参数,如果未给定一个合法的IP地址,则提示 “给一个合法的IPV4地址” ,并立即退出。如果给出IPV4地址,则测试是否可连通。如果能ping通,则提示用户“该IP地址可访问”;如果不可ping通,则提示用户“该IP地址不可访问”

        echo $1 |egrep -q "\<(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]2[0-4][0-9]|25[0-5])\>" && ( ping -c1 -w1 $1 &>/dev/null  && echo "主机网络畅通" || echo “网络不可用” ) || echo "输入IP有误,格式:xxx.xxx.xxx.xxx,xxx小于255"

        3、编写脚本/root/bin/checkdisk.sh,检查磁盘分区空间和inode使用率,如果超过80%,就发广播警告空间将满

            #!/bin/bash            

            u1=$(df|grep /dev/sd |tr -s " " :|cut -d: -f5|cut -d% -f1 |sort -rn|head -1)

            u2=$(df -i|grep /dev/sd |tr -s " " :|cut -d: -f5|cut -d% -f1 |sort -rn|head -1)

            [ $u1 -gt 80 ] && wall "发警告"|| [ $u2 -gt 80 ] && wall "发警告" || echo "安全"

    二:文件测试:

        存在性测试

            -a FILE:同-e

            -e FILE: 文件存在性测试,存在为真,否则为假

        存在性及类别测试

            -b FILE:是否存在且为块设备文件

            -c FILE:是否存在且为字符设备文件

            -d FILE:是否存在且为目录文件

            -f FILE:是否存在且为普通文件

            -h FILE 或-L FILE:存在且为符号链接文件

            -p FILE:是否存在且为命名管道文件

            -S FILE:是否存在且为套接字文件

        文件权限测试:

            -r FILE:是否存在且可读

            -w FILE: 是否存在且可写

            -x FILE: 是否存在且可执行

        文件特殊权限测试:

            -u FILE:是否存在且拥有suid权限

            -g FILE:是否存在且拥有sgid权限

            -k FILE:是否存在且拥有sticky权限

        文件大小测试:

            -s FILE: 是否存在且非空

        文件是否打开:

            -t fd: fd表示文件描述符是否已经打开且与某终端相关

            -N FILE:文件自动上一次被读取之后是否被修改过

            -O FILE:当前有效用户是否为文件属主

            -G FILE:当前有效用户是否为文件属组

        双目测试:

            FILE1 -ef FILE2: FILE1与FILE2是否指向同一个设备上的相同inode

            FILE1 -nt FILE2: FILE1是否新于FILE2(mtime)

            FILE1 -ot FILE2: FILE1是否旧于FILE2

         例子

        [ -z “$HOSTNAME” -o $HOSTNAME "=="localhost.localdomain" ] && hostname www.magedu.com

       ([ -z “$HOSTNAME” -o $HOSTNAME "=="localhost.localdomain" ]等价于[ -z "$HOSTNAME" ]||[ "$HOSTNAME"=="localhost.localdomain" ])

        [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab

        ( [ -f /bin/cat -a -x /bin/cat ]等价于[ -f /bin/cat ]&&[ -x /bin/cat ])

        1、编写脚本/bin/per.sh,判断当前用户对指定的参数文件,是否不可读并且不可写

                 #!/bin/bash

                 if [ ! -r $1 ]&&[ ! -w $1 ]

                 then    

                        echo "$1是不可读不可写文件"

                 elif [ -r $1 ]&&[ -w $1 ]

                 then

                        echo "$1是可读可写文件"

                 elif [ -w $1 ]&&[ ! -r $1 ]

                 then

                        echo "$1是不可读可写文件"

                 else

                        echo "$1是可读不可写文件"

                 fi

        2、编写脚本/root/bin/excute.sh ,判断参数文件是否为sh后缀的普通文件,如果是,添加所有人可执行权限,否则提示用户非脚本文件

            #!/bin/bash

            if [[ $1 =~ .*\.sh ]]

            then 

                    chmod a+x $1

            else

                    echo "非脚本文件"

            fi

        3、编写脚本/root/bin/nologin.sh和login.sh,实现禁止和充许普通用户登录系统

            #!/bin/bash

            if id $1 &> /dev/null && [ $1 != root ]

            then

                    usermod -s /sbin/nologin $1

            elif [ $1 == root ]

            then

                    echo "这是root用户"

            fi

            #!/bin/bash

            if id $1 &> /dev/null && [ $1 != root ]

            then

                    usermod -s /bin/bash $1

            elif [ $1 == root ]

            then

                    echo "这是root用户"

            fi

        4.read命令:把输入值分配给一个或多个shell变量

            -p指定要显示的提示

            -s 静默输入,一般用于密码(等价于stty -echo)

            -n N 指定输入的字符长度N

            -d‘字符’ 输入结束符

            -t N TIMEOUT为N秒

            注意:read从标准输入中读取值,给每个单词分配一个变量所有剩余单词都被分配给最后一个变量

         5.转译:使随后的字符按原意解释

                转译有以下方式 '';\和""。不过这三种转译也是不一样的:首先""和''是范围转译,一次能转译多个字符,\一次只能转译一个字符。然后,''和\是完全转译,""在遇到!\`$这四种情况下是不转译的!           

        三:交互式登录和非交互式登录 

            1.bash的配置文件

                全局配置:

                    /etc/profile

                    /etc/profile.d/*.sh

                    /etc/bashrc

                个人配置:

                    ~/.bash_profile

                    ~/.bashrc

            2.交互式与非交互式登录方式及区别

                交互式登录:完整的登录方式,需要账户密码

                    (1)直接通过终端输入账号密码登录

                    (2)使用“su - UserName”切换的用户

                非交互式登录:

                    (1)suUserName

                    (2)图形界面下打开的终端

                    (3)执行脚本

                    (4)任何其它的bash实例

                交互式与非交互式登录方式的区别 

                    (1)交互式登录重新读取文件来获取别名,变量等不会继承上一个shell的变量。非交互式登录首先继承上一个shell的所有变量,再去读取文件,而且读取的文件比交互式登录读取的文件少。

                    (2)交互式文件读取文件的顺序:/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile--> ~/.bashrc--> /etc/bashrc

                    (3)非交互式文件读取文件的顺序:~/.bashrc--> /etc/bashrc--> /etc/profile.d/*.sh

                 实验:(1)在/etc/profile下添加变量A=A1,在/etc/profile.d/目录下创建wangkai.sh文件,并添加变量B=B2,在用户wangkai家目录下修改.bash_profile 文件,添加变量C=C3,接着修改文件.bash_rc添加变量D=D4,最后在/etc/bashrc下添加变量E=E5,交互式登录root用户,结果如图:

逻辑运算

解析:这是因为root用户登录时会访问/etc/profile,/etc/profile.d/*.sh, /etc/bashrc这三个文件,而访问不到用户wangkai的文件所以输出这三个变量。

                        (2)修改/etc/profile文件A=A6,不切换用户啊,再次输出变量。结果如图

逻辑运算

从图上发现内容不变是因为我们没有切换用户,没有读取文件,所以内容保持不变。

                    (3)非交互式登录用户root,在输出变量,发现内容不变,这是因为非交互式登录继承上一个shell的所有变量,所以虽然他不访问/etc/profile文件但也有该变量

                     (4)退出该子shell,修改/etc/profile.d/wangkai.sh下变量B=B7,非交互式登录登录root 输出变量结果如下图:

 逻辑运算

这是因为非交互式登录用户root,首先继承变量A=A6,B=B2,E=E5 ,之后再读取文件/etc/profile.d/wangkai.sh,覆盖变量B=B2,而变量E=E5在文件中不变,所以结果便如上图所示。

                (5)退出该shell,非交互式登录用户wangkai,再输出变量。再退出shell,交互式登录用户wangkai,输出变量,结果如图。

逻辑运算

            3.文件分类

                profile类:为交互式登录的shell提供配置

                    全局:/etc/profile, /etc/profile.d/*.sh

                    个人:~/.bash_profile

                    作用:

                        (1) 用于定义环境变量

                        (2) 运行命令或脚本

                bashrc类:为非交互式和交互式登录的shell提供配置

                    全局:/etc/bashrc

                    个人:~/.bashrc

                    作用:

                        (1) 定义命令别名和函数

                        (2) 定义本地变量

                修改profile和bashrc文件后生效的两种方法:

                    1重新启动shell进程

                    2 . 或source(在当前shell下有效,区别于bash ..和./执行后面的会开辟子shell来执行,不会对当前shell产生影响。)

            4.~/.bash_logout文件在退出登录shell时运行可以用于创建自动备份和清除临时文件

            5练习:

                5.1.让所有用户的PATH环境变量的值多出一个路径,例如:/usr/local/apache/bin

                    注意:要将该目录写在/etc/profile下,写完后用.或source运行即可,还要注意格式PATH=$PATH:/usr/local/apache/bin

                5.2用户root登录时,将命令指示符变成红色,并自动启用如下别名:

                        rm=‘rm –i’

                cdnet=‘cd /etc/sysconfig/network-scripts/’

                editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eth0’

                editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eno16777736 或 ifcfg-ens33 ’ (如果系统是CentOS7)

                        注意:要在当前用户家目录下的.bashrc下加进去,在用source命令执行。

                5.3、编写用户的环境初始化脚本reset.sh,包括别名,登录提示符,vim的设置,环境变量等

                           一旦执行reset.sh,会设置以下内容

                           创建一个别名为ipconfig功能是显示第一个网卡的IP

                           设置提示符为绿色

                           设置vim自动显示行号

                           设置登录后的欢迎界面(内容自定义)

                    

                             #!/bin/bash

                              2 if id $1 &>/dev/null && [ $1 != root ]

                              3 then

                              4         cat <<EOF >>/home/$1/.bashrc 

                              5         alias ipconfig='ifconfig ens33|grep "inet\>"|tr -s " " :|cut -d: -f3' 

                              6 EOF

                              7         echo 'PS1="\[\e[32m\][\[email protected]\h \W]\\$\[\e[0m\] " '>>/home/$1/.bashrc

                              8         echo 'set number'>>/etc/vimrc

                              9         echo '你好,世界'>>/etc/motd

                             10         source /home/$1/.bashrc

                             11 elif id $1 &>/dev/null && [ $1 == root ]

                             12 then

                             13         cat <<EOF >>/root/.bashrc 

                             14         alias ipconfig='ifconfig ens33|grep "inet\>"|tr -s " " :|cut -d: -f3' 

                             15 EOF

                             16         echo 'PS1="\[\e[32m\][\[email protected]\h \W]\\$\[\e[0m\] " '>>/root/.bashrc

                             17         echo 'set number'>>/etc/vimrc

                             18         echo '你好,世界'>> /etc/motd

                             19         source /root/.bashrc

                             20 else

                             21         echo "没有该用户"

                             22 fi

                5.4、编写一个创建用户的脚本,要求以下功能

                a.提示用户输入希望创建的用户名(当用户超时8秒不输入,提示超时并退出)

                b.检测用户名是否已存在,若存在则提示用户名已存在,并退出。

                c.用户创建完成后提示用户是否要继续设置密码,若用户输入yes、YES、y、Y时则继续下一步,如输入其他,或超时8秒均退出。

                d.接上一步,为用户设置密码,首先提示用户输入要设置的密码,密码的输入过程不可见。

                e.对用户上一步所输入的密码进行长度检测,若少于5位(包含5位),则提示用户密码太短,并退出。

                f.对用户在第d步所输入的密码进行复杂度检测,若所输入的内容与/usr/share/dict/words 字典中的某一行条目完全一致,则提示密码是一个常见单词,并退出。

                g.再一次让用户输入密码,若第二次输入的密码与在第d步输入的不一致,则提示用户两次密码不一致并退出。

                h.d至g步骤全部通过后,为用户设置密码后,并提示密码已成功设置。最后正确退出。

                以上的所有退出情况应给出不同的返回值。

                             #!/bin/bash

                             13 read -p "请输入用户名 " -t 8 userName

                             14 if id $userName &>/dev/null ;then 

                             15         echo "该用户已存在";exit 1

                             16 else 

                             17         useradd $userName

                             18         read -p "是否继续设置密码? " -t 8 mima 

                             19         if [ $mima == yes ]||[ $mima == YES ]||[ $mima == y ]||[ $mima == Y ];then

                             20                 read  -t 8  -sp "输入密码 " mima1

                             21                 lens=$(echo $mima1 |grep -o .|wc -l)

                             22                 if [ $lens -lt 6 ] ;then 

                             23                         echo "太短";exit 2

                             24                 else        

                             25                         pd=$(cat /usr/share/dict/words | egrep -o "^$mima1$")

                             26                         if [ "$mima1" == "$pd" ];then

                             27                                 echo "常见";exit 3

                             28                         else            

                             29                                 read  -sp "再次输入密码 " -t 8 mima2

                             30                                 if [ $mima1 != $mima2 ] ;then

                             31                                         echo "密码不一致 ";exit 4

                             32                                 else    

                             33                                         echo $mima2 |passwd --stdin $userName &>/dev/null && echo "密码修改成功";exit 0        

                                                  

                             34                                 fi

                             35                         fi

                             36                                 

                             37                 fi

                             38         fi      

                             39 fi       

                             40