redhat linux之bash 编程

bash编程:
    bash进程:解释器
        type

    shell脚本:
    第一行,顶格:
        shebang
        #!/bin/bash
        #!/usr/bin/python

        其它的以#开头的行均为注释,会被解释器忽略;

    练习:
        创建一个组newgroup,id号8008;
        创建一个用户,名字为mageedu, id号为3306,附加组为newgroup
        创建目录/tmp/hellobash
        复制/etc/rc.d/init.d/functions至/tmp/hellobash目录中

    过程式编程语言:
        顺序执行
        选择执行:测试条件,可能会多个测试条件,某条件满足时,则执行对应的分支
        循环执行:将同一段代码反复执行多次;因此,循环必须有退出条件;否则,则陷入死循环;

    bash 
        -n: 语法测试
        -x: 模拟单步执行

    变量类别:
        本地变量
        环境变量
            export:导出
        局部变量
        位置变量
            $1, ..., $n, ${10}
                练习:写一个脚本,能接受一个参数作为用户名,此脚本可创建此用户,并且其密码同用户名;
                shift [n]
        特殊变量:
            $?
            $#: 传递给脚本参数的个数
            $*
            $@:引用传递给脚本的所有参数

    bash的循环语句:
        for:遍历有限的元素列表,
        while:
        until:

        for语句的格式:
            for VAR_NAME in LIST
            do
                循环体
            done

            LIST:列表,中间包括一个或多个元素

            退出条件:遍历结束

            练习:创建10个用户,user301, user310
                列表:user301, user310
                列表:301, 310

                生成数值列表:
                    {start..end}
                        例如:{1..100}
                    seq
                        命令引用 

                for userNo in {301..310}
                for userNo in $(seq 301 310); do
                    useradd user${userNo}
                done

            练习:创建目录/tmp/dir-当前日期时间;例如/tmp/dir-20140707-155503
                在此目录中创建10个空文件,分别为file1-file10;

            练习:写一个脚本
            1、创建用户tuser1-tuser9; 
            2、创建目录/tmp/dir-当前日期时间;
            3、在/tmp/dir-当前日期时间 目录中创建9个空文件file101-file109
            4、将file101的属主改为tuser1,依次类推,一直将file109的属主改为tuser9;

            练习:写一个脚本
            1、脚本可以接受一个以上的文件路径作为参数;
            2、显示每个文件所拥的行数;

            3、显示本次共对多少个文件执行了行数统计;
            !/bin/bash
            #
            for file in $*; do
                lines=`wc -l $file | cut -d' ' -f1`
                echo "$file has $lines lines."
            done

            echo "$# files."

            练习:写一个脚本
            1、显示/etc/passwd文件中位于文件的第偶数行的用户名;并显示共有多少个这样的用户;
                #!/bin/bash
                #
                totalUsers=`wc -l /etc/passwd | cut -d' ' -f1`

                for i in `seq 2 2 $totalUsers`; do
                    userName=`head -n $i /etc/passwd | tail -1 | cut -d: -f1`
                    echo $userName >> /tmp/passwd.tmp
                    echo $userName
                done

                users=`wc -l /tmp/passwd.tmp | cut -d' ' -f1`
                echo "Total users: $users."                

        生成列表的方式:
            1、手动给个列表:
                for i in 1 2 3 4 5;
            2、数值列表:
                {start..end}
                `seq [start [increment]] end`
            3、$*, $@
            4、命令生成列表

    bash如何实现算术运算:
        变量:弱类型

        如何定义整型变量:
            let VAR_NAME=INTEGER_VALUE
                例如:let a=3

            declare -i VAR_NAME=INTEGER_VALUE
                例如:declare -i a=3

        注意:即使没有定义为整型变量,字符型的数字依然可以参与算术运算;bash会执行变量类型的隐式类型转换;

        实现算术运算的方式:
            let VAR_NAME=ARITHMATIC_EXPRESSION
            VAR_NAME=$[ARITHMATIC_EXRESSION]
            VAR_NAME=$((EXPRESSION))
            VAR_NAME=$(expr $num1 + $num2)

        算术运算符:
            +
            -
            *
            /
            %:取模,取余数
                5%2=1, 
            **: 2**2

        练习:计算100以内所有正整数之和
            #!/bin/bash
            #
            declare -i sum=0

            for i in {1..100}; do
              sum=$[$sum+$i]
            done

            echo $sum

        练习:分别计算100以内所有偶数之和和奇数之和;
            #!/bin/bash
            #
            declare -i evensum=0
            declare -i oddsum=0

            for i in `seq 1 2 100`; do
              oddsum=$[$oddsum+$i]
            done

            for j in `seq 2 2 100`; do
              evensum=$[$evensum+$j]
            done

            echo "evensum: $evensum, oddsum: $oddsum."


        练习:计算当前系统上所有用户的ID之和;

            declare -i idsum=0

            for i in `cut -d: -f3 /etc/passwd`; do
                let idsum+=$i
            done

            echo $idsum

        练习:写一个脚本
            1、脚本可以接受一个以上的文件路径作为参数;
            2、显示每个文件所拥有的行数;
            3、显示本次共对多少个文件执行了行数统计;
            4、显示所有文件的总行数;

                #!/bin/bash
                #
                declare -i totalLines=0
                declare -i noFiles=0

                for file in $*; do
                    curFileLines=`wc -l $file | cut -d' ' -f1`
                    echo "$file has $curFileLines."
                    let noFiles++
                    let totalLines+=$curFileLines
                done

                echo "Total Files: $noFiles."
                echo "Total Lines: $totalLines."


        练习:新建10个用户tuser401-tuser410,并求他们的ID之和;
            #!/bin/bash
            #
            declare -i idsum=0

            for i in {401..410}; do
                useradd tuser$i
                userID=`id -u tuser$i`
                let idsum+=$userID
            done

            echo "ID sum: $idsum."            

        练习:写一个脚本
            1、创建用户tuser501-tuser510; 
            2、创建目录/tmp/dir-当前日期时间;
            3、在/tmp/dir-当前日期时间 目录中创建9个空文件file101-file110
            4、将file101的属主改为tuser501,依次类推,一直将file110的属主改为tuser510;    


        练习:写一个脚本
            分别统计/etc/rc.d/rc.sysinit、/etc/rc.d/init.d/functions和/etc/inittab文件中以#开头的行的行数和空白行数;
            
                #!/bin/bash

                for file in /etc/rc.d/rc.sysinit /etc/rc.d/init.d/functions /etc/inittab; do
                    echo "The lines contain #  in $file is `grep -E "^#" $file | wc -l`." 
                    echo "The space lines in $file is `grep -E "^[[:space:]]*$" $file | wc -l`." 
                done


        练习:写一个脚本
            显示当前系统上所有默认shell为bash的用户的用户名、UID及其所有此类用户的UID之和;
                #!/bin/bash
                #
                grep "/bin/bash$" /etc/passwd | cut -d: -f1,3

                declare -i sum=0
                for userID in `grep "/bin/bash$" /etc/passwd | cut -d: -f3`; do
                    let sum+=$userID
                done

                echo "$sum"


    bash弱类型:
        变量=值
            任何无需事先声明,可直接使用
            值默认都是字符型
            a=abc, b=3
            a=3
            赋值:
                a=4
            增强型赋值:
                +=, -=, *=, /=, %=
                a=$[$a+1] 相当于 let a+=1

                自加:var++, var--, ++var, --var
            export PATH=$PATH:/usr/local/apache/bin

            unset: 撤消 

        算术运算:bash会对数字执行隐式的类型转换
            let VAR_NAME=Integer_Value
            declare -i Var_Name=Integer_Value

            操作符:
                +, -, *, /, %, **

                双目运算符:需要至少两个操作数

        bash的算术运算的方式:
            let Var_Name=EXPRESSION
            $[EXPRESSION]
            $((EXPRESSION))
            命令:expr ARG1 OP ARG2

        for循环:
            新建10个用户:tuser601-tuser610
                useradd $userName

            for Var in LIST; do

            for userName in tuser601 tuser602 tuser603; do
                useradd $userName
            done

            for i in {601..610}; do
                useradd tuser$i
            done

            遍历LIST元素,遍历结束,循环退出;

        bash中的字串连接:
            变量引用后方跟直接字串时,变量名要加{}

            求100以内所有正整数的和:
                declare -i sum=0

                sum+=1, 0+1
                sum+=2, 0+1+2
                sum+=3
                sum+=4
                ...
                sum+=100

            declare -i sum=0
            for i in {1..100}; do
                let sum+=$i
            done

            echo $sum

    练习:写一个脚本,显示当前系统上有附加组的用户的用户名;并统计共有多少个此类用户;
    for userName in `cut -d: -f1 /etc/passwd`; do
        id $userName | 

        # egrep '[^:]$' /etc/group | cut -d: -f4 | sort -u | egrep -o '[[:alnum:]]*' | sort -u

    写一个脚本,创建十个用户tuser401, tuser410

