Linux 命令(9)-Shell编程

155 阅读4分钟

Shell编程

  1. type 确定內建命令
  2. . 执行程序
  3. alias 别名
  4. unalias 删除别名
  5. bgfgjobs 任务前后台切换
  6. cd 改变目录
  7. declaretypeset 声明变量
  8. echo 打印字符
  9. break 跳出循坏
  10. continue 循坏控制
  11. exec 执行命令来取代当前Shell
  12. exit 退出Shell
  13. export 使变量能被子Shell识别
  14. kill 发送信号给指定PID和进程
  15. let 整数运算
  16. pwd 显示当前工作目录
  17. local 声明局部变量
  18. read 从标准输入读取一行到变量
  19. return 定义函数返回值
  20. shift 向左移动位置参数
  21. ulimit 显示并设置进程资源限度
  22. test 测试表达式

Shell编程基础

  1. 变量

    1. 局部变量

    2. 环境变量

      变量含义
      BASHBash Shell的全路径
      BASH_VERSIONBash Shell的版本
      CDPATH用于快速进入某个目录
      EUID记录当前用户的UID
      FUNCNAME在用户函数体内部记录当前函数体的函数名
      HISTCMD记录下一条命令在history中的编号
      HISTFILE记录history命令记录文件的位置
      HISTFILESIZE设置HISTFILE文件记录命令的行数
      HISTSIZE定义缓存区的大小
      HOSTNAME展示主机名
      HOSTTYPE展示主机架构
      MACHTYPE主机类型的GNU标识
      LANG设置当前系统的语言环境
      PWD记录当前目录
      OLDPWD记录之前目录
      PATH命令的搜索路径
      PS1命令提示符
    3. 变量命名

      变量区分大小写

    4. 变量赋值和取值

      赋值:name=jhonmsg="Hello world!" 取值:echo $nameecho ${msg}

    5. 取消变量unset name

    6. 特殊变量

      1. 位置参数

        参数含义
        $0脚本本身
        $1第一个参数
        $2第二个参数
        ......
        ${10}第10个参数
        $#脚本参数个数总和
        $@脚本所有参数
        $*脚本所有参数
      2. $? 脚本或命令返回值

    7. 数组

      1. 数组定义

        [root@localhost ~]# declare -a Array
        [root@localhost ~]# Array[0]=0
        [root@localhost ~]# Array[1]=1
        [root@localhost ~]# Array[2]="HelloWorld"
        [root@localhost ~]# declare -a Name=('jhon' 'sue')
        [root@localhost ~]# Name[2]='wang'
        [root@localhost ~]# Name1=('jhon' 'sue')
        [root@localhost ~]# Score=([3]=3 [5]=5 [7]=7)
        
      2. 数组操作

        # 取数组第一个值
        [root@localhost ~]# echo ${Array[0]}
        0
        # 取数组第三个值
        [root@localhost ~]# echo ${Array[2]}
        HelloWorld
        # 打印数组中的值
        [root@localhost ~]# echo ${Name[0]}
        jhon
        [root@localhost ~]# echo ${Name[1]}
        sue
        # 获取数组所有的值
        [root@localhost ~]# echo ${Array[@]}
        0 1 HelloWorld
        [root@localhost ~]# echo ${Array[*]}
        0 1 HelloWorld
        # 获取数组长度
        [root@localhost ~]# echo ${#Array[@]}
        3
        [root@localhost ~]# echo ${#Array[*]}
        3
        # 获取数组某个元素的长度
        [root@localhost ~]# echo ${#Array[2]}
        10
        # 取出数组中第一个、第二个元素
        [root@localhost ~]# echo ${Array[@]:1:2}
        1 HelloWorld
        # 取出数组中第二个元素从第0个字符开始连续5个字符
        [root@localhost ~]# echo ${Array[2]:0:5}
        Hello
        # 数组拼接
        [root@localhost ~]# Conn=(${Array[@]} ${Name[@]})
        [root@localhost ~]# echo ${Conn[@]}
        0 1 HelloWorld jhon sue wang
        # 数组替换元素
        [root@localhost ~]# Array=(${Array[@]/HelloWorld/HelloJhon})
        [root@localhost ~]# echo ${Array[@]}
        0 1 HelloJhon
        # 删除数组中的一个元素
        [root@localhost ~]# unset Array[1]
        [root@localhost ~]# echo ${Array[@]}
        0 HelloJhon
        # 删除数组
        [root@localhost ~]# unset Array
        [root@localhost ~]# echo ${Array[@]}
        
        [root@localhost ~]#
        
    8. 只读变量 readonly R0=100declare -r R0=100

    9. 变量作用域

  2. 转义和引用

    1. 转义 \
    2. 引用
      1. 部分引用
      2. 全引用
    3. 命令替换
      1. `命令`
      2. $(命令)
  3. 运算符

    1. 算数运算

      运算符含义
      +
      -
      *
      /
      %取余
      **幂运算
      +=加等
      -=减等
      *=乘等
      /=除等
      %=取余等
    2. 位运算

      运算符含义
      <<左移
      >>右移
      &按位与
      ``按位或
      ^按位异或
      ~按位非
    3. 自增++、自减--

    4. 其他

      1. $[]
      2. expr
      3. declare 内建运算命令
      4. 算数扩展 $((算数表达式))
      5. bc
  4. 特殊字符

    1. 通配符 *?[]
    2. 引号
    3. 注释符 #
    4. 大括号
    5. 控制字符
    6. 杂项

