shell开发
在前面,超哥已经带着大家,学习了linux系统命令操作,为了提升运维效率,我们得学习shell脚本开发。
使用多个命令
shell脚本的关键是在于处理多个命令,且处理每个命令的结果,或者将不同的命令结果进行传递,再次加工。
shell支持多个命令连接起来执行。
[root@web01 ~]# clear
[root@web01 ~]# date;whoami
Sun Sep 27 17:57:45 CST 2020
root
恭喜你,铁子,你已经会了第一个shell脚本。这个脚本简单到只有2个命令,这种形式,命令少还好说,如果命令较长,较多,那就很难在命令行敲打了。
我们可以把命令组合成一个文本文件,然后执行这个文件即可。
shell脚本文件
shell脚本文件,第一行必须指定想要用的shell。
#!/bin/bash
shell脚本里,#号
是注释行,shell不会处理脚本中的注释行,然而第一行例外,该写法会通知shell用哪个解释器来运行脚本。
shell脚本中可以书写你想要执行的命令,且可以添加注释行。
[root@web01 ~]# cat test.sh
#!/bin/bash
# This is test script
date
whoami
echo "It's Over."
执行脚本
用解释器读取脚本
[root@web01 ~]# sh test.sh
Mon Sep 28 09:34:28 CST 2020
root
It's Over.
[root@web01 ~]# bash test.sh
Mon Sep 28 09:34:36 CST 2020
root
It's Over.
直接运行文件,需要赋予权限
[root@web01 ~]# ./test.sh
-bash: ./test.sh: Permission denied
[root@web01 ~]# ll test.sh
-rw-r--r-- 1 root root 64 Sep 28 09:34 test.sh
[root@web01 ~]# chmod +x test.sh
[root@web01 ~]#
[root@web01 ~]# ll test.sh
-rwxr-xr-x 1 root root 64 Sep 28 09:34 test.sh
# 执行
[root@web01 ~]# ./test.sh
Mon Sep 28 09:35:35 CST 2020
root
It's Over.
当以./test.sh
该形式执行脚本,则以文件第一行的shebang
指定的解释器执行文件。
常用echo
在shell脚本里,shell命令会有自己的输出,若是你想要自定义内容打印,以告知用户,当前脚本在做什么事。
可以通过echo命令来实现,注意单引号
、双引号
。
[root@web01 ~]# cat test.sh
#!/bin/bash
# This script displays the date and who's logged on
echo "The time and date are:"
date
echo ''
echo "Let's see who's logged into the system:"
who
[root@web01 ~]# ./test.sh
The time and date are:
Mon Sep 28 09:45:20 CST 2020
Let's see who's logged into the system:
root tty1 2020-09-27 11:01
root pts/0 2020-09-27 17:57 (10.0.1.1)
使用变量与echo
脚本里,可以在环境变量名称前加上$
来使用环境变量。
[root@web01 ~]# cat test.sh
#!/bin/bash
# display user information from the system
echo "User info for userid: $USER"
echo UID: $UID
echo HOME: $HOME
[root@web01 ~]# ./test.sh
User info for userid: root
UID: 0
HOME: /root
转义符
当一些情况,我们不希望shell解析一些符号,可以使用单引号
和转义符
对符号不做解析。
echo识别变量的情况
[root@web01 ~]# echo "The cost of the item is $15"
The cost of the item is 5
这显然不是超哥想要的,改成如下写法
[root@web01 ~]# echo ' The cost of the item is $15'
The cost of the item is $15
方法二
[root@web01 ~]# echo "The cost of the item is \$15"
The cost of the item is $15
现在允许shell解读$
只是一个普通的美元符了。
变量应用
[root@web01 ~]# cat test.sh
#!/bin/bash
# test variables
days=10
guest="超哥"
echo "$guest checked in $days days ago"
[root@web01 ~]# ./test.sh
超哥 checked in 10 days ago
变量被引用时会输出赋予给它的值,变量会在shell脚本退出后消失。
变量再赋值
变量每次被引用的时候,都会输出赋予的值,需要加上$
符
[root@web01 ~]#
[root@web01 ~]# cat test.sh
#!/bin/bash
# assigning a variable value to another variable
value1=10
value2=$value1
echo "The resulting value is $value2"
[root@web01 ~]# ./test.sh
The resulting value is 10
[root@web01 ~]#
若是忘记用美元符,则结果就错误了。
[root@web01 ~]# cat test.sh
#!/bin/bash
# assigning a variable value to another variable
value1=10
value2=value1
echo "The resulting value is $value2"
[root@web01 ~]#
[root@web01 ~]#
[root@web01 ~]# ./test.sh
The resulting value is value1
命令替换
shell一大特性就是可以从命令中提取结果,再赋予给变量,这样处理脚本数据特别方便。
有两个方式将命令输出赋予给变量
反引号 ``
$() 格式
来看超哥的用法
[root@web01 ~]# cat test.sh
#!/bin/bash
testing=$(date)
echo "The date and time are:" $testing
# 结果
[root@web01 ~]# ./test.sh
The date and time are: Mon Sep 28 10:31:39 CST 2020
再来看案例
[root@web01 ~]# cat test.sh
#!/bin/bash
# copy the /usr/bin directory listing to a log file
today=$(date +%y%m%d)
ls /usr/bin -al > log.$today
today变量是取出命令的值,也就是提取了日期,然后在结合到文件名里使用
[root@web01 ~]# ./test.sh
[root@web01 ~]# cat log.200928 |wc -l
1240
反引号
反引号和$()的作用相同,用于命令替换(command substitution),即完成引用的命令的执行,将其结果替换出来,与变量替换差不多。比如:
[root@web01 ~]# echo `date '--date=1 hour ago' +%Y-%m-%d-%H`
2020-09-28-10
等同于
[root@web01 ~]# echo $(date '--date=1 hour ago' +%Y-%m-%d-%H)
2020-09-28-10
Josen的总结
反引号`` 替换、代表了命令执行的结果,效果与$()相同
单引号'' 强引用,单引号里面的内容不会被解析,例如echo '我爱淑宜'
双引号"" 弱引用,能解析出里面的各种符号,可加反斜杠\,不被解析;
常和 `` 一起使用,如echo "`ls`"
常和 $() 一起使用,如echo "$(ls)"
${变量名} 输出变量内容
$变量名 输出变量内容,但遇到空格容易出错
数值计算
编程语言都支持数字计算,但是对于shell来说,数值计算稍微麻烦点。
算数运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SCFmLePB-1678232171867)(http://book.luffycity.com/linux-book/shell%E5%BC%80%E5%8F%91/pic/image-20210308143733046.png)]
运算符命令
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tgGiPs0s-1678232171871)(http://book.luffycity.com/linux-book/shell%E5%BC%80%E5%8F%91/pic/image-20210308143808429.png)]
Shell if参数
shell 编程中使用到得if语句内判断参数
–b 当file存在并且是块文件时返回true
-c 当file存在并且是字符文件时返回true
-d 当pathname存在并且是一个目录时返回true
-e 当pathname指定的文件或目录存在时返回true
-f 当file存在并且是文件时返回true
-g 当由pathname指定的文件或目录存在并且设置了SGID位时返回为true
-h 当file存在并且是符号链接文件时返回true,该选项在一些老系统上无效
-k 当由pathname指定的文件或目录存在并且设置了“粘滞”位时返回true
-p 当file存在并且是命令管道时返回为true
-r 当由pathname指定的文件或目录存在并且可读时返回为true
-s 当file存在文件大小大于0时返回true
-u 当由pathname指定的文件或目录存在并且设置了SUID位时返回true
-w 当由pathname指定的文件或目录存在并且可执行时返回true。一个目录为了它的内容被访问必然是可执行的。
-o 当由pathname指定的文件或目录存在并且被子当前进程的有效用户ID所指定的用户拥有时返回true。
UNIX Shell 里面比较字符写法:
-eq 等于
-ne 不等于
-gt 大于
-lt 小于
-le 小于等于
-ge 大于等于
-z 空串
= 两个字符相等
!= 两个字符不等
-n 非空串
用于数值计算的命令
双括号(())
效率极高,常用方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BAvXB9A3-1678232171872)(http://book.luffycity.com/linux-book/shell%E5%BC%80%E5%8F%91/pic/image-20210308144033950.png)]
案例,注意必须是整数,双括号不支持浮点数,浮点数需要其他命令计算
# 加减乘除
[root@chaogelinux shell_program]# echo $((3+4))
7
[root@chaogelinux shell_program]# echo $((5-3))