zoukankan      html  css  js  c++  java
  • shell编程

    关于基本语法,可以快速通读一下: 菜鸟学堂Shell 教程

    Shell适用:帮助管理员减少重复操作或进行运维操作,不适合进行复杂的运算的场合。

    1.shell 基础

    1.1 shell 基本概念

    shell本身就是一个在UNIX/Linux系统上运行的应用程序,负责用户与系统间的交互。shell的一个主要功能就是解释执行用户输入的各种命令。shell只有极少数的内置命令,大部分的命令都是通过存放在/bin目录下与命令名同名的可执行程序实现的。

    Bourne shell 是标准的UNIX shell,是大多数UNIX系统的缺省shell。Bourne Again shell 即bash,通常是Linux系统的缺省shell。bash 是基于Bourne shell 的,不但与Bourne shell兼容,而且融入了许多C shell 与 Korn shell 的功能。

    要查看系统当前使用的是何种shell,只需在shell中输入:

    [shawnee@localhost ~]$ echo $SHELL
    /bin/bash

    1.2 shell编程语言

    shell还是一种高级程序设计语言,有自己的语法,如变量、关键字、顺序、选择和循环语句等。作为一种编程语言,shell是一种解释性的程序设计语言,即命令语言,通过组合一系列的命令来编写程序,写完的程序无需编译,可直接投入运行。

    用shell编程语言编写的程序文件常常称为shell脚本。当运行shell脚本时,脚本文件中的命令被依次传送给shell执行,一次执行一条命令,直到所有的命令执行完毕或出现错误为止。

    所以,可以将经常用到的具有一定执行顺序的操作命令编写成shell脚本,这样在运行时只需执行shell脚本即可,从而大大提高了工作效率。

    1.3 shell脚本的生成与执行

    #!/bin/bash 
    #This is my first shell script.
    echo -n "The current date and time is:"
    date
    who
    echo -n "The current users is:"
    who|wc -l

    要执行shell脚本,有以下几种方法:

    (1)输入定向到shell脚本:#bash<sysinfo

    (2)以脚本名作为shell命令的参数:#bash sysinfo

    (3)点命令是shell的一个内部命令,表示当前正在使用的shell:# . sysinfo

    (4)增加可执行权限,然后在提示符下运行shell脚本:

      #chmod +x sysinfo

      #./sysinfo

    [shawnee@localhost test]$ chmod +x sys_info
    -rwxrwxr-x. 1 shawnee shawnee 135 2月 12 18:01 sys_info
    [shawnee@localhost test]$ ./sys_info
    The current date and time is:2018年 02月 12日 星期一 18:02:20 CST
    shawnee :0 2018-01-30 00:39 (:0)
    shawnee pts/0 2018-01-30 00:40 (:0)
    The current users is:2
    

      

    2.shell 语法

    2.1shell的变量

    变量名=变量值(等号两边不能有空格,若变量的赋值中含有空格,则必须使用双引号将变量值括起来)

    #name="Zheng Hao"

    要引用变量的值,只需在变量名前增加美元符号"$",如:

    #echo $name

    #env (列出已定义的环境变量)

    2.2位置变量

    在执行shell脚本时允许在命令行给出传递shell脚本的参数,这些参数被存储在变量名为0,1,2,···的特殊变量里,称为位置变量。因为这些变量名是与命令行上参数位置相对应的。

    例:新建一个脚本文件showposvar,脚本内容如下:

    #This script shows how to use the position variable.
    echo "The number of command line parameters is $#"
    echo "The command line parameters is: $ *"
    echo "The script name is $0"
    echo "The first parameter is $1"
    echo "The second parameter is $2"
    echo "The third parameter is $3"

    执行如下:

    [shawnee@localhost test]$ . showposvar one two three
    The number of command line parameters is 3
    The command line parameters is: $ *
    The script name is bash
    The first parameter is one
    The second parameter is two
    The third parameter is three
    

    2.3 shell的流程控制(转载自:[Shell]条件判断与流程控制:if, case, for, while, until

    【条件判断】

    1. 按文件类型进行判断

      -b 文件    判断该文件是否存在,并且为块设备文件(是块设备文件为真)

      -c 文件    判断该文件是否存在,并且为字符设备文件(是字符设备文件为真)

      -d 文件    判断该文件是否存在,并且为目录文件(是目录为真)

      -e 文件    判断该文件是否存在(存在为真)

      -f 文件    判断该文件是否存在,并且为普通文件(是普通文件为真)

      -L 文件    判断该文件是否存在,并且为符号链接文件(是符号链接文件为真)

      -p 文件    判断该文件是否存在,并且为管道文件(是管道文件为真)

      -s 文件    判断该文件是否存在,并且为非空(非空为真)

      -S 文件    判断该文件是否存在,并且为套接字文件(是套接字文件为真)

    两种判断格式:

        ① test -e /root/install.log

        ② [ -e /root/install.log ] 方括号的左右两边必须有空格

        [ -f /root/install.log ] && echo 'yes' || echo 'no'

    2. 按照文件权限进行判断(不区分所有者, 所属组)

      -r 文件    判断该文件是否存在,并且拥有读权限(有读权限为真)

      -w 文件    判断该文件是否存在,并且拥有写权限(有写权限为真)

      -x 文件    判断该文件是否存在,并且拥有执行权限(有执行权限为真)

      -u 文件    判断该文件是否存在,并且拥有SUID权限(有SUID权限为真)

      -g 文件    判断该文件是否存在,并且拥有SGID权限(有SGID权限为真)

      -k 文件    判断该文件是否存在,并且拥有SBit权限(有SBit权限为真)

    3. 两个文件之间进行比较

      文件1 -nt 文件2    判断文件1的修改时间是否比文件2的新(如果新则为真)

      文件1 -ot 文件2    判断文件1的修改 时间是否比文件2的旧

      文件1 -ef 文件2    判断文件1是否和文件2的Inode号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法。

    4. 两个整数之间比较

      整数1 -eq 整数2    判断整数1是否和整数2相等(相等为真)

      整数1 -ne 整数2    判断整数1是否和整数2不相等(不相等为真)

      整数1 -gt 整数2    判断整数1是否大于整数2(大于为真)

      整数1 -lt 整数2    判断整数1是否大于整数2(小于为真)

      整数1 -ge 整数2    判断整数1是否大于等于整数2(大于等于为真)

      整数1 -le 整数2    判断整数1是否小于等于整数2(小于等于为真)

      [ 1 eq 2 ] && echo 'yes' || echo 'no'

    5. 字符串的判断

      -z 字符串    判断字符串是否为空(为空返回真)

      -n 字符串    判断字符串是否为非空(非空返回真)

      字符串1 == 字符串2    判断字符串1和字符串2是否相等(相等返回真)

      字符串1 != 字符串2    判断字符串1是否和字符串2不相等(不相等返回真) 

      name=chen

      [ -z "$name" ] && echo 'yes' || echo 'no'

    6. 多重条件判断

      判断1 -a 判断2    逻辑与,判断1和判断2都成立,最终的结果才为真

      判断1 -o 判断2    逻辑或,判断1和判断2有一个成立,最终的结果就为真

      ! 判断    逻辑非,使原始的判断式取反

      a=24

      [ -n "$a" -a "$a" -gt 23 ] && echo 'yes' || echo 'no'

    【流程控制 - if 语句】

    1. 单分支if条件语句

    if [ 条件判断式 ]; then
        程序
    fi
    if test -z "$ac_version"; then​
        程序
    fi

    或者

    if [ 条件判断式 ]
        then
            程序
    fi

    注意:

        ① if开头,fi结尾

        ② [ 条件判断式 ]就是使用test命令判断,所以中括号和条件判断式之间必须有空格

        ③ then后面跟符合条件之后执行的程序,可以放在[]之后,用" ; "分割,也可以换行写入,就不需要" ; "了。

    复制代码
    #!/bin/bash
    # 统计根分区使用率
    
    rate=$(df -h | grep "/dev/sda3" | awk '{print $5}' | cut -d "%" -f1) # 把根分区使用率作为变量值赋予变量rate
    
    if [ $rate -ge 80 ]; then
        echo "Warning! /dev/sda3 is full !"
    fi
    复制代码

    2. 双分支if条件语句

    if [ 条件判断式 ]
        then
            条件成立时,执行的程序
        else
            条件不成立时,执行的另一个程序
    fi
    复制代码
    #!/bin/bash
    # 备份mysql数据库
    ntpdate asia.pool.ntp.org &> /dev/null    # 同步系统时间(需联网)
    date=$(date +%y%m%d)    # 把当前系统时间按照"年月日"格式赋予变量date
    size=$(du -sh /var/lib/mysql)    # 统计mysql数据库的大小,并把大小赋予size变量
    
    if [ -d /tmp/dbbak ]
        then
            echo "Date: $date!" > /tmp/dbbak/dbinfo.txt
    echo "Data size: $size" >> /tmp/dbbak/dbinfo.txt
    cd /tmp/dbbak
    tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt
    &> /dev/null # 把所有输出丢弃
    rm -rf /tmp/dbbak/dbinfo.txt  # 卸磨杀驴 else mkdir /tmp/dbbak ... fi
    复制代码
    复制代码
    #!/bin/bash
    # 判断Apache是否启动 ( 先安装nmap:rpm -ivh http://nmap.org/dist/nmap-4.68-1.i386.rpm )
    
    port=$(nmap -sT 192.168.1.156 | grep tcp | grep http | awk '{print $2}')    # 使用nmap命令扫描服务器,并截取apache服务的状态,赋予变量port
    
    if [ "$port" == "open" ] then echo "$(date) httpd is ok!" >> /tmp/httpd-acc.log  # 如果状态正常,追加到日志中 else /etc/rc.d/init.d/httpd start &> /dev/null  # 把所有输出丢弃 echo "$(date) httpd reboot!" >> /tmp/httpd-err.log  # 重启记录追加到错误日志 fi
    复制代码

    3. 多分支if条件语句

    复制代码
    if [ 条件判断式1 ]
        then
            当条件判断式1成立时,执行程序1
        elif [ 条件判断式2 ]
            then
                当条件判断式2成立时,执行程序2
        ...更多判断...
        else
            当所有条件都不成立时,最后执行此程序
    fi
    复制代码
    复制代码
    #!/bin/bash
    # 判断用户输入的是什么文件
    
    read -p "Please input a filename:" file # 接收键盘的输入,并赋予变量file
    
    if [ -z "$file" ]
        then
            echo "Error, please input a filename"
            exit 1
        elif [ ! -e "$file" ]    # 判断file的值是否存在
            then
                echo "Your input is not a file!"
                exit 2
        elif [ -f "$file" ]    # 判断file的值是否为普通文件
            then
                echo "$file is a regular fie!"
        elif [ -d "$file" ]
            then
                echo "$file is a directory!"
        else
            echo "$file is an other file!"
    fi
    复制代码

    【流程控制 - case 语句】

    多分支case条件语句:case语句只能判断一种条件关系,而if语句可以判断多种条件关系。

    复制代码
    case $变量名 in
        "值1")
             如果变量的值等于值1,则执行程序1
             ;;
        "值2")
    如果变量的值等于值2,则执行程序2 ;; *) 如果变量的值都不是以上的值,则执行此程序 ;; esac
    复制代码
    复制代码
    #!/bin/bash
    # 判断用户输入
    read -p "Please choose yes/no" -t 30 cho case $cho in "yes") echo "You choose yes" ;; "no") echo "You choose no" ;; *) echo "You choose none" ;; esac
    复制代码

    【流程控制 - for 循环】

    语法1:

    for 变量 in 值1 值2 值3... ; do
        程序
    done

    语法2:

    for (( 初始值; 循环控制条件; 变量变化 ))
        do
            程序
        done
    复制代码
    #!/bin/bash
    # 打印时间
    for time in morning noon afternoon evening ; do echo "This time is $time" done for i in 1 2 3 4 ; do echo $i done
    复制代码
    复制代码
    #!/bin/bash
    # 批量解压缩脚本
    
    cd /lnmp
    ls *.tar.gz > ls.log
    
    for i in $(cat ls.log) ; do
        tar -zxf $i &> /dev/null
    done
    rm -rf /lnmp/ls.log
    复制代码
    复制代码
    #!/bin/bash
    # 求和
    
    s=0
    for (( i=1; i<=100; i++ )) ; do
        s=$(( $s + $i ))
    done
    echo "The sum of 1+2+3+...+100 is : $s"
    复制代码
    复制代码
    #!/bin/bash
    # 批量添加指定数量的用户
    
    read -p "Please input user name:" -t 30 name
    read -p "Please input the number of users:" -t 30 num
    read -p "Please input the password of users:" -t 30 pass
    
    # -a用于连续多个条件判断
    if [ ! -z "$name" -a ! -z "$num" -a ! -z "$pass" ]
        then
            y=$(echo $num | sed 's/^[0-9]*$//g')    # 任意数字替换为空
            if [ -z "$y" ]    # 如果y的值是空,则num是数字
                then
                    for (( i=0; i<=$num; i++ ))
                        do
                            /usr/sbin/useradd $name$i &> /dev/null
                            echo $pass | /usr/bin/passwd --stdin "$name$i" &> /dev/null
                        done
            fi
    fi
    复制代码

    【流程控制 - while 和 until 循环】

    while循环是条件循环,只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。

    while [ 条件判断式 ]
        do
            程序
        done
    复制代码
    #!/bin/bash
    # 示例用法
    
    while [ $# -gt 0 ]; do
        case "$#" in
        3)
            echo "第一个参数是$1, 参数个数是$#"
            ;;
        4)
            echo "第一个参数是$1, 参数个数是$#"
            ;;
        *)
            echo 'What happened'
            ;;
        esac    # 与case对应构成case语句,形如if和fi
    
        case "$#" in
        abc)
            ...  ;;
        esac
        shift    # 用shift命令把位置参数左移
    done
    复制代码

    运行如:./example.sh 3 4 5

    until循环:和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。

    复制代码
    #!/bin/bash
    
    i=1
    s=0
    until [ "$i" -gt 100 ]    # 循环直到变量i的值大于100就停止循环
        do
            s=$(( $i + $s))
            i=$(( $i + 1 ))
        done
    echo "The sum is : $i"
    复制代码

    2.4 特殊的shell命令

    (1)read命令

    [shawnee@localhost test]$ cat readtest
    echo -n "Please input some words:"
    read a b c
    echo "a=$a"
    echo "b=$b"
    echo "c=$c"
    
    [shawnee@localhost test]$ . readtest
    Please input some words:one two three four
    a=one
    b=two
    c=three four
    

    (2)命令置换:讲一个命令的输出用做另一个命令的参数(倒引号`)

    [shawnee@localhost test]$ `pwd`
    bash: /home/shawnee/test: 是一个目录
    

    (3)set命令:用来给位置变量赋值

    [shawnee@localhost test]$ cat settest
    set one two three
    echo $1 $2 $3
    date
    set `date`
    echo $1 $2 $3
    
    [shawnee@localhost test]$ . settest
    one two three
    2018年 02月 12日 星期一 23:09:10 CST
    2018年 02月 12日
    

    (4)shift命令:将命令行参数向左移动,其使用形式为:shift n,缺省为向左移一位

    [shawnee@localhost test]$ cat testshift
    until [ -z $1 ]
    do
    	echo $1
    	shift
    done
    echo $0
    
    [shawnee@localhost test]$ bash testshift one two three
    one
    two
    three
    testshift
    

    (5)expr命令:用来处理算术运算(数字、字符串、运算符每个元素之间必须有空格)

    #expr 3 + 1
    #expr 2 * 3
    #对shell有特殊含义的字符:* % () >< 必须在前面加‘’
    

     (6)let命令:与expr类似,但表达式中变量可直接访问,不需加美元符号,也不需要有空格,也不需要加前倒号

    let expressions 或 (( expressions))

    [shawnee@localhost test]$ i=5
    [shawnee@localhost test]$ let i=i*6
    [shawnee@localhost test]$ echo $i
    30
    [shawnee@localhost test]$ echo $((3*2))
    6
    

      

  • 相关阅读:
    Latex学习
    【测试】安卓自动化测试代码片段Java
    【测试】adb(Android debug bridge译名:安卓测试桥)的介绍与常用命令
    【测试】安卓开发中常用的布局和UI元素
    mac终端命令大全
    【测试】使用UIAutomatorViewer做App元素探测工作
    【测试】adb连接夜神模拟器
    mac版本夜神模拟器卡99的解决办法
    mac电脑查看apk文件的包名等信息
    新版macbook pro 取消/恢复开盖启动 revert
  • 原文地址:https://www.cnblogs.com/exciting/p/8444264.html
Copyright © 2011-2022 走看看