Shell编程规范与变量

Shell编程规范与变量

Shell脚本概述

Shell脚本的概念

  • 将要执行的命令按顺序保存到一个文本文件
  • 给该文件可执行权限
  • 可结合各种Shell控制语句以完成更复杂的操作

Shell脚本应用场景

  • 重复性操作
  • 交互性任务
  • 批量事务处理
  • 服务运行状态监控
  • 定时任务执行
  • ……

Shell的作用

  • 命令解释器,“翻译官”
  • 介于系统内核与用户之间,负责解释命令行
  • 系统上合法的Shell要写入/etc/shells,系统某些服务运行过程中,会去检查用户能够使用的Shell,而这些Shell的查询借助于/shell/shells文件
  • 用户登录时,系统会给一个Shell来给用户使用,而这个登陆取得的Shell就记录在/etc/passwd中。

用户登陆的Shell

  • 登陆后默认使用的Shell程序,一般为/bin/bash

  • 不同的Shell的内部指令、运行环境等会有所区别

  • Linux中的shell

    • 检查一下/etc/shells这个文件,里面就是Linux所包含的Shell。

    • 最常用的就是bash、tcsh、csh、sh、nologin这些shell。这些shell都是依据Linux发展者的不同所创造出的不同版本。

    • bash:基准于GNU的框架下发展出的Shell。

    • csh:语法有点类似于c语言的Shell。

    • tcsh:整合了csh,提供更多的功能。sh:已经被bash所替换。

    • nologin:这个shell可以让用户无法登录主机。

shell脚本的作用

  • 自动化运维

  • 批量化重复操作可以编写脚本结合计划任务自动周期运行

  • 减轻管理员工作量

  • 提高处理文本文件的速度避免配置出错

    Shell是一个面向字符串的编程语言,可以跟Python之类的其他语言配合起来,比如某个复杂的功能使用一个Python脚本来实现,然后在shell中调用这个脚本实现较复杂的功能;或者反过来,在Python脚本中调用外部的Shell脚本来提高自动化的效率,也是可以的。

Shell编程规范

  • Shell脚本的构成

    1. 脚本申明(解释器)∶若第一行为"#!/bin/bash",表示此行以下的代码语句是通过/bin/bash程序来解释执行,#/bin/bash为默认解释器。还有其它类型的解释器,比如#!/usr/bin/python、#!/usr/bin/expect。
    2. 注释信息:以"#"开头的语句表示为注释信息,被注释的语句在运行脚本时不会被执行。
    3. 可执行语句:比如echo命令,用于输出" "之间的字符串
  • 编写脚本代码

  • 使用vim文本编辑器

    vim /root/first.sh

    每行一条Linux命令,按执行顺序依次编写

    #!/bin/bash
    #This is my first shell-script.
    cd /boot
    echo "当前的目录位于:"pwd
    echo "其中以vml开头的文件包括:"ls -lh vml*
    
  • 赋予可执行权限,使脚本具有可执行属性

    chmod +x first.sh

  • Shell脚本的执行

    • 方法一:指定路径的命令,要求文件必须有x权限。(执行在脚本中的shell环境)

      chmod +x /root/first.sh

      • 指定绝对路径: /root/first.sh
      • 指定相对路径:./first.sh
    • 方法二:指定shell来解释脚本,不要求文件必须有x权限。(执行在当前用户所在的shell环境)

      • sh脚本路径: sh first.sh

      • source脚本路径:. first.sh或者source first.sh

重定向与管道

管道操作 “|”

  • 将管道符号"|"左侧的命令输出的结果,作为右侧命令的输入(处理对象),同一行命令中可以使用多个管道。

    ps aux l wc -l

    echo "abc123" | passwd --stdin zhangsan

交互式硬件设备

  • 标准输入:从该设备接收用户输入的数据

  • 标准输出:通过该设备向用户输出数据

  • 标准错误:通过该设备报告执行出错信息

    类型设备文件文件描述编号默认设备
    标准输入/dev/stdin0键盘
    标准输出/dev/stdout1显示器
    标准错误输出/dev/stderr2显示器

重定向操作

类型操作符用途
重定向输入<从指定的文件读取数据,而不是从键盘输入
重定向输出>将输出结果保存到指定的文件(覆盖原有内容)
重定向输出>>将输出结果追加到指定的文件尾部
标准错误输出2>将错误信息保存到指定的文件(覆盖原有内容)
标准错误输出2>>将错误信息追加到指定的文件中
混合输出&>将标准输出、标准错误的内容保存到同一个文件中
混合输出2>&1将标准输出、标准错误的内容保存到同一个文件中
  • ls -lh > log.txt 2>&1等同于ls -lh &> log.txt

    • 本来1–>屏幕(1指向屏幕)

    • 执行>log后,1–>log.txt(1指向log.txt)

    • 执行2>&1后,2–>1(2指向1,而1指向log.txt,因此2也指向了log.txt)

  • echo "123456" > pass.txt

    passwd --stdin zhangsan < pass.txt

    从pass.txt文件中取密码,需要注意SELinux会影响此命令执行,若执行失败可尝试关闭SELinux