测试和判断

  1. 测试

    0为真,其他为假

    1. 测试结构

      test exp[ exp ]

    2. 文本测试

      • test file_operator FILE
      • [ file_operator FILE ]
      [root@localhost ~]# test -e /var/log/messages
      [root@localhost ~]# echo $?
      0
      [root@localhost ~]# [ -e /var/log/messages ]
      [root@localhost ~]# echo $?
      0
      [root@localhost ~]#
      
      文件测试符含义
      -b FILE当文件存在且是个块文件时返回真,否则为假
      -c FILE当文件存在且是个字符设备时返回真,否则为假
      -d FILE当文件存在且是个目录时返回真,否则为假
      -e FILE当文件存在或目录时返回真,否则为假
      -f FILE当文件存在且是普通文件时返回真,否则为假
      -x FILE当文件存在且是可执行文件时返回真,否则为假
      -w FILE当文件存在且是可写文件时返回真,否则为假
      -r FILE当文件存在且是可读文件时返回真,否则为假
      -l FILE当文件存在且是连接文件时返回真,否则为假
      -p FILE当文件存在且是管道文件时返回真,否则为假
      -s FILE当文件存在且大小不为零时返回真,否则为假
      -S FILE当文件存在且是socket文件时返回真,否则为假
      -g FILE当文件存在且设置了SGID时返回真,否则为假
      -u FILE当文件存在且设置了SUID时返回真,否则为假
      -k FILE当文件存在且设置了sticky属性时返回真,否则为假
      -G FILE当文件存在且属于有效的用户组时返回真,否则为假
      -O FILE当文件存在且属于有效的用户时返回真,否则为假
      FILE1 -nt FILE2当FILE1比FILE2新时返回真,否则为假
      FILE1 -ot FILE2当FILE1比FILE2旧时返回真,否则为假
    3. 字符串测试

      字符串测试含义
      -z "string"字符串string为空时返回真,否则为假
      -n "string"字符串string非空时返回真,否则为假
      "string1"="string2"字符串string1和string2相同时返回真,否则为假
      "string1"!="string2"字符串string1和string2不相同时返回真,否则为假
      "string1">"string2"按字典排序,字符串string1在string2之前时返回真,否则为假
      "string1"<"string2"按字典排序,字符串string1在string2之后时返回真,否则为假
      [root@localhost ~]# str1=""
      [root@localhost ~]# test -z "$str1"
      [root@localhost ~]# echo $?
      0
      [root@localhost ~]# test -n "$str1"
      [root@localhost ~]# echo $?
      1
      [root@localhost ~]# str2="hello"
      [root@localhost ~]# [ -z "str2" ]
      [root@localhost ~]# echo $?
      1
      [root@localhost ~]# [ -n "str2" ]
      [root@localhost ~]# echo $?
      0
      [root@localhost ~]# [ "$str1" = "$str2" ]
      [root@localhost ~]# echo $?
      1
      [root@localhost ~]# [ "$str1" != "$str2" ]
      [root@localhost ~]# echo $?
      0
      [root@localhost ~]# [ "$str1" \> "$str2" ]
      [root@localhost ~]# echo $?
      1
      [root@localhost ~]# [ "$str1" \< "$str2" ]
      [root@localhost ~]# echo $?
      0
      [root@localhost ~]# [[ "$str1" > "$str2" ]]
      [root@localhost ~]# echo $?
      1
      [root@localhost ~]# [[ "$str1" < "$str2" ]]
      [root@localhost ~]# echo $?
      0
      [root@localhost ~]#
      
    4. 整数比较

      整数比较说明
      "num1" -eq "num2"num1 == num2时返回真,否则为假。eq为equal
      "num1" -gt "num2"num1 > num2时返回真,否则为假。gt为great than
      "num1" -lt "num2"num1 < num2时返回真,否则为假。lt为less than
      "num1" -ge "num2"num1 >= num2时返回真,否则为假。ge为great equal
      "num1" -le "num2"num1 <= num2时返回真,否则为假。le为less equal
      "num1" -ne "num2"num1 != num2时返回真,否则为假。ne为not equal
      [root@localhost ~]# num1=10
      [root@localhost ~]# num2=10
      [root@localhost ~]# num3=9
      [root@localhost ~]# num4=11
      [root@localhost ~]# [ "$num1" -eq "$num2" ]
      [root@localhost ~]# echo $?
      0
      [root@localhost ~]# [ "$num1" -gt "$num3" ]
      [root@localhost ~]# echo $?
      0
      [root@localhost ~]# [ "$num1" -lt "$num4" ]
      [root@localhost ~]# echo $?
      0
      [root@localhost ~]# [ "$num1" -ge "$num2" ]
      [root@localhost ~]# echo $?
      0
      [root@localhost ~]# [ "$num1" -le "$num3" ]
      [root@localhost ~]# echo $?
      1
      [root@localhost ~]# [ "$num1" -ne "$num3" ]
      [root@localhost ~]# echo $?
      0
      [root@localhost ~]#
      
    5. 逻辑测试符和逻辑运算符

      • 测试符

        • !
        • -a
        • -o
      • 运算符

        • ! 逻辑非
        • && 逻辑与
        • || 逻辑或
    6. 判断

      1. if判断结构

        if exp; then
            command1
            command2
            ...
        fi
        
      2. if/else判断结构

        if exp; then
            command
        else
            command
        fi
        
      3. if/elif/else判断结构

        if exp1; then
            command1
        elif exp2; then
            command2
        elif exp3; then
            command3
        ...
        else
            command
        fi
        
      4. case判断

        case VAR in
        var1) command1;;
        var2) command2;;
        var3) command3;;
        ...
        *) command;;
        esac
        
  2. 循环

    1. for循坏

      for VARIABLE in (list)
      do
          command
      done
      
    2. 不带列表的for循坏

      for VARIABLE
      do
          command
      done
      
      #!/bin/bash
      # for_list_2.sh
      for var
      do 
          echo "$var "
      done
      echo
      
      [root@localhost code]# bash for_list_2.sh 1 2 3
      1 2 3
      
    3. 类C的for循坏

      for ((exp1;exp2;exp3))
      do
          command
      done
      
    4. for的无限循坏

  3. while循坏

    1. while循坏语法

      while exp
      do
          cmd
      done
      
    2. 使用while按行读取文件

      #!/bin/bash
      while read LINK
      do
          NAME=`echo $LINK | awk '{print $1}'`
          AGE=`echo $LINK | awk '{print $2}'`
          Sex=`echo $LINK | awk '{print $3}'`
          echo "My name is $NAME, I'm $AGE years old, I'm a $Sex."
      done < student_info.txt
      
      [root@localhost code]# bash while04.sh
      My name is John, I'm 30 years old, I'm a Boy.
      My name is Sue, I'm 28 years old, I'm a Girl.
      My name is Wang, I'm 25 years old, I'm a Boy.
      My name is Xu, I'm 23 years old, I'm a Girl.
      [root@localhost code]#
      
    3. while的无限循坏

      # 1
      while ((1))
      do
          cmd
      done
      
      # 2
      while true
      do
          cmd
      done
      
      #3
      while :
      do
          cmd
      done
      
  4. until循坏

    1. until循坏语法

      until exp
      do
          cmd
      done
      
    2. until无限循坏

      #1
      until ((0))
      do 
          cmd
      done
      
      # 2
      until false
      do
          cmd
      done
      
  5. select循坏

    select MENU in (list)
    do
        cmd
    done
    
  6. 嵌套循坏

  7. 循坏控制

    1. break语句
    2. continue语句

