1.Shell的概念:

  • Shell的定义:

    • Shell (外壳)是一个用C语言编写的程序,它是用户使用Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
    • Shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
  • 什么时脚本:

    • 脚本简单地说就是一条条的文字命令,这些文字命令是可以看到的(如可以用记事本打开查看、编辑)。
    • 常见的脚本:JavaScript, VBScript,ASP, JSP, PHP, SQL, Perl, Shell, python, Ruby, JavaFX,Lua等。
  • 为什么要学生和使用shell:

    • 程序开发的效率非常高,依赖于功能强大的命令可以迅速地完成开发任务
  • 常见的shell种类:

    • 在linux中有很多类型的shell,不同的shell具备不同的功能,shell还决定了脚本中函数的语法,Linux 中默认的shell是/bin/bash,流行的shell有ash、bash、 ksh、csh、 zsh等,不同的shell都有自己的特点以及用途。

      ①csh:c shell 使用的是“类C”语法,csh是具有C语言风格的一-种shell, 其内部命令有52个,较为庞大。目前使用的并不多,已经被/bin/tcsh 所取代。

      ②ksh:Korn shell的语法与Bourne shell 相同,同时具备了C shell的易用特点。许多安装脚本都使用ksh。ksh有42条内部命令,与bash有一定的限制性。

      ③tcsh:是csh的增强版,与C shell完全兼容。

      ④sh:是一个快捷方式,已经被/bin/bash 所取代。

      ⑤nologin:指用户不能登录

      ⑥zsh:目前Linux里最庞大的一种shell:zsh。 它有84个内部命令,使用起来也比较复杂。一般情况下,不会使用该shell.

      ⑦bash:大多数Linux系统默认使用的shell, bash shell是Bourne shell的一个免费版本,它是早的Unix shell, bash还有一个特点,可以通过help命令来查看帮助。包含的功能几乎可以涵盖shell所具有的功能,所以一般的shell脚本都会指定它为执行路径

2.Shell解析器:

特殊符号 功能 说明
; 可使用分号分隔多条命令 在一行上输入和执行多条较短的命令,可使用分号来分隔命令
* 匹配任意零个或者多个字符 不能用于创建文件
匹配任意单个字符 不能用于创建文件
[] 匹配方括号中的任意一个字符,表示范围可以用”-” 不能用于创建文件
[^]或者[!] 匹配方括号中的任意一个字符或数字后进行取反 用于查找和删除文件,不用于创建文件
{string,string} 匹配括号中的任意一个字符串,表示一个范围时,字符串之间个”..” 可用于创建、查看、删除文件
\ s 使\后面的特殊字符失s

1.普通变量的定义与使用:

  • 定义:(只对本次连接有效)

    1
    2
    class_name="yunsuanfu"
    _name_4=$(cmd)
  • 使用:

    1
    echo $class_name  # 输出class_name变量
  • 变量名的规范:

    • 注意,变量名后面的等号左右不能有空格,这可能和你熟悉的所有编程语言都不一样

    • 变量名的命名须遵循如下规则:

      • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。

      • 中间不能有空格,可以使用下划线“_”。

      • 不能使用标点符号。

      • 不能使用bash里的关键字(可用help命令查看保留关键字)。

    • 双引号能够识别变量;单引号是不能识别变量,只会原样输出

    • 双引号能够实现转义(类似于“*”);只会原样输出,单引号是不能转义的

2.环境变量的定义与使用:

  • 环境变量也可称为全局变量,可以在创建它们的Shell 及其派生出来的任意子进程 Shell 中使用,环境变量又可分为自定义环境变量bash 内置的环境变量

    • bash内置的环境变量:用于定义 Shell 的运行环境,保证 Shell 命令的正确执行,Shell 通过环境变量来确定登录用户名命令路径终端类型登录目录
    • 自定义环境变量:自定义环境变量可以在命令行中设置和创建,但用户退出命令时这些变量值就会丢失。如果希望永久保存环境变量,可在用户家目录下的 .bash_profile 或 .bashrc 文件中,或者全局配置 /etc/bashrc 或 /etc/profile 文件中定义,在将环境变量放入上述的文件中后,每次用户登录时这些变量都将被初始化。
  • 所有环境变量的名字均采用大写形式

  • 定义:

    1
    export 变量名=value
  • 通过echo printf 打印变量

    1
    2
    echo $HOME

  • 显示默认的环境变量

    1
    2
    3
    4
    [root@www ~]$ env 
    XDG_SESSION_ID=17
    HOSTNAME=www.oliven.com
    TERM=xterm
  • 其他:

    1
    2
    3
    4
    [root@www ~]$ set 
    BASH=/bin/bash
    [root@www ~]$ declare | head
    BASH=/bin/bash
  • unset 消除本地变量和环境变量

    1
    unset USER