Shell脚本变量

Shell变量的作用、类型

  • 变量的作用

    • 用来存放系统和用户需要使用的特定参数(值)

      变量名:使用固定的名称,由系统预设或用户定义

      变量值:能够根据用户设置、系统环境的变化而变化

  • 变量的类型

    • 自定义变量:由用户自己定义、修改和使用
    • 特殊变量
      • 环境变量:由系统维护,用于设置工作环境
      • 只读变量:不能被修改
      • 位置变量:通过命令行给脚本程序传递参数
      • 预定义变量:Bash中内置的一类变量,不能直接修改

自定义变量

/etc/profile中可设置重启不消失的变量(export全局)

  • 定义一个新的变量

    • 变量名以字母或下划线开头,区分大小写,建议全大写

      变量名=变量值 //变量值包含空格或者其他特殊符号时,要用引号包裹

      • declare

        declare [+/-][rxi][变量名称=设置值] 或 declare -f

        • +/-:"-“指定变量的属性,”+"是取消变量所设的属性。
        • -f :仅显示函数。
        • -r:将变量设置为只读。
        • -x :指定的变量会成为环境变量,可供shell以外的程序来使用。
        • -i :[设置值]可以是数值,字符串或运算式。
  • 查看变量的值

    echo $变量名 //要在变量名后添加其他字符时,需要用{}将变量分隔出来,防止产生歧义

  • 赋值时使用引号

    • 双引号:允许通过$符号引用其他变量值
    • 单引号:禁止引用其他变量值,$视为普通字符
    • 反撇号:命令替换,提取命令执行后的输出结果(相当于"$(……)")
  • 从键盘输入内容为变量赋值

    read [-p "提示信息"] 变量名

    echo -n "……" //不换行输出,默认情况下输出结束即换行

  • 变量作用范围

  • 默认情况下,新定义的变量只在当前的Shell环境中有效,因此称为局部变量。当进入子程序或新的子Shell环境时,局部变量将无法再使用。

  • 可以通过内部命令export将指定的变量导出为全局变量,使用户定义的变量在所有的子Shell环境中能够继续使用

    • 格式1:export 变量名
    • 格式2:export 变量名=变量值
  • 可以使用pstree命令查看shell环境

  • 输入bash命令进入子shell环境,

  • 按Ctrl+D组合键或输入exit命令退出子shell环境

    export product version   #导出为全局变量
    bash
    echo " $product $version"   #子程序引用全局变量
    
整数变量的运算
  • 整数变量的运算

    expr 变量1 运算符 变量2 [运算符变量3] …… //注意空格

  • 常用运算符

    • 加法运算:+
    • 减法运算:-
    • 乘法运算:\*
    • 除法运算:/(得到商)
    • 求模(取余)运算:%

    [ ] 和 [ ]和 [](( ))括号中可以整数变量运算也不一定必须加空格

    let i=12*5:let可以整数变量运算

  • 常用的运算表达式

    i=$(expr 12 \* 5)

    i=$((12 * 5))

    i=$[12 * 5]

    let i=12\*5

在ksh中的test

  • 数字的运算可使用let、(()),其中运算时不需要变量$符号,运算符为+、-、*、/、%,不建议使用expr

  • 数字的比较使用(()),其运算符>、>=、<、<=、==、!=

  • 可以使用算术扩展,如:(( 99+1 <= 101 ))

  • 字符表达式的比较使用[[ ]],其运算符=、!=、-n、-Z

  • 文件表达式的测试使用[[ ]],其运算符-r、-l、-w、-x、-f、-d、-s、-nt、-ot

  • 逻辑表达式的测试使用[[ ]],其运算符!、&&、ll

  • 数字比较、字符比较、逻辑测试可以组合,如$[[ "a" != "b" && 4 -gt 3 ]]

  • 支持bash中的通配符扩展,如:[[ hest = h??t ]][ hest = h*t ]]

  • 使用(())时,不需要空格分隔各值和运算符,使用[[]]时需要用空格分隔各值和运算符。

bash与ksh中的[[]]不同

  • 在redhat9的bash中也可以使用[[]]符号。但是建议严格按照上面的原则使用。
  • 在bash中,数字的比较最好使用(()),虽说可以使用[[]],但若在其内使用运算符>、>=、<、<=、==, !=时,其结果经常是错误的,不过若在[[ ]]中使用[ ]中的运算符"-eq、-ne、-le、-lt、-gt、-ge”等,还尚未发现有错。因此诸如$[[ “a” != “b” && 4>3 ]]这类组合(见上)也不可以在bash中使用,其出错率很高。
    • 例:[[ "a" != "b" && 10 > 2]]判断结果就不正常。
    • 诸如[ 2 \< 10 ][[ 2 < 10 ]]都是不要使用。使用算术扩展最好用(( 99+1 == 100 )),而不要使用[[ 99+1 -eq 100 ]]。
