第十九章 shell 脚本的基础
(上课时间2021-07-13,笔记整理时间2021-07-24)
本节所讲内容:
19.1 shell 基本语法
19.2 SHELL 变量及运用
19.3 数学运算
19.4 实战-升级系统中的 java 版本到 1.8 版本
19.1 shell 基本语法
19.1.1 什么是 shell?
Shell 是一个命令解释器,它在操作系统的最外层,负责直接与用户进行对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出到屏幕反馈给用户。这种对话方式可以是交互式也可以是非交互式的。
我们所输入的命令计算机是不识别的,这时就需要一种程序来帮助我们进行翻译,变成计算机能识别的二进制程序,同时又把计算机生成的结果返回给我们。
当前终端使用的哪种 shell?
大多数 linux 发行版本默认 shell 使用的是 bash
19.1.2 什么是 SHELL 脚本?
shell 脚本:就是说我们把原来 linux 命令或语句放在一个文件中,然后通过这个程序文件去执行时,我们就说这个程序为 shell 脚本或 shell 程序;我们可以在脚本中输入一系列的命令以及相关的语法语句组合,比如变量,流程控制语句等,把他们有机结合起来就形成了一个功能强大的 shell 脚本。
[root@CentOS83 ~]# vim bash.sh #!/bin/bash #This is shell. echo "hello world" mkdir /tmp/test touch /tmp/test/test.txt echo 'shell test' > /tmp/test/test.txt注释: 1、!/bin/bash 作用:告诉脚本使用的是哪种命令解释器。如不指 shell,以当前 shell 作为执行的shell。
2、在 shell 中以#表示开头,整个行就被当作一个注释。执行时被忽略。
3、shell 程序一般以.sh 结尾
[root@CentOS83 ~]# chmod +x bash.sh #给bash.sh执行权限 [root@CentOS83 ~]# ./bash.sh #执行bash.sh hello world [root@CentOS83 ~]# cat /tmp/test/test.txt shell test创建 shell 程序的步骤:
第一步:创建一个包含命令和控制结构的文件。
第二步:修改这个文件的权限使它可以执行。 使用 chmod +x bash.sh
第三步:检测语法错误 bash -x abc.sh
第四步:执行 ./example
shell 脚本的执行通常有以下几种方式
1、/root/test.sh 或者 ./test.sh (当前路径下执行脚本的话要有执行权限 chmod +x bash.sh)
2、bash bash.sh 或 sh bash.sh (这种方式可以不对脚本文件添加执行权限)
3、source bash.sh (可以没有执行权限) . bash.sh
4、sh < bash.sh 或者 cat bash.sh |sh(bash)
19.2 SHELL 变量及运用
19.2.1 shell 变量
变量是 shell 传递数据的一种方法。变量是用来代表每个值的符号名。我们可以把变量当成一个容器,通过变量,可以在内存中存储数据。也可以在脚本执行中进行修改和访问存储的数据变量的设置规则;
1.变量名称通常是大写字母,它可以由数字、字母(大小写)和下划线_组成。变量名区分大小写;但是大家要注意变量名称不能以数字开头;
2.等号 = 用于为变量分配值,在使用过程中等号两边不能有空格;
3.变量存储的数据类型是整数值和字符串值;
4.在对变量赋于字符串值时,建议大家用引号将其括起来。因为如果字符串中存在空格符号。需要使用单引号或双引号;
5.要对变量进行调用,可以在变量名称前加美元符号$;
6.如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含“$变量名”或用${变量名}包含;
变量的分类
按照变量的作用可以分成 4 类:
1、用户自定义变量
2、环境变量:这种变量中主要保存的是和系统操作环境相关的数据。
3、位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的。
$1 $2 …
4、预定义变量:是 Bash 中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
按照变量作用域可以分成 2 类:全局变量和局部变量。
局部变量是 shell 程序内部定义的,其使用范围仅限于定义它的程序,对其它程序不可见。包括:用户自定义变量、位置变量和预定义变量。
全局变量是环境变量,其值不随 shell 脚本的执行结束而消失。
19.2.2 用户定义变量
变量名命名规则:由字母或下划线打头,不允许数字开头,后面由字母、数字或下划线组成,并且大小写字母意义不同。在使用变量时,在变量名前加$
[root@CentOS83 ~]# var1=112233 #给 var1 赋值 [root@CentOS83 ~]# echo $var1 #读取 var1 变量 112233 variable [ˈveəriəbl] 变量错误的赋值方式,不允许数字开头,等号两边不能有空格
变量值的叠加,使用${}
$name 是${name}的简化版本,但是在某些情况下,还必须使用花括号引起的方式来消除歧义并避免意外的结果;
[root@CentOS83 ~]# var2=mysql [root@CentOS83 ~]# echo $var2 mysql [root@CentOS83 ~]# echo $var2.db.log mysql.db.log [root@CentOS83 ~]# echo $var2-db.log mysql-db.log [root@CentOS83 ~]# echo $var2db.log #想输出mysqldb.log 发现输出的结果不是我们想要的 [root@CentOS83 ~]# echo ${var2}db.log mysqldb.log19.2.3 命令的替换,使用$()或反引号
在命令中调用 date 命令输出值
[root@CentOS83 ~]# echo `date` Sat Jul 24 14:52:17 CST 2021 [root@CentOS83 ~]# echo $(date) Sat Jul 24 14:52:33 CST 2021 [root@CentOS83 ~]# echo `date +"%Y-%m-%d"` #输出当前日期 2021-07-24 [root@CentOS83 ~]# echo `date +%F` #输出当前日期 2021-07-24 [root@CentOS83 ~]# echo $(date +%F) #输出当前日期 2021-07-24分享一个系统时间错误,引起 tar 报警告
[root@CentOS83 ~]# tar czvf bash.tar.gz /root/bash.sh && tar xvf bash.tar.gz -C /opt/ tar: Removing leading `/' from member names /root/bash.sh root/bash.sh tar: root/bash.sh: time stamp 2021-07-24 14:35:31 is 12340954.851104013 s in the future注: 如果弹出这个消息,是因为咱们的当前系统的时间不对。 比如:当前系统的时间晚于文件的mtime 时间
[root@CentOS83 ~]# hwclock -s [root@CentOS83 ~]# date Sat Jul 24 15:04:24 CST 202119.2.5 shell 中单引号和双引号区别
‘’ 在单引号中所有的字符包括特殊字符($,'',和\)都将解释成字符本身而成为普通字符(所见即所得)。
“” 在双引号中,除了$, '', `反引号和\以外所有的字符都解释成字符本身,拥有“调用变量的值”、“引用命令”和“转义符”的特殊含义;
注:\转义符,跟在\之后的特殊符号将失去特殊含义,变为普通字符。如$将输出“$”符号,而不当 做是变量引用;
[root@CentOS83 ~]# var3='Hello word' #给变量值赋于多个单词,需要使用单引号和双引号 [root@CentOS83 ~]# echo $var3 Hello word [root@CentOS83 ~]# var3='Hello Word $var1' #双引中$符号没有作用 [root@CentOS83 ~]# echo $var3 Hello Word $var1 [root@CentOS83 ~]# var4="Hello Word $var1" #双引中$符号有作用 [root@CentOS83 ~]# echo $var4 Hello Word 112233单引号之间的内容原封不动赋值给变量, 双引号之间的内容如有特殊符号会保留它的特殊含义
[root@CentOS83 ~]# vim var.sh #!/bin/bash var=88 echo "$var" echo '$var' echo "'$var'" echo '"$var"' [root@CentOS83 ~]# ./var.sh 88 $var '88' "$var" [root@CentOS83 ~]# unset var1 #删除变量 [root@CentOS83 ~]# echo $var1当单独使用双引号时,可以取出变量值
当单独使用单引号时,不能取出变量值
当外层使用双引号时,输出内层的单引号和变量值
当外层使用单引号时,输出内层的双引号和双引号中的内容。
19.2.6 环境变量
在 bash shell 中,变量分为两类:全局变量和局部变量
全局变量:对于 shell 会话和所有的子 shell 都是可见的
局部变量: 它只在自己的进程当中使用
局部变量
[root@CentOS83 ~]# var1=1100 [root@CentOS83 ~]# var2=2200 [root@CentOS83 ~]# echo $var1 1100 [root@CentOS83 ~]# echo $var2 2200 [root@CentOS83 ~]# echo $var1 $var2 1100 2200使用 export 把这个 var1 局部变量输出为全局变量
[root@CentOS83 ~]# export var1=mygod [root@CentOS83 ~]# echo $var1 $var2 mygod 2200 [root@CentOS83 ~]# cat test.sh #!/bin/bash echo $var1 echo $var2 [root@CentOS83 ~]# bash test.sh #引用全局变量 var1 成功 mygodenv 环境变量 全局变量
让变量永久生效,可以把定义好的变量写入配置文件当登录系统或新开启一个 ssh 连接启动 bash 进程时,一定会加载这 4 个配置文件:
[root@CentOS83 ~]# vim /etc/profile #系统全局环境和登录系统的一些配置 [root@CentOS83 ~]# vim /etc/bashrc #bash 全局自义配置文件,用于自定义 shell [root@CentOS83 ~]# vim /root/.bashrc #用于单独自定义某个用户的 bash [root@CentOS83 ~]# vim /root/.bash_profile #用户单独自定义某个用户的系统环境下面开始插入永久变量:
[root@CentOS83 ~]# vim /etc/profile #在文件的最后插入 export var1=Linux_shell #=等号两边不能有空格 [root@CentOS83 ~]# source /etc/profile #重新加载 profile 文如何知道新建一个 ssh 连接,加载这 4 个配置文件先后顺序。
[root@CentOS83 ~]# echo 'echo /etc/profile ' >> /etc/profile [root@CentOS83 ~]# echo 'echo /etc/bashrc' >> /etc/bashrc [root@CentOS83 ~]# echo 'echo /root/.bashrc ' >> /root/.bashrc [root@CentOS83 ~]# echo 'echo /root/.bash_profile ' >> /root/.bash_profile [root@CentOS83 ~]# ssh root@10.170.80.83 /etc/bashrc /etc/profile /etc/bashrc /root/.bashrc #这个文件会判断/etc/bashrc 是否存在,存在则激活 /root/.bash_profile19.2.7 设置 PATH 环境变量
SHELL 要执行某一个程序,它要在系统中去搜索这个程序的路径,PATH 变量是用来定义命令和查找命令的目录,当我们安装了第三方程序后,可以把第三方程序 bin 目录添加到这个 path 路径内,就可以在全局调用这个第三方程序了。
[root@CentOS83 ~]# vim /opt/backup [root@CentOS83 ~]# chmod +x /opt/backup [root@CentOS83 ~]#backup bash: backup: 未找到命令... [root@CentOS83 ~]# echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin [root@CentOS83 ~]# PATH=/opt/:$PATH [root@CentOS83 ~]# backup #发现命令可以直接执行了,不用写全路径了 Backup datais OK! [root@CentOS83 ~]# vim /etc/profile #在文件最后追加以下内容,永久生效 [root@CentOS83 ~]# source /etc/profile #重新加载配置文件,使用配置生效 /etc/bashrc /etc/profile19.2.8 shell 位置变量
Shell 解释执行用户的命令时,将命令行的第一个字符作为命令名,而其它字符作为参数。
$0 获取当前执行 shell 脚本文件的文件名,包括脚本路径,命令本身
$n 获取当前脚本的第 n 个参数 n=1,2.....n 当 n 大于 9 时 用${10}表示。
[root@CentOS83 ~]# vim print.sh #!/bin/bash echo "本 shell 脚本的文件名: $0" echo "第 1 个参数: $1" echo "第 2 个参数: $2" echo "第 3 个参数: $3" echo "第 4 个参数: $4" [root@CentOS83 ~]# chmod +x print.sh [root@CentOS83 ~]# ./print.sh 1100 2200 test.txt 4400 本 shell 脚本的文件名: ./print.sh 第 1 个参数: 1100 第 2 个参数: 2200 第 3 个参数: test.txt 第 4 个参数: 4400使用场景:服务器启动传参数
[root@CentOS83 ~]# /etc/init.d/network restart19.2.9 特殊变量(预定义变量)
有些变量是一开始执行 Script 脚本时就会设定,且不能被修改,但我们不叫它只读的系统变量,而叫它特殊变量。这些变量当执行程序时就有了,以下是一些特殊变量:
符号 定义 $* 以一个单字符串显示所有向脚本传递的参数;如"$*"用【"】括起来的情况、以"$1 $2 … $n"的形式输出所有参数 $# 传递到脚本的参数个数 $$ 当前进程的进程号 PID 脚本运行的当前 进程 ID 号 $? 显示最后命令的退出状态;0 表示没有错误,其他任何值表明有错误 $! 后台运行的最后一个进程的进程号 pid [root@CentOS83 ~]# vim test_var.sh [root@CentOS83 ~]# cat test_var.sh #!/bin/bash echo "$* 一个字符串显示这个程序的所有参数" echo "$# 表示这个程序的参数个数" touch /tmp/test_a.txt echo "$$ 表示当前进程的进程号 PID" touch /tmp/test_b.txt & echo "$! 表示上一个后台运行的进程的 PID" echo "$? 表示上一个程序执行返回结果" [root@CentOS83 ~]# bash test_var.sh 1 2 3 4 5 1 2 3 4 5 一个字符串显示这个程序的所有参数 5 表示这个程序的参数个数 1738 表示当前进程的进程号 PID 1740 表示上一个后台运行的进程的 PID 0 表示上一个程序执行返回结果常用的环境变量
[root@CentOS83 opt]# cat /env.sh #!/bin/bash echo \$HOME 变量值是$HOME echo \$PATH 变量值是$PATH echo \$PWD 变量值是$PWD [root@CentOS83 opt]# bash env.sh $HOME 变量值是/root $PATH 变量值是/opt/:/opt/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin $PWD 变量值是/optdeclare 声明变量类型
declare [+/-] [选项] 变量名
-: 给变量设定类型属性
+: 取消给变量设定类型属性
-i 将变量声明为整数型
-x 将变量声明为环境变量 等同于 exprot
-r 将变量声明为只读变量
-p 显示指定变量的被声明类型
[root@CentOS83 ~]# declare -i num [root@CentOS83 ~]# num=1 [root@CentOS83 ~]# echo $num 1 [root@CentOS83 ~]# num=abc [root@CentOS83 ~]# echo $sum [root@CentOS83 ~]# declare +i num [root@CentOS83 ~]# num=abc [root@CentOS83 ~]# echo $num abc [root@CentOS83 ~]# a=123 [root@CentOS83 ~]# b=456 [root@CentOS83 ~]# c=$a+$b [root@CentOS83 ~]# echo $c 123+456 [root@CentOS83 ~]# declare -i c=$a+$b [root@CentOS83 ~]# echo $c 579 [root@CentOS83 ~]# declare -x abc [root@CentOS83 ~]# abc=123 [root@CentOS83 ~]# env | grep abc abc=12319.3 数学运算
19.3.1 expr 命令
(1)对数字的基本计算,做比较时,输出结果假为 0,1 为真;特殊符号用转义符
[root@CentOS83 ~]# expr 2 \> 5 0 [root@CentOS83 ~]# expr 6 \> 5 1 [root@CentOS83 ~]# expr 3*5 # 想算出3*5 3*5 [root@CentOS83 ~]# expr 3 \* 5 # \* 前后有空格 15 [root@CentOS83 ~]# expr 3 \+ 5 # \* 前后有空格 8(2)对字符串的处理
[root@CentOS83 ~]# expr length "Hello expr" 10 [root@CentOS83 ~]# expr substr "Hello expr" 2 7 #从第 2 个开始,截取7个字符出来 ello ex字符串提取 第一种模式:${var:num},这种模式时,shell 在 var 中提取第 n 个字符到末尾的所有字符。若 n为正数,从左边 0 处开始;若 n 为负数,从右边开始提取字串,但必须使用在冒号后面加空格或整个 n加上小括号,如${var: -2}、${var:(-2)}。
[root@CentOS83 ~]# var=http://www.mygod.cn/index.htm [root@CentOS83 ~]# echo ${var:5} //www.mygod.cn/index.htm [root@CentOS83 ~]# echo ${var:(-5)} x.htm [root@CentOS83 ~]# echo ${var: -5} x.htm第二种模式:${var:n1:n2},n1 是位置,n2 是长度。表示从$var 字符串的第$n1 个位置开始提取长度为$n2 的子串。不能为负数。
[root@CentOS83 ~]# echo ${var:0:5} http: [root@CentOS83 ~]# echo ${var:1:5} ttp:/ [root@CentOS83 ~]# echo ${var:7:13} www.mygod.cn/ [root@CentOS83 ~]#字符串替换: 第一种模式:${var/pattern/pattern}表示将 var 字符串的第一个匹配的 pattern 替换为另一个pattern。
[root@CentOS83 ~]# echo ${var/cn/com} #把cn替换成.com http://www.mygod.com/index.htm第二种模式:${var//pattern/pattern}表示将 var 字符串中的所有能匹配的 pattern 替换为另一个pattern。
[root@CentOS83 ~]# echo ${var/w/opt} #把w替换成opt http://optww.mygod.cn/index.htm [root@CentOS83 ~]# echo ${var/w/o} #把w替换成o http://oww.mygod.cn/index.htm% 是去掉右边,最小匹配
${variable%pattern},这种模式时,shell 在 variable 中查找,看它是否符合 pattern,如果是, 就把 variable 中的内容去掉右边最小的匹配
[root@CentOS83 ~]# echo ${var%/*m} http://www.mygod.cn%% 是去掉右边,最大匹配
${variable%%pattern},这种模式时,shell 在 variable 中查找,看它是否符合 pattern,如果 是,就把 variable 中的内容去掉右边最大的匹配
[root@CentOS83 ~]# echo ${var%/*m} http://www.mygod.cn [root@CentOS83 ~]# echo ${var%%/*m} http: [root@CentOS83 ~]# echo ${var%w*m} #最短匹配 http://ww [root@CentOS83 ~]# echo ${var%%w*m} #最长匹配 http:// [root@CentOS83 ~]# echo ${var#*w} # 是去掉左边,最小匹配 ww.mygod.cn/index.htm [root@CentOS83 ~]# echo ${var##*w} # 是去掉左边,最大匹配 http://www.mygod.cn/index.htm [root@CentOS83 ~]# echo ${var#*/} /www.mygod.cn/index.htm [root@CentOS83 ~]# echo ${var##*/} index.htm如何取中间的www.mygod.cn ?
[root@CentOS83 ~]# a=${var#*//} [root@CentOS83 ~]# echo $a www.mygod.cn/index.htm [root@CentOS83 ~]# a=${a%/*} [root@CentOS83 ~]# echo $a www.mygod.cn19.3.2 $(( ))应用
格式:$((表达式 1,表达 2))
特点:
1、在双括号结构中,所有表达式可以像 c 语言一样,如:a++,b--等。a++ 等价于 a=a+1
2、在双括号结构中,所有变量可以不加入:“$”符号前缀。
3、双括号可以进行逻辑运算,四则运算
4、双括号结构 扩展了 for,while,if 条件测试运算
5、支持多个表达式运算,各个表达式之间用“,”分开
常用的算数运算符
运算符 意义
运算符 意义 ++ -- 递增及递减,可前置也可以后置 + - ! ~ 一元运算的正负号 逻辑与取反 + - * / % 加减乘除与余数 < <= > >= 比较大小符号 == != 相等 不相等 >> << 向左位移 向右位移 & ^ | 按位的与 按位的异或 按位的或 && || 逻辑与 逻辑或 ? : 条件判断 [root@CentOS83 ~]# b=$((1+2)) [root@CentOS83 ~]# echo $b 3 [root@CentOS83 ~]# echo $((2*3)) 6 [root@CentOS83 ~]# echo $((++b)) #递增和递减 4说明: a++或 a--为先赋值再+1 或减 1 ; ++a 或--a 为先加 1 或减 1,然后再进行赋值
[root@CentOS83 ~]# for i in {1..10}; do echo $((++a)); done; [root@CentOS83 ~]# for i in {1..10}; do echo $((a++)); done; [root@CentOS83 ~]# a=1;b= [root@CentOS83 ~]# echo $a,$b 1, [root@CentOS83 ~]# ((a=a+b,b=a,c=4*5)) [root@CentOS83 ~]# echo $a,$b,$c 1,1,2019.4 实战-升级系统中的 java 版本到 1.8 版本
19.4.1 安装 jdk java 运行环境
[root@CentOS83 ~]# rpm -ivh jdk-8u231-linux-x64.rpm #通过查看 jdk 的信息可以知道 jdk的安装目录在/usr/java [root@CentOS83 ~]# rpm -qpi jdk-8u231-linux-x64.rpm [root@CentOS83 ~]# vim /etc/profile #在文件的最后添加以下内容: export JAVA_HOME=/usr/java/jdk1.8.0_231-amd64 export JAVA_BIN=${JAVA_HOME}/bin export PATH=${JAVA_BIN}:$PATH export CLASSPATH=.:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar [root@CentOS83 ~]# source /etc/profile #使配置文件生效 [root@CentOS83 ~]# env | grep jav [root@CentOS83 ~]# java -version #验证 java 运行环境是否安装成功 java version "1.8.0_231" Java(TM) SE Runtime Environment (build 1.8.0_231-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)如果出现安装的对应版本,说明 java 运行环境已经安装成功。
注:这里只是升级了 jdk 的版本,因为在我安装的系统中已经安装了 jdk。
总结:
19.1 shell 基本语法
19.2 SHELL 变量及运用
19.3 数学运算
19.4 实战-升级系统中的 java 版本到 1.8 版本
【本文由:阿里云代理 http://www.56aliyun.com欢迎留下您的宝贵建议】