zoukankan      html  css  js  c++  java
  • 1.8 linux基础(八)-shell脚本基础

    1.8 linux基础(八)-shell脚本基础

    1.8.1、创建shell脚本

    • 使用文本编辑器vim来创建文本文件
    • 第一行必须包括shell声明序列:#!(幻数)
    • #!/bin/bash
    • 添加注释,注释以#开头 (尽量不要用中文)

    1.8.2 脚本的执行方式

    • bash script-name.sh
    • /path/to/script-name.sh或者 ./script-name.sh 脚本需要有执行权限才行
    给脚本增加执行权限:
    chmod +x script-name.sh
    
    • source或. script-name
      • 注意:会将脚本中的变量值或函数返回值传递到父shell中,会在当前shell中执行加载脚本中的变量命令,而不是产生子shell去执行脚本。a,b都是产生子shell执行的脚步。
    [root@CentOS7 data]# cat source.sh
    #!/bin/bash 
    #
    name=10000 
    [root@CentOS7 data]# name=0 
    [root@CentOS7 data]# echo $name
    0
    [root@CentOS7 data]# sh source.sh
    [root@CentOS7 data]# echo $name 
    0
    [root@CentOS7 data]# . source.sh
    [root@CentOS7 data]# echo $name
    10000
    [root@CentOS7 data]# cat source2.sh
    echo $name
    [root@CentOS7 data]# . source2.sh
    10000 ##一个脚本调用另一个脚本的参数
    

    1.8.3、脚本规范

    脚本代码开头约定

    1、第一行一般为调用使用的语言

    2、程序名,避免更改文件名为无法找到正确的文件

    3、版本号

    4、更改后的时间

    5、作者相关信息

    6、该程序的作用,及注意事项

    7、最后是各版本的更新简要说明

    #!/bin/bash
    # ------------------------------------------
    # Filename: hello.sh
    # Revision: 1.1
    # Date: 2018/08/01
    # Author: zhu
    # Email: xxx@qq.com
    # Website: www.xxx.com
    # Description: This is the first script
    # ------------------------------------------
    # Copyright: 2018 zhu
    # License: GPL
    echo “hello world
    

    1.8.4 脚本调试

    检测脚本中的语法错误bash -n /path/to/some_script

    调试分步执行bash -x /path/to/some_scrip

    1.8.5 养成脚本编写的好习惯

    • 成对符号一次性打出来,然后退格在符号里添加内容,防止遗漏
    • []中括号,[[]]两端必须都有两个空格
    • 流程控制语句,一次性将格式这写完,在添加内容
    • 通过缩进让代码易读
    • 常规变量的字符串定义变量值应该加号,并且等号前后不能有空格,需要强引用的,用'',如果是命令的引用,则用双引号""
    • linux中的符号都是英文状态下的符号

    1.8.6 编写第一个脚本hello world

    [root@CentOS7 ~]# vim test1.sh
    [root@CentOS7 ~]# cat test1.sh
    #!/bin/bash
    
    # ------------------------------------------
    
    # Filename: test1.sh
    
    # Revision: 1.1
    
    # Date: 2018/08/01
    
    # Author: zhu
    
    # Email: 154760531@qq.com
    
    # Website: www.studylinux.net
    
    # Description: This is the first script
    
    # ------------------------------------------
    
    # Copyright: 2018 zhu
    
    # License: GPL
    
    echo "hello world"
    

    1.8.7 写一个脚本脚本/root/bin/systeminfo.sh,显示当前主机系统信息

    包括主机名, IPv4地址,操作系统版本,内核版本,CPU型号,内存大小,硬盘大小

    [root@CentOS7 ~]# cat /root/bin/systeminfo.sh
    #!/bin/bash 
    echo "OS_version is  `cat /etc/centos-release| grep -o "[0-9]+"|head -n1`"
    echo "Kernel_version is `uname -r`"
    echo "IPv4 is `ifconfig ens33|grep "cast"|tr -s ' ' |cut -d" " -f3`"
    echo "CPU_type is `lscpu |grep "Model name"|tr -s " " |cut -d: -f2`"
    echo "Memory Size is `cat /proc/meminfo |head -n1 |tr -d " "|cut -d: -f2`"
    lsblk|grep "^sd"|tr -s " "|cut -d " "  -f1,4`"
    echo "Hostname is $HOSTNAME"
    echo "My name is "$USER""
    

    1.8.8 变量

    • 变量:命名的内存空间

    • 数据存储方式:ASCII

      • 字符:110
      • 数值:110
    • 变量作用:

      • 1、数据存储格式
      • 2、参与的运算
      • 3、表示的数据范围
    • 变量类型:

      • 字符
      • 数值:整型、浮点型
    • 强类型:变量在使用前,必须事先声明,甚至还需要初始化

    • 弱类型:变量在使用前,不需要事先声明,参与运算会自动进行隐式类型转换。默认为字符形式,bash不支持浮点型。

    • 变量命名法则:

      • 1、不能使程序中的保留字:例如if, for
      • 2、只能使用数字、字母及下划线,且不能以数字开头
      • 3、见名知义
      • 4、统一命名规则:驼峰命名法
    • 根据变量的生效范围等标准划分下面变量类型:

    • 局部变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效

    • 环境(全局)变量:生效范围为当前shell进程及其子进程

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

    • 位置变量:$1, $2, ...来表示,用于让脚本在脚本代码中调用通过命令行传递给它 的参数

    • 特殊变量:$?, $0, $*, $@, $#,$$

    • $$:当前进程的PID

    • $!:执行上一个指令的PID

    1.8.8.1 局部变量

    • 变量赋值:name=‘value’
    • 可以使用引用value:
      • (1) 可以是直接字串; name=“root"
      • (2) 变量引用:name="$USER"
      • (3)命令引用:name=`COMMAND` name=$(COMMAND)
    • 变量引用:${name} $name
      • "":弱引用,其中的变量引用会被替换为变量值
      • '':强引用,其中的变量引用不会被替换为变量值,而保持原字符串
    • 显示已定义的所有变量:set
    • 删除变量:unset name

    1.8.8.2环境变量

    • 变量声明、赋值:
      • export name=VALUE
      • declare -x name=VALUE
    • 变量引用:$name, ${name}
    • 显示所有环境变量:
      • env
      • printenv
      • export
      • declare -x
    • 删除变量: unset name

    1.8.8.3 只读变量

    • 只读变量:只能声明,但不能修改和删除
    • 声明只读变量:
      • readonly name
      • declare -r name
    • 查看只读变量: readonly –p

    1.8.8.4 位置变量

    • 位置变量:在脚本代码中调用通过命令行传递给脚本的参数
    • $1, $2, ...:对应第1、第2等参数,
    • shift [n]换位置
    • $0: 命令本身
    • "$*":传递给脚本的所有参数,全部参数合为一个字符串,相当于"$1 $2 $3"
    • "$@": 传递给脚本的所有参数,会保留所有的内嵌在每个参数中的任何空白,将所有参数视为不同的独立字符串,相当于"$1" "$2" "$3"
    • $#: 传递给脚本的参数的个数
    • $@: 传递给脚本的所有参数
    • $*: 引用传递给脚本的所有参数,只在被双引号包起来的时候$*和$#才会有差异。
    • set -- 清空所有位置变量
    [root@CentOS7 ~]#  name=parent;{ echo "1:$name";name=son;echo "2:$name"; };echo "3:$name"
    1:parent  ## 花扩号在当前shell中执行,前后有空格,不开启子shell
    2:son
    3:son
    [root@CentOS7 ~]#  name=parent;(echo "1:$name";name=son;echo "2:$name");echo "3:$name"
    1:parent  ## 小括号在执行时,会开启子进程,子进程能拿到父进程的变量,子进程内变量赋值、内部命令将会影响子进程的环境,()执行完成后,子进程结束,不保留变量赋值。
    2:son
    3:parent
    

    1.8.9 $?命令执行状态返回值(退出状态)

    进程使用退出状态来报告成功或失败

    • 0 代表成功 1-255代表失败
    • $? 变量保存上一条命令执行状态返回值
    • 例如: ping -c1 -W1 hostdown &> /dev/null echo $?

    1.8.10 退出状态码

    • bash自定义退出状态码
    • exit [n]:自定义退出状态码
    • 注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命 令后面的数字 注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

    1.8.11 算术运算

    • bash中的算术运算:bash会对数字执行隐式的类型转换
    • 运算操作符:+, -, *, /, %取模(取余), **(乘方)
    • 实现算术运算:
    • (1) let var=算术表达式
    • (2) var=$[算术表达式]
    • (3) var=$((算术表达式))
    • (4) var=$(expr arg1 arg2 arg3 ...)
    • (5) declare –i var = 数值
    • (6) echo "算术表达式" | bc
    • 乘法符号有些场景中需要转义,如*
    • bash有内建的随机数生成器:$RANDOM(0-32767) echo $[$RANDOM%50] :0-49之间随机数
    • 增强型赋值: +=, -=, *=, /=, %=
    • let varOPERvalue
    • 例如:let count+=3 即count=count+3 自加3后自赋值
    • 自增,自减:
    • let var+=1
    • let var++
    • let var-=1
    • let var--

    1.8.12 逻辑运算

    • true, false
    • 1, 0
    • 与:
      • 1 与 1 = 1
      • 1 与 0 = 0
      • 0 与 1 = 0
      • 0 与 0 = 0
    • 或:
      • 1 或 1 = 1
      • 1 或 0 = 1
      • 0 或 1 = 1
      • 0 或 0 = 0
    • 非:
      • ! 1 = 0
      • ! 0 = 1
    • 短路运算
    • 短路与
      • 第一个为0,结果必定为0
      • 第一个为1,第二个必须要参与运算
    • 短路或
      • 第一个为1,结果必定为1
      • 第一个为0,第二个必须要参与运算
    • 异或:^
      • 异或的两个值,相同为假0,不同为真1

    1.8.13 条件测试

    • 判断某需求是否满足,需要由测试机制来实现
    • Note:专用的测试表达式需要由测试命令辅助完成测试过程
    • 评估布尔声明,以便用在条件性执行中
      • 若真,则返回0
      • 若假,则返回1

    1.8.14 测试命令

    • test EXPRESSION
    • [ EXPRESSION ]
    • [[ EXPRESSION ]]
    • 注意:EXPRESSION前后必须有空白字符

    1.8.15 bash的数值测试

    • 数值测试:
      • -gt 是否大于
      • -ge 是否大于等于
      • -eq 是否等于
      • -ne 是否不等于
      • -lt 是否小于
      • -le 是否小于等于

    1.8.16 bash的字符串测试

    • 字符串测试:
      • = 是否等于

      • > ascii码是否大于ascii码

      • < 是否小于

      • != 是否不等于

      • =~ 左侧字符串是否能够被右侧的PATTERN所匹配

      • 注意: 此表达式一般用于[[]]中;扩展的正则表达式,右侧的PATTERN不加引号

      • -z "STRING" 字符串是否为空,空为真,不空为假

      • -n "STRING" 字符串是否不空,不空为真,空为假

      • 注意:用于字符串比较时的用到的操作数都应该使用引号

    [root@CentOS7 ~]# var=abcdef;[[ "$var" = abc* ]] && echo 1 || echo 0
    1 ## [[  = ]] 支持通配符
    [root@CentOS7 ~]# var=abcdef;[[ "$var" = "abc*" ]] && echo 1 || echo 0
    0  ## 引号引起来的都视为是字符串
    [root@CentOS7 ~]# filename=a.conf;[[ "$filename" =~ .conf ]] && echo 1 || echo 0
    1 ## 正则表达式不加引号
    

    1.8.17 Bash的文件测试

    1.8.17.1 文件存在性测试

    • -a FILE:同-e
    • -e FILE: 文件存在性测试,存在为真,否则为假

    1.8.17.2 文件类别测试

    • -b FILE:是否存在且为块设备文件
    • -c FILE:是否存在且为字符设备文件
    • -d FILE:是否存在且为目录文件
    • -f FILE:是否存在且为普通文件
    • -h FILE 或 -L FILE:存在且为符号链接文件
    • -p FILE:是否存在且为命名管道文件
    • -S FILE:是否存在且为套接字文件

    1.8.17.2 Bash的文件权限测试

    • -r FILE:是否存在且可读
    • -w FILE: 是否存在且可写
    • -x FILE: 是否存在且可执行

    1.8.17.3 文件特殊权限测试:

    • -u FILE:是否存在且拥有suid权限
    • -g FILE:是否存在且拥有sgid权限
    • -k FILE:是否存在且拥有sticky权限

    1.8.17.4 Bash的文件属性测试

    • 文件大小测试:
    • -s FILE: 是否存在且非空

    1.8.17.5 文件是否打开:

    • -t fd: fd 文件描述符是否在某终端已经打开
    • -N FILE:文件自从上一次被读取之后是否被修改过
    • -O FILE:当前有效用户是否为文件属主
    • -G FILE:当前有效用户是否为文件属组

    1.8.17.6 Bash的文件属性测试

    • 双目测试:
      • FILE1 -ef FILE2: FILE1是否是FILE2的硬链接
      • FILE1 -nt FILE2: FILE1是否新于FILE2(mtime) - FILE1 -ot FILE2: FILE1是否旧于FILE2

    1.8.17.7 Bash的组合测试条件

    • 第一种方式:
      • COMMAND1 && COMMAND2 并且
      • COMMAND1 || COMMAND2 或者
      • ! COMMAND 非
      • 如:[[ -r FILE ]] && [[ -w FILE ]]
    • 第二种方式:
      • EXPRESSION1 -a EXPRESSION2 并且
      • EXPRESSION1 -o EXPRESSION2 或者
      • ! EXPRESSION 非
      • 必须使用测试命令进行
      • 示例:
    [root@CentOS7 ~]# [ -z "$HOSTNAME" -o $HOSTNAME == "CentOS7.5.zhu.com" ] && echo 1 || echo 0
    1
    [root@CentOS7 ~]#[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
    [root@CentOS7 ~]#[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
    # /etc/fstab
    # Created by anaconda on Wed Jul 18 17:26:27 2018
    

    1.8.18 使用read命令来接受输入

    • 使用read来把输入值分配给一个或多个shell变量
      • -p 指定要显示的提示
      • -s 静默输入,一般用于密码
      • -n N 指定输入的字符长度N
      • -d '字符' 输入结束符
      • -t N TIMEOUT为N秒
    • read 从标准输入中读取值,给每个单词分配一个变量 所有剩余单词都被分配给最后一个变量
    • read -p "Enter a filename:" FILE

    1.8.19 bash的配置文件

    • 按生效范围划分,存在两类:
    • 全局配置: /etc/profile /etc/profile.d/*.sh /etc/bashrc
    • 个人配置: ~/.bash_profile ~/.bashrc

    1.8.20 shell登录两种方式

    • 交互式登录:
    • (1)直接通过终端输入账号密码登录
    • (2)使用“su - UserName” 切换的用户
    • 执行顺序:/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
    • 非交互式登录:
    • (1)su UserName
    • (2)图形界面下打开的终端
    • (3)执行脚本
    • (4)任何其它的bash实例
    • 执行顺序: ~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh

    1.8.20.1 Profile类

    • profile类:为交互式登录的shell提供配置
      • 全局:/etc/profile, /etc/profile.d/*.sh

      • 个人:~/.bash_profile

      • 功用:

      • (1)用于定义环境变量

      • (2) 运行命令或脚本

    1.8.20.2 Bashrc类

    • bashrc类:为非交互式和交互式登录的shell提供配置
      • 全局:/etc/bashrc
      • 个人:~/.bashrc
      • 功用:
      • (1) 定义命令别名和函数
      • (2) 定义本地变量

    编辑配置文件生效

    • 修改profile和bashrc文件后需生效
    • 两种方法:
      • 1重新启动shell进程
      • 2 . 或source
        例: . ~/.bashrc
    • 让任意一个目录下的具有执行权限的脚本不用输入路径就可以执行。
    [root@CentOS7 scripts]# cat /etc/profile.d/zhu.sh
    PATH=.:$PATH
    [root@CentOS7 scripts]# . /etc/profile.d/zhu.sh
    [root@CentOS7 scripts]# yesorno.sh
    please input yes or no:y
    Your answer is YES.
    [root@CentOS7 scripts]# echo $PATH
    .:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
    tips:为了安全考虑,在生产中不建议这么做 
    

    1.8.21 Bash 退出任务

    • 保存在~/.bash_logout文件中(用户)
    • 在退出登录shell时运行
    • 用于创建自动备份
    • 清除临时文件

    1.8.22 $-变量

    • h:hashall,打开这个选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选项关闭
    • i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的 shell。所谓的交互式shell,在脚本中,i选项是关闭的(cat /etc/profile.d/vte.sh)
    • m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继 续,后台或者前台执行等。
    • B:braceexpand,大括号扩展
    • H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完 成,例如“!!”返回上最近的一个历史命令,“!n”返回第 n 个历史命令
  • 相关阅读:
    python的特点
    epoll理解(转)
    数据库存储过程、触发器、连接
    Mysql的四种隔离级别
    linux指令
    利用asyncio(支持异步io)和协程实现单线程同步
    ubuntu安装codeblocks
    临界区与互斥量区别
    单链表的简单操作
    hdu 5475 An easy problem(暴力 || 线段树区间单点更新)
  • 原文地址:https://www.cnblogs.com/huangsefeizhu/p/11505993.html
Copyright © 2011-2022 走看看