Shell编程学习

  • Post author:
  • Post category:其他


《linux就该这么学》学习笔记

Shell终端解释器相当于人与计算机硬件之间的“翻译官”,我们通过输入命令可以轻松发挥计算机的各种功能。

Shell脚本命令的工作方式一般有两种:


交互式

(Interactive):用户每输入一条命令就立即执行;


批处理

(Batch):由用户事先编好一个完整的Shell脚本,Shell会一次性脚本中的命令。

我们编写的Shell脚本就是通过批处理的方式执行的。


查看默认的终端解释器

echo $SHELL
/bin/bash #这里假设我们默认的终端解释器是bash,其位置在/bin/bash


注意:一般为了做出区分,我们一般使用XXX.sh作为脚本的名称



一. 脚本入门
  1. 第一个简单的脚本 test.sh

    #!/bin/bash
    #第一个简单的脚本
    pwd
    ls -a
    

    以上内容就可以组成一个完整的脚本了,第一行使脚本声明(#!)告诉系统使用哪种Shell解释器来执行该脚本,第二行以#开头的语句是注释,第三行第四行就是普通的命令了,显示脚本文件所在目录,以及显示该目录下的所有文件。

    使用编辑器编写好脚本后保存退出,将脚本文件命名为test.sh,同时使用

    sudo chmod u+x test.sh

    来修改脚本文件的权限,否则无法正常运行脚本。修改好后在终端输入

    ./test.sh

    即可执行脚本(注意终端当前所在位置)。

    若果你不想修改脚本的权限,也可以使用**

    bash test.sh

    **来执行脚本

  2. 脚本接收用户的参数

    对于执行的脚本,我们可以传递参数,Shell脚本语言也预先定义了一些变量用于获取我们传递的参数:

    $# #代表我们一共传递了几个参数
    $0 #代表脚本名称
    $* #对应的是我们第几个参数,参数位置从1开始计数
    $? #代表上一次命令执行的返回值
    

    我们可以编写如下脚本test.sh

    #!/bin/bash
    #测试参数使用
    echo "脚本名称为$0"
    echo "一共有$#个参数"
    echo "第一个参数是$1"
    

    修改脚本文件权限后可以执行如下命令

    ./test.sh param1 param2
    

    输出

    脚本名称test.sh
    一共有2个参数
    第一个参数是param1
    
  3. 条件测试语句

    Shell提供了测试语法,可以判断条件表达式是否成立,若成立则返回数字

    0

    ,失败则返回

    非零

    数字。切记,条件表达式两边都应该有一个空格。

    注意这里和我们平时编程的思路不一致,成功返回0,失败返回非零

    [ 条件表达式 ] #注意括号旁边的空格,后面等号两边也有空格
    

    按照测试对象来划分,条件测试语句有四种

    • 文件测试语句
    • 逻辑测试语句
    • 整数值比较语句
    • 字符串比较语句
    1. 文件测试语句

      -d #测试文件是否为目录类型
      -e #测试文件是否存在
      -f #判断是否为一般文件
      -r #测试当前用户是否有读取权限
      -w #测试当前用户是否有写入权限
      -x #测试当前用户是否有执行权限
      

      案例

      [ -d /etc/ens160 ] #判断设备是否为目录类型,是返回0,否则返回非零
      
    2. 逻辑语句


      Shell中的与运算(&&),或运算(||)和非运算(!)

      若将两个命令通过与运算(&&)连接,前面命令执行成功后才会执行后面的命令,否则不执行后面的命令

      [ -e /etc/ens160] && echo "exist" #只有当/etc/ens160存在时才会输出exist
      

      若将两个命令通过或运算(||)连接,则表示前面命令执行失败时才会执行后面的命令

      [ -e /etc/ens160] || echo "not exist" #只有当/etc/ens160不存在时才会输出not exist
      

      非运算表示取反正确与错误对调

      [ ! $USER = root ] || echo "root" #如果当前用户是root,则输出root,注意符号之间是有空格的
      


      推广用法

      ,当前用户为root则输出root,否则输出normal user

      [ ! $USER = root] && echo "normal user" || echo "root"
      
    3. 整数比较语句

      考虑到大于号小于号会与重定向等冲突,Shell脚本语言采用参数来比较

      -eq #是否等于
      -nq #是否不等于
      -gt #是否大于
      -lt #是否小于
      -le #是否小于或等于
      -ge #是否大于或等于
      

      举例

      [ 5 -eq 5]
      echo $? # 输出 0
      [ 1 -gt 10]
      echo $? # 输出 1
      
    4. 字符串比较语句

      = #比较字符串内容是否相同
      != #比较字符串内容是否不同
      -z #判断字符串内容是否为空
      

      举例

      [ -z $String] #判断变量String是否为空值
      [ ! $LANG = "en.US" ] && echo "Not en.US" #如果当前系统语言不是en.US则输出Not en.US
      



    二. 流程控制语句

    如果一个脚本只能顺序执行,那么它的适用性以及功能一定会大打折扣,因此Shell脚本语言也提供了流程控制语句,让我们编写出更加复杂但是功能更加强大的脚本。

    1. if条件测试语句

      if [ 条件表达式 ];
      then
      	#执行语句
      elif [ 条件表达式 ];
      then
      	#执行语句
      else
      	#执行语句
      fi
      

      注意:如果if,then或者elif then写在一行,则中间需要加上分号

      使用案例

      test.sh

      :输入分数,若果在[60,100]则输出”Pass”,如果在[0,60)则输出“ Not Pass”,如果分数不在[0,100]以内,则输出“Not valid”。

      #!/bin/bash
      # score test
      if [ $1 -ge 0 ] && [ $1 -lt 60 ]
      then
      	echo "Not Pass"
      elif [ $1 -ge 60 ] && [$1 -le 100 ]
      then
      	echo "Pass"
      else
      	echo "Not valid"
      fi
      
      bash test.sh 60 #执行命令运行
      
    2. for条件循环语句

      for 变量名 in 取值列表
      do
      	命令序列
      done
      

      案例:创建文件IPTest.txt,内容为每一行一个ip地址,编写脚本test.sh,测试这些ip链接情况,注意IPTest.txt文件和test.sh文件要放在同一个目录中。

      # IPTest文件内容
      192.168.10.10
      192.168.10.20
      192.168.10.30
      

      编写脚本test.sh

      #!/bin/bash
      # 测试IP
      LIST=$(cat ./IPTest.txt)
      for IP in $LIST
      do
      	ping -c 3 -i 0.2 -W 3 $IP &> /dev/null
      	if [ $? -eq 0 ]
      	then
      		echo "Host $IP is Online"
      	else
      		echo "Host $IP is not Online"
      	fi
      done
      
      bash test.sh # 执行命令运行
      

      /dev/null是一个黑洞文件,写入这里的内容相当于被删除,这里将输出信息重定向到这个文件中可以是屏幕不输出信息而减小干扰。

    3. while条件循环语句

      while 条件测试操作
      do
      	命令序列
      	exit #结束循环,可选
      done
      
    4. case条件测试语句

      case 变量值 in
      模式1)
      	命令序列1
      	;;
      模式2)
      	命令序列2
      	;;
      ......
      *)
      	默认命令序列#没有选项则执行
      esac
      

      案例:输入字符检测类型

      #!/bin/bash
      # 输出成绩(以参数的形式),返回及格情况
      case "$1" in
      [a-z] | [A-Z])
      	echo "输入的字母"
      	;;
      [0-9])
      	echo "输入的是数字"
      	;;
      *)
      	echo "input not vaild"
      esac
      



    3. 计划任务服务程序
    1. 一次性计划任务,使用at命令

      # at命令参数
      -f #指定包含命令的任务文件
      -q #指定新任务名称
      -l #显示待执行任务的列表
      -d #删除指定的待执行的任务
      -m #任务执行后向用户发送邮件
      

      使用示例

      # 12:00重启电脑
      echo "sudo reboot" | at 12:00
      

      在当前时间的某个时间之后执行任务


      at now + 1 HOUR

      一小时之后,还有分钟

      MINUTE

      ,日

      DAY

      ,月

      MONTH

      # 一分钟之后再当前目录中的test.txt文件中输入hello world字符串
      echo "echo 'hello world' >> ./test.txt" | at now +1 minute
      
    2. 长期性计划任务,一般这种任务是周期性任务,会在规定时间时重复执行,我们使用crontab命令

      # crontab命令参数
      -e #编辑任务,会打开vim程序,在这里面编写计划任务,编写格式下面会介绍
      -u #指定用户名称,如果是管理员,可以使用u参数修改别的用户的任务计划
      -l #列出任务列表
      -r #删除任务,后面加上你的任务
      

      任务编写格式:

      # 分钟 小时 日期 月份 星期 命令
      
      # 分钟:取值为0~59的整数
      # 小时:取值为0~23的整数
      # 日期:取值为1~31的整数
      # 月份:取值为1~12的整数
      # 星期:取值为0~7的整数,其中0和7均表示星期日
      
      #例如每周日晚上23点重启电脑
      0 23 * * 0 sudo /usr/sbin/reboot
      

      使用crontab命令的注意事项:

      1. 在编写计划任务时,一般使用#开头编写注释,方便自己和他人查看了解信息(因为是vim编辑,所以可以写注释)
      2. 对于任务的编写,分钟字段是必须有数值的,其他的字段可以使用*表示任意值,同时需要注意的是,日期和星期两个字段不能同时出现数值,必须至少有一个为*号。
      3. 我们编写任务时所有的命令都需要使用

        绝对路径

        ,如

        reboot

        命令使用

        /usr/sbin/reboot

        ,如果不知道命令的路径,请使用

        whereis 命令

        命令来询查绝对路径。



    在这里记录一种Ubuntu设置开机自启动脚本的办法(打开终端输入执行脚本命令)
    1. Ubuntu开机启动命令功能(设置一个开机自动执行的命令,这里设置为打开一个终端,再在终端里开启脚本)

      gnome-session-properties
      

      在图形界面里添加命令

      gnome-terminal -- bash -c "cd 脚本所在文件夹的位置; bash 脚本名称.sh"
      



版权声明:本文为myc13381原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。