函数

  1. 函数的基本知识

    1. 函数定义和调用

      • 定义

        function FUNCTION_NAME(){
            cmd1
            cmd2
            ...
        }
        FUNCTION_NAME(){
            cmd1
            cmd2
            ...
        }
        
      • 调用

        FUNCTION_NAME
        
    2. 函数的返回值

      FILE=/etc/noExistFile
      function checkFileExist(){
          if [ -f $FILE ]; then
              return 0
          else
              return 1
          fi
      }
      
      echo "Call function checkFileExist"
      checkFileExist
      if [ $? -eq 0 ]; then
          echo "$FILE exist"
      else
          echo "$FILE not exist"
      fi
      
  2. 带参数的函数

    1. 位置参数

      function checkFileExist(){
          if [ -f $1 ]; then
              return 0
          else
              return 1
          fi
      }
      
      echo "Call function checkFileExist"
      checkFileExist $1
      if [ $? -eq 0 ]; then
          echo "$1 exist"
      else
          echo "$1 not exist"
      fi
      

      调用

      [root@localhost code]# checkFileExist_v2 /etc/noExistFile
      
    2. 指定位置参数值

      使用内置命令set给脚本指定位置设置参数的值

    3. 移动位置参数

      使用shift移动位置参数,shift的命令可让位置参数左移一位。

  3. 函数库

    1. 自定义函数库

    source /PATH/TO/LIB 加载函数库

    1. 函数库/etc/init.d/function简介

    2. 递归函数

      function factorial01(){
          local NUMBER=$1
          if [ $NUMBER -le 0 ]; then
              RES=1
          else
              factorial01 $((NUMBER-1))
              TEMP=$RES
              NUMBER=$NUMBER
              RES=$((NUMBER*TEMP))
          fi
      }
      factorial01 $1
      echo $RES
      