3.命令别名:

  • 别名是命令的快捷方式。对于需要经常执行,并需要很长时间输入的长命令创建快捷方式很有用

  • 在命令行中使用alias命令设置的别名仅在该次登入有效,如果重新开启一个 Shell,或者重新登录

    系统,则这些alias将无法使用。

  • 语法

    1
    2
    3
    alias 别名='原命令'
    例:
    alias myip="ip a | cut -d' ' -f6 | head -9 | tail -1"
  • 查看设置的别名:

    1
    alias
  • 删除别名:

    1
    unalias 别名
  • 在linux中提供alias永久化的方法:

    • 若要让某个用户使用该别名,则把别名加在 ~/.bash_profile 或 ~/.bashrc 中。然后 source ~/.bashrc 或者 source ~/.bash_profile
    • 若要让每一位用户都使用该别名,则把别名加在 /etc/bashrc 或者 /etc/profile 中,然后source /etc/bashrc 或者 source /etc/profile

4.命令历史:

  • history 命令可以查阅命令历史记录 ,也可在命令行利用向上或向下光标键来进行查询

  • 语法:

    1
    2
    3
    history [选项] [num]
    例:
    history 5 # 查询前5次的命令记录
  • 选项:

    1
    2
    3
    4
    5
    number:显示最近number条命令历史 
    -c:清空当前历史命令
    -a [file]:后面没跟文件时,默认将缓冲区中历史命令写入~/.bash_history中
    -r [file]:将历史命令文件中的命令读入当前历史命令缓冲区中
    -w:将当前历史命令缓冲区命令写入历史命令文件中;

5.内部命令:

  • echo可在屏幕上输出信息

    echo参数选项 说明
    -n 不换行输出内容
    -e 解析转义字符
    1
    2
    [root@localhost ~]# echo -n i have a cat
    i have a cat[root@localhost ~]#
    转义字符 说明
    \n 换行
    \r 回车
    \t 制表符
    \b 退格
    \v 纵向制表符
    1
    2
    [root@localhost ~]# echo -e "i\thave\ta\tcat"
    i have a cat
  • eval:当shell程序执行到eval语句时,shell读入参数args,并将它们组合成一个新的命令,然后执行(以 ; 为分隔符换行输出数据)

    1
    2
    3
    4
    5
    6
    [root@localhost test]# a='shuju;head -1 /etc/passwd'
    [root@localhost test]# echo $a
    shuju;head -1 /etc/passwd
    [root@localhost test]# eval echo $a
    shuju
    root:x:0:0:root:/root:/bin/bash
  • exec:能够在不创建新的子进程的前提下,转去执行指定的命令,当指定的命令执行完毕后,该进程就终止了

  • export:设置或者显示环境变量

  • read:可从标准输入读取字符串等信息,传给shell程序内部定义的变量

    参数 说明
    p (prompt) 设置提示信息
    -t (timeout) 设置输入等待时间,单位默认为秒
    1
    2
    [root@localhost test]# read -t 10 -p "please input your name:" name
    please input your name:xiaoming
    1
    2
    3
    4
    5
    6
    7
    #读取两个输入(以空格隔开),分别赋值给name1和name2
    [root@localhost test]# echo -n "please input your name:";read name1 name2
    please input your name:xiaoming xiaohong
    [root@localhost test]# echo $name1
    xiaoming
    [root@localhost test]# echo $name2
    xiaohong
  • shift:在程序中每使用一次shift语句,都会使所有的位置参数依次向左移动一个位置,并使位置参数$#减1,直到减到0为止

  • exit:退出shell程序。在exit之后可以有选择地指定一个数作为返回状态

3.shell脚本入门:

1.编写规则:

  • 代码规范: 作用:指定告知系统当前这个脚本要使用的shell解释器

    1
    2
    #!/bin/bash 
    .......
  • 文件命名规范:文件名.sh .sh是linux下bash shell的默认后缀

  • 开头加版本特权等信息

    1
    2
    3
    4
    5
    # Date:创建日期
    # Author:作者
    # Mail:联系方式
    # Function:功能
    # Version:版本
  • 脚本中尽量不要用中文注释

  • 多使用内部命令

    1
    常用的内部命令有:echo、eval、exec、export、read、shift、exit

