• 随堂练习 shell脚本(一)


    第一步:使用文本编辑器来创建文本文件

    第一行:必须包括shell 声明序列:#!

    示例:#!/bin/bash

    第二步:加执行权限

    给予执行权限,在命令行上指定脚本的绝对或相对路径

    第三步:运行脚本

    直接运行解释器,将脚本作为解释器程序的参数运行

    范例:第一个shell 脚本 hello world

    #!/bin/bash

    echo "Hello,world!"

    执行:

    bash hell.sh

    shell 脚本调试

    只检测脚本中的语法错误,但无法检查出命令错误,但不真正执行脚本

    bash -n /path/some_script.sh

    调试并执行

    bash  -x /path/some_script.sh

    cat -A test.sh

    #!/bin/bash

    echo line1$

    hostnam$
    cat > test.txt <<EOF $
    aaa$
    bbb$
    ccc$
    EOF $
    $
    echo line22$
    [root@centos8 scripts]#bash -n test.sh
    f1.sh: line 20: warning: here-document at line 14 delimited by end-of-file
    (wanted `EOF')

    总结:脚本错误常见的有三种

    1)语法错误。会导致后续的命令不继续执行,可以用bash -n 检查错误,提示的出错行数不一定是准确的

    2)命令错误。默认后续的命令还会继续执行,用bash -n 无法检查出来,可以使用 bash -x 进行观察

    3)逻辑错误。只能使用 bash -x 进行观察

    1,变量

    变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用,获取数据

    2,变量类型

    1)内置变量:如:PS1,PATH,UID,HOSTNAME,$$,BASHPID,PPID,$?,HISTSIZE

    2)用户自定义变量

    不同的变量存放的数据不同,决定了以下

      1)数据存储方式

      2)参与的运算

      3)表示的数据范围

    变量数据类型

      字符

      数值:整型,浮点型,bash不支持浮点数

    静态和动态语言

      1)静态编译语言:使用变量前,先声明变量类型,之后类型不能改变,在编译时检查,如:java,c

      2)动态编译语言:不用事先声明,可随时改变类型,如:bash,Python

    强类型和弱类型语言

      1)强类型语言:不同类型数据操作,必须经过强制转换才同一类型才能运算,如:java,c#,Python

      如:参考以下Python代码

        print('long'+10) 提示出错,不会自动转换类型

        print('long'+str(10)) 结果为long10,需要显示转换类型

      2)弱类型语言:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用。如:bash,php,JavaScript

    3,shell 中变量命名法则

    1)不能使用程序中的保留字:如 :if,for等

    2)只能使用数字,字母及下划线,且不能以数字开头,注意:不支持短横线“-”,和主机名相反

    3)见名知意,用英文单词命名,并体现出实际作用,不要用简写, 如:ATM

    4)统一命名规则:驼峰命名法;大驼峰 StudentName,小驼峰studentName

    5)变量名大写:STUDENT_NAME

    6)局部变量小写

    7)函数名小写

    4,变量的生效范围等标准划分变量类型

      1)普通变量:生效范围为当前shell 进程;对当前shell 之外的其它shell 进程,包括当前shell 的子shell 进程均无效

      2)环境变量:生效范围为当前shell 进程及其子进程

      3)本地变量:生效范围为当前shell 进程中某代码片断,通常指函数

    变量赋值

    name='value'

    value 可以是以下多种形式

    直接字串:name='root'

    变量引用:name='$USER'

    命令引用:name=`COMMAND`  或  name=$(COMMAND)

    注意:变量赋值是临时生效。当退出终端后,变量会自动删除,无法持久保存,脚本中的变量会随着脚本结束,也会自动删除

    变量引用:

    $name

    ${name}

    弱引用和强引用

    1)"$name" 弱引用,其中的变量引用会被替换为变量值

    2)'$name'  强引用,其中的变量引用不会被替换为变量值,而保持原字符串

    范例:变量的各种赋值方式和引用

    [root@centos8 ~]#TITLE='cto'
    [root@centos8 ~]#echo $TITLE
    cto
    [root@centos8 ~]#echo I am $TITLE
    I am cto
    [root@centos8 ~]#echo "I am $TITLE"
    I am cto
    [root@centos8 ~]#echo 'I am $TITLE'
    I am $TITLE
    [root@centos8 ~]#NAME=$USER
    [root@centos8 ~]#echo $NAME
    root
    [root@centos8 ~]#USER=`whoami`
    [root@centos8 ~]#echo $USER
    root

    [root@centos8 ~]#FILE=/etc/*
    [root@centos8 ~]#echo $FILE
    /etc/adjtime /etc/aliases /etc/alternatives /etc/anacrontab /etc/at.deny
    /etc/audit /etc/authselect /etc/autofs.conf /etc/autofs_ldap_auth.conf
    [root@centos8 ~]#seq 10
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [root@centos8 ~]#NUM=`seq 10`
    [root@centos8 ~]#echo $NUM
    1 2 3 4 5 6 7 8 9 10

    [root@centos8 ~]#NAMES="wang
    > zhang
    > zhao
    > li"
    [root@centos8 ~]#echo $NAMES
    wang zhang zhao li
    [root@centos8 ~]#echo "$NAMES"
    wang
    zhang
    zhao
    li

    范例:变量引用

    [root@centos8 data]#NAME=long
    [root@centos8 data]#AGE=20
    [root@centos8 data]#echo $NAME
    long
    [root@centos8 data]#echo $AGE
    20
    [root@centos8 data]#echo $NAME $AGE
    long 20
    [root@centos8 data]#echo $NAME$AGE
    long20
    [root@centos8 data]#echo $NAME_$AGE
    20

    [root@centos8 data]#echo ${NAME}_$AGE
    long_20

    范例:变量的间接赋值和引用

    [root@centos8 ~]#TITLE=cto
    [root@centos8 ~]#NAME=wang
    [root@centos8 ~]#TITLE=$NAME
    [root@centos8 ~]#echo $NAME
    wang
    [root@centos8 ~]#echo $TITLE
    wang
    [root@centos8 ~]#NAME=long
    [root@centos8 ~]#echo $NAME
    long
    [root@centos8 ~]#echo $TITLE
    wang

    范例:变量追加值

    [root@centos8 ~]#TITLE=CTO
    [root@centos8 ~]#TITLE+=:wang
    [root@centos8 ~]#echo $TITLE
    CTO:wang

    范例:利用变量实现动态命令

    [root@centos8 ~]#CMD=hostname
    [root@centos8 ~]#$CMD
    centos8.longwang.com

    显示已定义的所有变量:set

    删除变量:unset <name>

    [root@centos8 ~]#NAME=long

    [root@centos8 ~]#TITLE=ceo
    [root@centos8 ~]#echo $NAME $TITLE
    long ceo
    [root@centos8 ~]#unset NAME TITLE
    [root@centos8 ~]#echo $NAME $TITLE

    范例:显示系统信息

    #!/bin/bash
    #
    #********************************************************************
    #Author: xuanlv
    #QQ: 360956175
    #Date: 2020-06-15
    #FileName: system_info.sh
    #URL: http://www
    #Description: The test script
    #Copyright (C): 2020 All rights reserved
    #********************************************************************
    RED="E[1;31m"
    GREEN="echo -e E[1;32m"
    END="E[0m"
    $GREEN-----------------------Host systeminfo-----------------------$END
    echo -e "HOSTNAME: $RED`hostname`$END"
    echo -e "IPADDR: $RED`ifconfig eth0 |grep -Eo '([0-9]{1,3}.){3}[0-9]{1,3}' |head -n1`$END "
    echo -e "OSVERSION: $RED`cat /etc/redhat-release`$END"
    echo -e "KERNEL: $RED`uname -r`$END"
    echo -e "CPU: $RED`lscpu |grep 'Model name' |tr -s ' ' |cut -d: -f2`$END"
    echo -e "MEMORY: $RED`free -h |grep Mem |tr -s ' ' : |cut -d: -f2`$END"
    echo -e "DISK: $RED`lsblk |grep '^nv' |tr -s ' ' |cut -d " " -f4`$END"
    $GREEN------------------------------------------------------------$END

     5,环境变量

      1)可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量

      2)一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程

      3)一般只在系统配置文件中使用,在脚本中较少使用

    变量声明和赋值

    #声明并赋值
    export name=VALUE
    declare -x name=VALUE
    #或者分两步实现
    name=VALUE
    export name

    显示所有环节变量

    env

    printenv

    export

    declare -x

    bash 内建的环境变量

    PATH

    SHELL

    USER

    UID

    HOME

    PWD

    SHLVL  # shell 的嵌套层数,即深度

    LANG

    MAIL

    HOSTNAME

    HISTIZE

    _     # 下划线   表示前一个命令的最后一个参数

    只读变量:只能声明定义,但后续不能修改和删除,即常量

    声明只读变量:

    readonly  name

    declare  -r name

    查看只读变量

    readonly  [-p]

    declare  -r

    [root@centos8 ~]#readonly PI=3.14159
    [root@centos8 ~]#echo $PI
    3.14159
    [root@centos8 ~]#PI=3.14
    -bash: PI: readonly variable
    [root@centos8 ~]#unset PI
    -bash: unset: PI: cannot unset: readonly variable
    [root@centos8 ~]#echo $PI
    3.14159
    [root@centos8 ~]#exit
    logout

    6,位置变量

    位置变量:在bash shell 中内置的变量,在脚本代码中调用通过命令行传递给脚本的参数

    $1,$2,... 对应第1个,第2个等参数, shift [n]换位置

    $0  命令本身,包括路径

    $*  传递给脚本的所有参数,全部参数合为一个字符串

    $@  传递给脚本的所有参数,每个参数为独立字符串

    $#  传递给脚本的参数的个数

    注意:$@   $*   只在被双引号包起来的时候才会有差异

    清空所有位置变量

    set  --

    [root@centos8 ~]#cat /data/scripts/arg.sh
    #!/bin/bash
    #
    #********************************************************************
    #Author: xuanlv
    #QQ: 360956175
    #Date: 2020-06-20
    #FileName: arg.sh
    #URL: http://www.
    #Description: The test script
    #Copyright (C): 2020 All rights reserved
    #********************************************************************
    echo "1st arg is $1"
    echo "2st arg is $2"
    echo "3st arg is $3"
    echo "10st arg is ${10}"
    echo "11st arg is ${11}"
    echo "The number of arg is $#"
    echo "All args are $*"
    echo "All args are $@"

    echo "The scriptname is `basename $0`"

    [root@centos8 ~]#bash /data/scripts/arg.sh {a..z}
    1st arg is a
    2st arg is b
    3st arg is c
    10st arg is j
    11st arg is k
    The number of arg is 26
    All args are a b c d e f g h i j k l m n o p q r s t u v w x y z
    All args are a b c d e f g h i j k l m n o p q r s t u v w x y z
    The scriptname is arg.sh

    范例:删库跑路之命令rm的安全实现

    #!/bin/bash

    WARNING_COLOR="echo -e E[1;31m]"

    END="E[0m"

    DIR=/tmp/`date +%F_%H-%M-%S`

    mkdir $DIR

    mv $*  $DIR

    ${WARNING_COLOR}Move $* to $DIR $END

    [root@centos8 ~]#chmod a+x /data/scripts/rm.sh
    [root@centos8 ~]#alias rm='/data/scripts/rm.sh'
    [root@centos8 ~]#touch {1..10}.txt
    [root@centos8 ~]#rm *.txt
    Move 10.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt to /tmp/2020-
    06-20_15-15-28

    范例:$* 和$@ 的区别

    [root@centos8 scripts]#cat f1.sh
    #!/bin/bash
    echo "f1.sh:all args are $@"
    echo "f1.sh:all args are $*"
    ./file.sh "$*"
    [root@centos8 scripts]#cat f2.sh
    #!/bin/bash
    echo "f2.sh:all args are $@"
    echo "f2.sh:all args are $*"

    ./file.sh "$@"
    [root@centos8 scripts]#cat file.sh
    #!/bin/bash
    echo "file.sh:1st arg is $1"
    [root@centos8 scripts]#./f1.sh a b c
    f1.sh:all args are a b c
    f1.sh:all args are a b c
    file.sh:1st arg is a b c
    [root@centos8 scripts]#./f2.sh a b c
    f2.sh:all args are a b c
    f2.sh:all args are a b c
    file.sh:1st arg is a

    范例: 利用软链接实现同一个脚本不同功能

    [root@centos8 ~]#cat test.sh
    #!/bin/bash
    #********************************************************************
    echo $0
    [root@centos8 ~]#ln -s test.sh a.sh
    [root@centos8 ~]#ln -s test.sh b.sh
    [root@centos8 ~]#./a.sh
    ./a.sh
    [root@centos8 ~]#./b.sh
    ./b.sh

    7,退出状态码变量

    进程执行后,将使用变量$? 保存状态码的相关数字,不同的值反应成功或失败,

    $?  的值为 0           # 代表成功

    $?  的值是1 到 255   # 代表失败

    用户可以在脚本中使用以下命令自定义退出状态码

    exit  [n]

    注意:

    1)脚本中一旦遇到exit 命令,脚本会立即终止;终止退出状态取决于 exit 命令后的数字

    2)如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

    8,展开命令执行顺序

    把命令行分成单个命令词

    展开别名

    展开大括号的声明 {}

    展开波浪符声明 ~

    命令替换 $() 和 ``

    再次把命令行分成命令词

    展开文件通配*,?,[abc]等等

    准备I/O重定向 < ,>

    运行命令

    防止扩展

    反斜线 ()会使随后的字符按原意解释

    范例:

    echo Your cost: $5.00
    Your cost: $5.00

    加引号来防止扩展

    单引号(' ')防止所有扩展

    双引号(" ")也可防止扩展,但是以下情况例外:$(美元符号)

    变量扩展

    ``  :反引号,命令替换

      :反斜线,禁止单个字符扩展

    :叹号,历史命令替换

    脚本安全和 set

    $- 变量
    h:hashall,打开选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选
    项关闭
    i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的 shell。所谓的交互式shell,
    在脚本中,i选项是关闭的
    m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等
    B:braceexpand,大括号扩展
    H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!”返回上最近的
    一个历史命令,“!n”返回第 n 个历史命令

    范例:

    [root@centos8 ~]#echo $-
    himBHs
    [root@centos8 ~]#set +h
    [root@centos8 ~]#echo $-
    imBHs
    [root@centos8 ~]#hash
    -bash: hash: hashing disabled
    [root@centos8 ~]#echo {1..10}
    1 2 3 4 5 6 7 8 9 10
    [root@centos8 ~]#echo $-
    imBHs
    [root@centos8 ~]#set +B
    [root@centos8 ~]#echo $-
    imHs
    [root@centos8 ~]#echo {1..10}
    {1..10}

    set 命令实现脚本安全

    -u  :在扩展一个没有设置的变量时,显示错误信息,等同set -o  nounset

    -e  :如果一个命令返回一个非0 退出状态值(失败)就退出,等同 set -o errexit

    -o  :option 显示,打开或者关闭选项

      显示选项:set -o

      打开选项:set -o 选项

      关闭选项:set +o 选项

    -x  :当执行命令时,打印命令及其参数,类似 bash -x

    9,格式化输出 printf

    格式:printf "指定的格式"  "文本1" "文本2"...

     常用格式替换符

    替换符: 功能

    %s :字符串

    %f  :浮点格式

    %b :相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转义

    %c :ASCII字符,即显示对应参数的第一个字符

    %d,%i :十进制整数

    %o :八进制值

    %u :不带正负号的十进制值

    %x :十六进制值(a-f)

    %X :十六进制值(A-F)

    %% :表示% 本身

    说明:%s 中的数字代表此替换符中的输出字符宽度,不足补空格,默认是右对齐,%-10s表示10个字
    符宽,- 表示左对齐

    常用转义字符:

    转义符: 功能

    :警告字符,通常为ASCII 的BEL字符

    :后退

    :换页

    :换行

    :回车

    :水平制表符

    v :垂直制表符

      :表示 本身

    范例:

    [root@centos8 ~]#printf "%s " 1 2 3 4
    1
    2
    3
    4
    [root@centos8 ~]#printf "%s %s " 1 2 3 4
    1 2
    3 4

    [root@centos8 ~]#printf "%f " 1 2 3 4
    1.000000
    2.000000
    3.000000
    4.000000
    #.2f 表示保留两位小数
    [root@centos8 ~]#printf "%.2f " 1 2 3 4
    1.00
    2.00
    3.00
    4.00
    [root@centos8 ~]#printf "(%s)" 1 2 3 4;echo
    (1)(2)(3)(4)
    [root@centos8 ~]#printf " (%s) " 1 2 3 4;echo ""
    (1) (2) (3) (4)
    [root@centos8 ~]#printf "(%s) " 1 2 3 4
    (1)
    (2)
    (3)
    (4)
    [root@centos8 ~]#printf "%s %s " 1 2 3 4
    1 2
    3 4
    [root@centos8 ~]#printf "%s %s %s " 1 2 3 4
    1 2 3
    4

    #%-10s 表示宽度10个字符,左对齐

    [root@centos8 ~]#printf "%-10s %-10s %-4s %s " 姓名 性别 年龄 体重 小明 男 20 70小红 女 18 50

    姓名 性别 年龄 体重
    小明 男 20 70
    小红 女 18 50
    #将十进制的17转换成16进制数
    [root@centos8 ~]#printf "%X" 17
    11

    [root@centos8 ~]#
    #将十六进制C转换成十进制
    [root@centos8 ~]#printf "%d " 0xC
    12
    [root@centos8 ~]#VAR="welcome to dd";printf "33[1;31m%s33[0m " $VAR
    welcome
    to
    dd
    [root@centos8 ~]#VAR="welcome to dd";printf "33[1;31m%s33[0m " "$VAR"
    welcome to dd

  • 相关阅读:
    Java VS .NET:Java与.NET的特点对比
    .NET Core 快速入门教程
    System.Net.Mail.SmtpClient通过SSL/TLS协议发送邮件失败问题解决
    在CentOS 7上安装&配置PostgreSQL 12
    如何在团队中做好Code Review
    SonarQube部署及代码质量扫描入门教程
    Kafka集群部署指南
    ASP.NET Core 入门教程 10、ASP.NET Core 日志记录(NLog)入门
    ASP.NET Core 入门教程 9、ASP.NET Core 中间件(Middleware)入门
    ASP.NET Core 入门教程 8、ASP.NET Core + Entity Framework Core 数据访问入门
  • 原文地址:https://www.cnblogs.com/xuanlv-0413/p/13211162.html
Copyright © 2020-2023  润新知