浮点运算
  • bash不支持浮点运算,如果需要进行浮点运算,需要借助bc, awk处理。

    #!/ bin/bash
    
    # 加
    f=$(echo "4.3+2.5" | bc)
    echo " 4.3+2.5=$f"
    
    #减
    f=$(echo "4.3-2.5" | bc)
    echo "4.3-2.5=$f"
    
    #乘
    f=$(echo "4.30*2.50" | bc)
    echo "4.3*2.5=$f"
    
    #除
    f=$(echo "scale=2;4.3/2.5" | bc) # scale指定保留小数位数
    echo "4.3/2.5=$f"
    
    #混合运算
    f=$(echo "5.6/(2.2-1.1)*2+1.1" | bc)
    echo "5.6/(2.2-1.1)*2+1.1=$f"
    
    # ---------------------
    
    #加
    f=$(awk 'BEGIN{print 4.5+3.4} ')   # BEGIN最多六位小数
    echo "4.5+3.4=$f"
    
    #减
    f=$(awk 'BEGIN{print 4.5-3.4} ')
    echo "4.5-3.4=$f"
    
    #乘
    f=$(awk 'BEGIN{print 4.5*3.4}')
    echo "4.5*3.4=$f"
    
    #除
    f=$(awk 'BEGIN{print 4.5/3.4}')
    echo "4.5/3.4=$f"
    
    #混合
    f=$(awk 'BEGIN{print (4.5-3.4)*2+3} ')
    echo " (4.5-3.4)*2+3=$f"
    

特殊的Shell变量

  • 环境变量

    • 由系统提前创建,用来设置用户的工作环境

    • 配置文件: /etc/profile、~/.bash_profile

    • 常见的环境变量(env 显示当前环境变量)

      • PWD、PATH

      • USER、SHELL、HOME

  • 只读变量

    • 用于变量值不允许被修改的情况,不可改变、删除、unset(重启可以消除)
    • 定义格式:readonly name=xxx
    • declare -r name=xxx:declare定义只读变量
  • 位置变量

    • 表示为$n,n为1~9之间的数字

    • vim num.sh

      #!/bin/bash
      echo $1
      echo $2
      echo $3
      echo $4
      echo $5
      echo $6
      echo $7
      echo $8
      echo $9
      echo ${10}   #9以上的位置参数要用{}括起来,否则输出$1加0
      

      ./num.sh 1 2 3 4 5 6 7 8 9 10

    • vim cal.sh

      #!/bin/bash
      
      num1=$1   #传入
      num2=$2
      
      sum=$[num1 + bum2]
      echo "$1 + $2 = $sum"
      

      ./cal.sh 10 20

    • 位置变量可用于给脚本传参

  • 预定义变量

    • $*$@:表示命令或脚本要处理的参数。

      • $*:把所有参数看成以空格分隔的一个字符串整体(单字符串)返回,代表"$1 $2 $3 $4"。

      • $@:把各个参数加上双引号分隔成n份的参数列表,每个参数作为一个字符串返回,代表"$1""$2"$3""$4"。

      • #!/bin/bash
          
        echo "未加双引号时,两者相同"
          
        echo $*
        echo $@
          
        echo "加上引号后对比"
          
        for i in "$*"
        do
          echo $i
          echo ""
        done   # 结果仅一次性输出所有参数
          
        echo "----------"
          
        for j in "$@"
        do
          echo $i
          echo ""
        done   # 结果依次输出所有参数
        
    • $0:表示当前执行的脚本或命令(进程/程序名)的名称。

    • $#:表示命令或脚本要处理的参数的个数。

    • $?:表示前一条命令或脚本执行后的返回状态码,返回值为0表示执行正确,返回任何非0值均表示执行出现异常(包括无结果产生的执行)。也常被用于 shell 脚本中 return 退出函数并返回的退出值。

      vim mybak.sh

      #!/bin/bash
      time=backup-`date +%F`.tgz # 指定归档文件名样式
      tar zcf bak-${time}.tar.gz $* &> /dev/null
         #/dev/null表示的是一个黑洞文件,通常用于丢弃不需要的数据输出,这里丢弃任务完成过程中的提示
      echo "已执行$0脚本进行文件备份"
      echo "共完成$#个对象的备份"
      echo "具体内容包括:$@。"
      

      chmod +x mybak.sh

      ./mybak.sh /etc/passwd /etc/shadow /etc/yum.conf /etc/yum.repos.d/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值