实现某种操作:总是 测试 前提是否满足

    /tmp/test
        10

    逻辑运算:
        布尔运算:真,假

        与、或、非、异或

        与运算:
            真,假:
                真 && 真 = 真
                真 && 假 = 假
                假 && 真 = 假
                假 && 假 = 假

        或运算:
            真,假
                真 || 真 = 真
                真 || 假 = 真
                假 || 真 = 真
                假 || 假 = 假

        非运算:
            真,假

        异或运算:

    命令都有其状态返回值:
        成功:0,真
        失败:1-255, 假

    bash条件测试:
        命令执行成功与否即为条件测试
            test EXPR
            [ EXPR ]
            [[ EXPR ]]

        比较运算:
            >, <, >=, <=, ==, !=

        测试类型:根据比较时的操作数的类型
            整型测试:整数比较
            字符测试:字符串比较
            文件测试:判断文件的存在性及属性等

            注意:比较运算通常只在同一种类型间进行

            整型测试:
                -gt: 例如 [ $num1 -gt $num2 ]
                -lt: 
                -ge: 
                -le:
                -eq:
                -ne:

            字符串测试:
                双目
                    >: [[ "$str1" > "$str2" ]]
                    <:
                    >=
                    <=
                    ==
                    !=

                单目:
                      -n String: 是否不空,不空则为真,空则为假
                      -z String: 是否为空,空则为真,不空则假

    过程式编程:
        顺序
        选择
        循环:for

    选择:if和case

    if: 三种使用格式
        单分支的if语句:
            if 测试条件; then
                 选择分支
            fi
                表示条件测试状态返回值为值,则执行选择分支;

                if ! id $username &> /dev/null; then
                    useradd $username
                fi

            练习:写一个脚本,接受一个参数,这个参数是用户名;如果此用户存在,则显示其ID号;

        双分支的if语句:
            if 测试条件; then
                选择分支1
            else
                选择分支2
            fi

            两个分支仅执行其中之一。

            练习:通过命令行传递两个整数参数给脚本,脚本可以返回其大者。

            练习:通过命令行传递任意个整数给脚本,脚本可以返回其大者。

            练习:通过命令行给定一个文件路径,而后判断:
                如果此文件中存在空白行,则显示其空白行的总数;
                否则,则显示无空白行;

                if grep "^[[:space]]*$" $1 &> /dev/null; then
                    echo "$1 has $(grep "^[[:space]]*$" $1 | wc -l) blank lines."
                else
                    echo "No blank lines"
                fi

                注意:如果把命令执行成功与否当作条件,则if语句后必须只跟命令本身,而不能引用。

                if [ $(grep "^[[:space:]]*$" $1 | wc -l) -lt 1 ]

        多分支的if语句:
            if 条件1; then
                分支1
            elif 条件2; then
                分支2
            elif 条件3; then
                分支3
            ...
            else
                分支n
            fi

            练习:传递一个参数给脚本:    
                如果参数为quit,则显示说你要退出;
                如果参数为yes,则显示说你要继续
                其它任意参数,则说无法识别;

            练习:传递一个用户名给脚本:
                如果此用户的id号为0,则显示说这是管理员
                如果此用户的id号大于等于500,则显示说这是普通用户
                否则,则说这是系统用户;

                #!/bin/bash
                #
                if [ $# -lt 1 ]; then
                    echo "Usage: `basename $0` username"
                    exit 1
                fi

                if ! id -u $1 &> /dev/null; then
                    echo "Usage: `basename $0` username"
                    echo "No this user $1."
                    exit 2
                fi

                if [ $(id -u $1) -eq 0 ]; then
                    echo "Admin"
                elif [ $(id -u $1) -ge 500 ]; then
                    echo "Common user."
                else
                    echo "System user."
                fi

        if 测试条件; then
            测试条件:在bash中是命令 (test EXPR, [ EXPR ] ) 或由 [[ EXPR ]]
            if 命令;
                在bash运行至if时,其后的命令会被执行,其状态结果则作为判断标准:
                    0:表示真
                    1-255:表示假

                如果条件包含比较之意,则必须使用


自定义shell进程的状态返回值:
    exit [n]


回顾:
    条件测试:
        整型测试:数值间的大小比较
            -gt, -lt, -eq, -ne, -ge, -le
        字符串测试:字符串大小比较
            >, <, ==, !=, =~, -n, -z
        文件测试

    例如:如果当前主机的主机名为localhost,则将其修改为www.magedu.com

        比较时,
        if [ `hostname` == 'localhost' ]; then
            hostname www.magedu.com
        fi

    例如:如果当前主机的主机名为空,则将其修改为用户通过命令行参数传递过来的用户名
        hostName=`hostname`

        if [ -z "$hostName" ]; then
            hostname $1
        fi

    组合条件测试:在多个条件间实现逻辑运算
        与:[ condition1 -a condition2 ]
            condition1 && condition2
        或:[ condition1 -o condition2 ]
            condition1 || condition2
        非:[ -not condition ]
            ! condition

        例如:如果当前主机的主机名为空,或者为"localhost",则将其修改为www.magedu.com
            #!/bin/bash
            #
            hostName=`hostname`

            if [ -z "$hostName" -o "$hostName" == 'localhost' ]; then
                hostname www.magedu.com
            fi

        如果某用户存在,则显示id号:
            if id $userName &> /dev/null; then
                id -u $userName
            fi

        例如:如果某用户存在,且answer变量的值为“yes",则显示用户的ID号;否则,说用户选择了退出;
            id $userName
            retVal=$?

            if [ $retval -eq 0 -a "$answer" == 'yes' ]; then

            上述方式改为:

            if id $userName &> /dev/null && [ "$answer" =='yes' ]; then

        例如:如果answer不为"quit",也不为"q",则说用户选择了继续;

        例如:如果answer不为quit或q,则说明用户选择了继续;

        德 摩根定律:
            
    练习:给定一个用户,如果其shell为/bin/bash且其ID号大于等于500,则说这是一个可登录普通用户;否则,则显示其为非登录用户或管理员。

        #!/bin/bash
        #
        if ! id $1 &> /dev/null; then
            echo "No this user."
            exit 3
        fi

        userShell=$(grep "^$1\>" /etc/passwd | cut -d: -f7)
        userID=$(id -u $1)

        if [ "$userShell" == '/bin/bash' -a $userID -ge 500 ]; then
            echo "Login user."
        else
            echo "not login user."
        fi        

    练习:写一个脚本
        如果某用户不存在,就添加之;
            #!/bin/bash
            #
            if ! id $1 &> /dev/null; then
                useradd $1
            fi        

    练习:写一脚本
        1、添加10个用户:tuser501-tuser510
            如果用户不存在,才添加;如果存在,则显示已经有此用户
        2、显示一共添加了多少个用户;
            #!/bin/bash
            #
            declare -i count=0

            for i in {501..510}; do
                if id tuser$i &> /dev/null; then
                    echo "tuser$i exists."
                else
                    useradd tuser$i
                    let count++
                fi
            done

            echo "Total add $count users."


    练习:写一脚本
        1、添加10个用户:tuser601-tuser610
            如果用户不存在,才添加,并以绿色显示添加成功;如果存在,则以红色显示已经有此用户;
        2、显示一共添加了多少个用户;
            #!/bin/bash
            #
            declare -i count=0

            for i in {501..510}; do
                if id tuser$i &> /dev/null; then
                    echo -e "\033[31mtuser$i\033[0m exists."
                else
                    useradd tuser$i
                    echo -e "add user \033[32mtuser$i\033[0m successfully."
                    let count++
                fi
            done

            echo "Total add $count users."        

    练习:写一个脚本
        传递用户名给脚本
        1、判断此用户的shell是否为/bin/bash,如果是,则显示此用户为basher
        2、否则,则显示此用户为非basher

            #!/bin/bash
            #
            userShell=`grep "^$1\>" /etc/passwd | cut -d: -f7`

            if [ "$userShell" == '/bin/bash' ]; then
                echo "basher"
            else
                echo "not basher"
            fi        


在剩下的三月里,你愿意与学习结为伴侣,无论贫穷还是富贵,无论电脑还是手机,无论多困或者多累,无论想吃还是想睡,都要把学习放在第一位,以不落后为目标,同甘共苦同舟共济永不言弃,爱惜她尊重她理解她保护她,你愿意这样做么?
Yes, I do.


bash条件测试之文件测试:

       -a file
              True if file exists.
       -b file
              True if file exists and is a block special file.
       -c file
              True if file exists and is a character special file.
       -d file
              True if file exists and is a directory.
       -e file
              True if file exists.
       -f file
              True if file exists and is a regular file.
       -g file
              True if file exists and is set-group-id.
       -h file
              True if file exists and is a symbolic link.
       -k file
              True if file exists and its ''sticky'' bit is set.
       -p file
              True if file exists and is a named pipe (FIFO).
       -r file
              True if file exists and is readable.
       -s file
              True if file exists and has a size greater than zero.
       -t fd  True if file descriptor fd is open and refers to a terminal.
       -u file
              True if file exists and its set-user-id bit is set.
       -w file
              True if file exists and is writable.
       -x file
              True if file exists and is executable.
       -O file
              True if file exists and is owned by the effective user id.
       -G file
              True if file exists and is owned by the effective group id.

       -L file
              True if file exists and is a symbolic link.
       -S file
              True if file exists and is a socket.
       -N file
              True if file exists and has been modified since it was last read.
       file1 -nt file2
              True if file1 is newer (according to modification date) than file2, or if file1 exists and file2 does not.
       file1 -ot file2
              True if file1 is older than file2, or if file2 exists and file1 does not.
       file1 -ef file2
              True if file1 and file2 refer to the same device and inode numbers.
       -o optname
              True  if  shell  option  optname  is  enabled.  See the list of options under the description of the -o option to the set builtin
              below.


          -a FILE
          -e FILE: 存在则为真;否则则为假;

          -f FILE: 存在并且为普通文件,则为真;否则为假;
          -d FILE: 存在并且为目录文件,则为真;否则为假;
          -L/-h FILE: 存在并且为符号链接文件,则为真;否则为假;
          -b: 块设备
          -c: 字符设备
          -S: 套接字文件
          -p: 命名管道

          -s FILE: 存在并且为非空文件则为值,否则为假;

          -r FILE
          -w FILE
          -x FILE

          file1 -nt file2: file1的mtime新于file2则为真,否则为假;
          file1 -ot file2:file1的mtime旧于file2则为真,否则为假;

    例如:如果wget命令对应的可执行文件存在且可执行,则使用它下载http://172.16.0.1/centos6.5.repo至当前目录中;

        #!/bin/bash
        #
        downURL='http://172.16.0.1/centos6.5.repo'
        downloader=`which wget`

        if [ -x $downloader ]; then
            $downloader $downURL
        fi

    练习:给定一个文件路径
        1、判断此文件是否存在;不存在,则说明文件不存,并直接结束脚本;
        2、如果文件是否普通文件,则显示为“regular file”;
           如果文件是目录,则显示为“directory”;
           如果文件是链接文件,则显示为“Symbolic file";
           否则,则显示为“unknown type.”

            #!/bin/bash
            #
            if [ ! -e $1 ]; then
                echo "file not exist."
                exit 8
            fi

            if [ -L $1 ]; then
                echo "Symbolic file"
            elif [ -d $1 ]; then
                echo "Directory"
            elif [ -f $1 ]; then
                echo "regular file."
            else
                echo "unknown."
            fi

    练习:写一个脚本,完成如下任务:
        1、分别复制/var/log下的文件至/tmp/logs/目录中;
        2、复制目录时,才使用cp -r
        3、复制文件时,使用cp
        4、复制链接文件,使用cp -d
        5、余下的类型,使用cp -a

    写一个脚本,完成如下任务,其使用形式如下所示:
        script.sh {start|stop|restart|status}
    其中:
        如果参数为空,则显示帮助信息,并退出脚本;
        如果参数为start,则创建空文件/var/lock/subsys/script,并显示“starting script successfully.”
        如果参数为stop,则删除文件/var/lock/subsys/script,并显示“Stop script successfully.”
        如果参数为restart,则删除文件/var/locksubsys/script并重新创建,而后显示“Restarting script successfully.”
        如果参数为status,那么:
            如果文件/var/lock/subsys/script存在,则显示“Script is running...”,否则,则显示“Script is stopped.”

        说明:script.sh是脚本文件名,在创建时,其名称可以自己随意定义,但如果其名称发生变量,上/var/lock/sussys/下的文件名也要随之而变;


 

猜你喜欢

转载自blog.csdn.net/qq_40210617/article/details/86572179
今日推荐