重定向

  1. 重定向简介

    1. 基本概念

    2. 文件标识符和标准输入输出

  2. I/O重定向

    1. I/O重定向符号和用法

      符号含义
      >标准输出覆盖重定向
      >>标准输出追加重定向
      >&标识输出重定向
      <标准输入重定向
      ``管道
    2. 使用exec

      命令说明
      exec <file将file文件中的内容作为exec的标准输入
      exec >file将file文件作为标准输出
      exec 3<file指定文件标识符
      exec 3<&-关闭文件标识符
      exec 3>file将写入指定文件标识符的内容写入指定文件
      exec 4<&3创建文件标识符3的拷贝4
    3. here Document

      格式为<< delimiter, delimiter是一个用于标注的“分隔符”。

脚本范例

  1. 文件打成zip包

用到的命令

  1. 通过ssh连接远程服务器

    [zerone@localhost ~]$ ssh root@192.168.56.5
    
  2. 通过scp上传文件到服务器

    [zerone@localhost ~]$ scp ./test.txt test@192.168.56.5:test.txt
    
  3. 通过scp下载文件到本地

    [zerone@localhost ~]$ scp test@192.168.56.5:test.txt  ./test.txt
    
  4. 配置静态IP

    1. cd /etc/sysconfig/network-scripts/
    2. vi ifcfg-eth1
    3. 添加如下代码
      NM_CONTROLLED=yes
      ONBOOT=yes
      BOOTPROTO=static
      TYPE=Ethernet
      HWADDR=08:00:27:9B:FF:5A // MAC地址
      IPADDR=192.168.56.6 // IP地址
      NETMASK=255.255.255.0 // 子网掩码
      GATEWAY=192.168.56.1 // 网关
      
    4. 重启系统
  5. 无法访问web服务器

    CentOS7防火墙没有开启端口

    [root@localhost html]# firewall-cmd --permanent --add-port=80/tcp
    success
    [root@localhost html]# firewall-cmd --reload
    success
    
  6. 端口占用

    netstat -anp | grep 8080

  7. 创建软链接

    sudo ln -s /home/zerone/app/v/v /usr/local/bin/v

  8. 删除软链接

    sudo rm /usr/local/bin/v