2.配置vim的编辑格式:

  • 针对单个用户:~/.vimrc

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    vim ~/.vimrc
    # 内容
    autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"

    func SetTitle()
    if expand("%:e") == 'sh'
    call setline(1,"#!/bin/bash")
    call setline(2,"#########################")
    call setline(3,"#File name:".expand("%"))
    call setline(4,"#Version:v1.0")
    call setline(5,"#Email:1095322098@qq.com")
    call setline(6,"#Created time:".strftime("%F %T"))
    call setline(7,"#Description:")
    call setline(8,"#########################")
    call setline(9,"")
    endif
    endfunc
    # 控制缩进格式为4个字符
    autocmd FileType sh setlocal ai ts=4 sw=4 et
  • 针对所有用户:/etc/./vimrc

2.注释:

  • 单行注释:

    1
    2
    #comment1
    #comment2
  • 多行注释:

    1
    2
    3
    :<<BLOCK
    ……注释内容
    BLOCK

3.使用流程:

  1. 创建一个.sh文件

    1
    touch test.sh
  2. 编写shell代码

    1
    vim test.sh
    1
    2
    #!/bin/bash 
    echo 'hello world!'
  3. 执行shell脚本(脚本必须有执行权限)

    1
    ./test.sh  # 相对路径执行
    1
    /usr/local/app/test.sh  # 绝对路径执行

4.执行脚本的方法:

  • 查看进程:

    1
    ps -ef | grep pts/4
  • 产生子进程,再运行,使用当前指定的bash shell去运行

    1
    bash ./filename.sh
  • 产生子进程,再运行,使用脚本里面指定的shell去运行。使用该种方式执行需要权限

    1
    ./filename.sh
  • (source命令是一个shell内部命令,其功能是读取指定的shell程序文件,并且依次执行其中的所有的语句,并没有创建新的子shell进程,所以脚本里面所有创建的变量都会保存到当前的shell里面

    1
    source ./filename.sh
  • 和source一样,也是使用当前进程执行

    1
    . filename.sh

5.shell脚本的退出状态:

  • 在UNIX或者Linux中,每个命令都会返回一个退出状态码。退出状态码是一个整数,其有效范围为0~255。

  • 通常情况下,成功的命令返回0,而不成功的命令返回非0值。非0值通常都被解释成一个错误码

  • Shell脚本中的函数和脚本本身也会返回退出状态码。

  • 在脚本或者是脚本函数中执行的最后的命令会决定退出状态码。

    1
    2
    ./test1.sh
    echo $?
  • 另外,用户也可以在脚本中使用exit语句将指定的退出状态码传递给Shell

    1
      

4.变量:

1.变量名的规范:

  • 注意,变量名后面的等号左右不能有空格,这可能和你熟悉的所有编程语言都不一样

  • 变量名的命名须遵循如下规则:

    • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。

    • 中间不能有空格,可以使用下划线“_”。

    • 不能使用标点符号。

    • 不能使用bash里的关键字(可用help命令查看保留关键字)。

  • 双引号能够识别变量;单引号是不能识别变量,只会原样输出

  • 双引号能够实现转义(类似于“*”);只会原样输出,单引号是不能转义

2.变量的类型:

  • 根据数据类型分类

    • Shell是一种动态类型语言和弱类型语言,即在Shell中,变量的数据类型毋需显示地声明,变量的数据类型会根据不同的操作有所变化。

    • 准确地讲,Shell中的变量是不分数据类型的,统一地按照字符串存储。

    • 但是根据变量的上下文环境,允许程序执行一些不同的操作,例如字符串的比较和整数的加减等等

    • 什么是弱类型语言、强类型语言:

      • 强类型语言,当你定义一个变量是某个类型,如果不经过代码显式转换(强制转化)过,它就永远都是这个类型
      • 弱类型语言,你想把这个变量当做什么类型来用,就当做什么类型来用,例:js中的var和let
    • declare命令还可输出所有的变量、函数、整数和已经导出的变量

      • 参数:

        参数 说明
        -p 显示所有变量的值
        -i 将变量定义为整数,在之后就可以直接对表达式求值,结果只能是整数。如果求值失败或者不是整数,就设置为0
        -r 将变量声明为只读变量。只读变量不允许修改,也不允许删除。(也可使用readonly定义只读变量)
        -a 变量声明为数组变量。但这没有必要,所有变量都不必显示定义就可以用作数组。事实上,在某种意义上,似乎所有变量都是数组,而且赋值给没有下标的变量与赋值给下标为0的数组元素相同
        -f 显示所有自定义函数,包括名称和函数体
        -x 将变量设置成环境变量。可使用+x将变量变成非环境变量
  • 根据作用域分类

    • 环境变量:

      • 自定义环境变量:
        • 一般是指用export内置命令导出的变量,用于定义shell的运行环境,保证shell命令的正确执行。环境变量可以在命令行中设置和创建,但用户退出命令行时这些变量值就会丢失,即该环境变量只在当前shell和子shell中有效。如果希望永久保存环境变量,可以在配置文件中设置

        • 自定义环境变量的配置文件

          1
          2
          3
          4
          # 用户的环境变量配置(non-login shell)
          ~/.bash_profile或~/.bashrc
          # 全局环境变量的配置(login shell)
          /etc/bashrc、/etc/profile文件或者/etc/profile.d目录中定义
        • 注意:按照系统规范,所有环境变量的名字均采用大写形式。在将环境变量应用于用户进程程序之前,都应该用命令export导出。

        • 有一些环境变量,比如HOME,PATH,SHELL,UID,USER等,在用户登录前就已经被/bin/login程序设置好了

        • 通常环境变量被定义并保存在用户家目录下的.bash_profile文件或全局的配置文件/etc/profile

      • bash内置的环境变量:
        • shell内置的环境变量是所有的shell程序都可以使用的变量。shell程序在运行时,都会接收一组变量来确定登录用户名、命令路径、终端类型、登录目录等,这组变量就是环境变量。环境变量会影响到所有的脚本的执行结果

        • 内置的环境变量:

          变量 说明
          PATH 命令搜索路径,以冒号为分隔符
          HOME 用户主目录的路径名,是cd命令的默认参数
          COLUMNS 定义了命令编辑模式下可使用命令行的长度
          HISTFILE 命令历史文件
          HISTSIZE 命令历史文件中最多可包含的命令条数
          HISTFILESIZE 命令历史文件中包含的最大行数
          IFS 定义shell使用的分隔符
          LOGNAME 当前的登录名
          SHELL shell的全路径名
          TERM 终端类型
          TMOUT shell自动退出的时间,单位为秒,若设为0则禁止shell自动退出
          PWD 当前工作目录
        • 注:可使用env查看环境变量

    • 普通变量:

      • 普通变量也可称为局部变量,与全局变量相比,局部变量的使用范围较小,通常仅限于某个程序段访问,例如函数内部。
      • 在Shell语言中,可以在函数内部通过local关键字定义局部变量,另外,函数的参数也是局部变量

3.变量的定义与使用:

  • 变量定义示例:变量名=变量值

    • 普通变量的定义:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      # 定义数值变量
      a=1
      # 定义字符串变量
      [变量]="yunsuanfu"
      # 定义备份路径
      bak_dir=/data/backup
      # 把一个命令的结果赋值变量
      变量名=`ls`
      变量名=$(ls)
    • 只读变量的定义

      1
      readonly a=10
    • 接受用户输入:

      1
      2
      read -p [提示信息] [变量名]
      # 例:read -p "请输入需要创建的文件路径:" filePath
    • 变量的删除:

      1
      unset [变量]
    • 将变量转换成环境变量

      1
      2
      3
      export mydata2=mydata2
      mydata=mydata;export mydata
      declare -x mydata3=mydata3
  • 位置参数和预定义变量:

    • 许多情况下,Shell脚本都需要接收用户的输入,根据用户输入的参数来执行不同的操作

    • 从命令行传递给Shell脚本的参数又称为位置参数,Shell脚本会根据参数的位置使用不同的位置参数变量读取它们的值:

      变量 说明
      $# 命令行参数的个数
      $n 表示传递给脚本的第n个参数,例如$1表示第一个参数,$2表示第二个参数,$3表示第三个参数
      $0 当前脚本的名称
      $* 以”参数1 参数2 参数3…”的形式返回所有参数的值
      $@ 以“参数1”“参数2”“参数3”…的形式返回所有的值
      $? 前一个命令或者函数的返回状态码
      $$ 返回本程序的进程ID(PID),不常用
      $! 获取上一个在后台工作的进程的进程号,不常用
      $_ 保存之前执行的命令的最后一个参数,不常用
    • 示例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      echo "第1个位置参数是$1"
      echo "第2个位置参数是$2"
      echo "所有参数是: $*"
      echo "所有参数是: $@"
      echo "参数的个数是: $#"
      echo "当前进程的PID是: $$"
      [root@localhost test]# bash param.sh shuju1 shuju2
      第1个位置参数是shuju1
      第2个位置参数是shuju2
      所有参数是: shuju1 shuju2
      所有参数是: shuju1 shuju2
      参数的个数是: 2
      当前进程的PID是: 23278
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      #!/bin/bash
      ping -c2 $1 &> /dev/null
      if [ $? = 0 ];then # $?为上一个命令或函数返回的状态码
      echo "host $1 is ok"
      else
      echo "host $1 is fail"
      fi
      [root@localhost test]# chmod a+rx ping.sh
      [root@localhost test]# ./ping.sh 192.168.168.128
      host 192.168.168.128 is ok
      1
      2
      3
      4
      5
      6
      [root@localhost test]# for i in "$*";do echo $i;done
      i have a cat
      [root@localhost test]# for i in "$@";do echo $i;done
      i have
      a
      cat
      1
      2
      3
      4
      5
      6
      [root@localhost test]# shift #使用该指令可将位置参数左移一位
      [root@localhost test]# echo $1
      a
      [root@localhost test]# shift
      [root@localhost test]# echo $1
      cat

4.shell中变量的引用:

  • 在bash中有很多特殊字符,这些特殊字符就具有特殊含义。引用就是通知shell将这些特殊字符当作普通字符来处理。

    符号 说明
    转义字符 “\” 如果将\放到特殊字符前面,shell就忽略这些特殊字符的原有含义,把它们当作普通字符对待
    单引号 如果将字符串放到一对单引号之间,那么字符串中所有字符的特殊含义被忽略
    双引号 双引号的引用与单引号基本相同,包含在双引号内的大部分特殊字符可以当作普通字符处理,但是仍然有一些特殊字符保留自己的特殊含义,比如”$“和“\”以及“ ` ”
    1
    2
    3
    4
    [root@localhost ~]# echo "current_user is: $USER"    # 双引号中的$没有被忽略
    current_user is: root
    [root@localhost ~]# echo 'current_user is: $USER' # 单引号中的$被忽略
    current_user is: $USER
  • 说明:反引号中的字符串将被解释为shell命令

    1
    2
    3
    4
    [root@localhost ~]# echo "current_user is: `whoami`"    # 双引号中的反引号字符串被解释为shell命令
    current_user is: root
    [root@localhost ~]# echo 'current_user is: `whoami`' # 单引号中的反引号字符串被忽略
    current_user is: `whoami`

4.1.转义符

转义字符 说明
\n 换行
\r 回车
\t 制表符
\b 退格
\v 纵向制表符
\f 换页符

6.变量的运算:

算数运算符 说明
+、- 、*、/、% 求和、差、乘积,商,余数
** 幂运算,例如3**3是求3的立方,即27
+=、-=、*=、/=、%= 例a+=1相当于a=a+1
++variable、–variable 先将变量variable的值加1,然后再赋给variable; 先将变量variable的值减1,然后再赋给variable
位运算符<<、>>
&、| ,~,^ 按位与:1和1为1,其他为0;按位或:只要有1即为1,否则为0;按位非;按位异或:相同为1
  • 条件表达式要放在方括号之间,并且要有空格

    1
    [$a  ==  $b]
  • 多原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如awk和expr , expr最常用

    运算命令 意义 说明
    (()) 用于整数运算的常用运算符 在(())中使用变量时可以去掉变量前的$符号
    let 用于整数运算 使用let命令可以执行一个或者多个算术表达式,其中的变量名毋需使用$符号
    expr 可用于整数运算 使用expr时,运算符及用于计算的数字左右都至少有一个空格
    bc 适合整数及小数运算
    $[] 用于整数运算
    awk 既可以整数也可以用于小数
    declare
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    num1=10
    num2=2
    echo "two bracket is $(($num1+$num2))" # (())用于整数运算的常用运算符
    let num3=$num1*$num2 # let用于整数运算
    echo "let is $num3"
    echo "expr is `expr $num1 \| $num2`" # expr可用于整数运算
    echo "square bracket is $[$num2**$num1]" # $[]用于整数运算
    declare -i num4=$num1/$num2 # declare -i定义整形变量,做运算
    echo "declare is $num4"
    echo -n "bc is ";echo "$num2 / $num1" | bc # bc:seq生成数字序列(这里是1~10),-s指定分隔符(这里是+)
    1
    awk 'BEGIN {print 2+3*2}'      # awk既可以整数也可以用于小数
  • expr是一款表达式计算工具,使用它能完成表达式的求值操作:(注意使用的是反引号)

    1
    2
    val='expr2 + 2'    
    num3=`expr \( 2 + 3 \) \* 4` # 使用expr在遇到除"+,-"之外,都需要加转义符"\"

7.${ }表达式:

表达式 说明
${parameter} 返回变量的内容
$