什么是shell???
- 在Linux内核与用户之间的解释器程序
- 通常指/bin/bash
- 负责向内核翻译及传达用户/程序指令
- 相当于操作系统的"外壳"
shell的使用方式
- 交互式 -----命令行
人工干预,智能化程度高,逐条解释执行,效率低. - 非交互式 -----脚本
需要提前设计,智能化难度大.批量执行,效率高.方便在后台静悄悄的运行
常见的shell解释器
[root@proxy ~]# cat /etc/shells (查看本机所有解释器)
/bin/sh (是bash的符号链接,Unix的默认shell)
/bin/bash (Linux默认使用的shell)
/sbin/nologin (非登录shell)
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/ksh (此解释器默认未安装)
/bin/rksh (此解释器默认未安装)
bash的基本特性(优点)
- 快捷键,tab键补齐
- 命令历史
- 命令别名
- 标准输入输出
- 重定向
- 管道操作
shell基础应用
- 一.快捷键
- 二.切换用户的shell环境
[root@proxy ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/bin/tcsh
/bin/csh
/bin/ksh
[root@proxy ~]# ksh (进入ksh解释器)
[root@proxy ~]# csh (进入csh解释器)
[root@proxy ~]# sh (进入csh解释器)
[root@proxy ~]# tcsh (进入tcsh解释器)
[root@proxy ~]# bash (进入bash解释器) ###exit退出解释器
修改用户的登录Shell,管理员可以直接通过usermod(或useradd)命令设置。
比如,以下操作可将用户zhangsan的登录Shell改为/bin/ksh:
[root@svr5 ~]# usermod -s /bin/ksh zhangsan //执行修改操作
[root@svr5 ~]# grep ‘zhangsan’ /etc/passwd
zhangsan❌516:516::/home/zhangsan:/bin/ksh //修改后
- 三.练习命令历史,命令别名
1.检查历史命令的容量。
[root@proxy ~]# grep ^HISTSIZE /etc/profile
HISTSIZE=1000
查看已为当前用户记录的历史命令条数:
[root@proxy ~]# history | wc -l
2.列出最近执行的10条历史命令:
[root@proxy ~]# history | tail
3.重新执行历史命令列表中的第88条操作:
[root@proxy ~]# !88
重新执行最近一次以cat开头(根据实际情况变更)的历史命令操作:
[root@svr5 ~]# !cat
4.查看已经定义的命令别名列表。
[root@proxy opt]# alias
- 四.重定向标准输入/输出/错误输出
1.使用 > 将命令执行的正常输出重定向到文件:
[root@proxy ~]# ls -ld /etc/ //正常应输出到屏幕
drwxr-xr-x. 140 root root 8192 8月 2 04:45 /etc/
[root@proxy ~]# ls -ld /etc/ > stdout.txt //重定向到文件
[root@proxy ~]# cat stdout.txt //确认重定向输出的结果
drwxr-xr-x. 140 root root 8192 8月 2 04:45 /etc/
> 操作会覆盖目标文件(先清空、再写入):
[root@proxy ~]# echo “I am the king.” > stdout.txt //覆盖目标文件
[root@proxy ~]# cat stdout.txt //确认结果
I am the king.
改用 >> 可实现追加重定向输出:
[root@proxy ~]# ls -ld /etc/ >> stdout.txt //追加输出
[root@proxy ~]# cat stdout.txt
I am the king. //原有内容还保留
drwxr-xr-x. 140 root root 8192 8月 2 04:45 /etc/
2.重定向标准错误。
对于命令执行出错的信息,使用 > 无法保存,仍然会输出到屏幕。比如,可使用ls命令同时查看两个对象(其中nb.txt并不存在),重定向输出:
[root@proxy ~]# ls -l nb.txt /etc/fstab > stderr.txt
[root@proxy ~]# cat stderr.txt //正常信息成功重定向到目标文件
-rw-r–r--. 1 root root 541 1月 5 2017 /etc/fstab
使用 2> 可重定向错误信息,比如,可执行一个错误的命令:
[root@proxy ~]# ls -l nb.txt /etc/fstab 2> stderr.txt
-rw-r–r--. 1 root root 541 1月 5 2017 /etc/fstab
//正确的信息默认输出至屏幕,错误信息重定向到目标文件
[root@proxy ~]# cat stderr.txt //从文件中查看出错信息
ls: nb.txt: 没有那个文件或目录
类似的,2>> 可实现追加输出:
[root@proxy ~]# ls tmpfile 2>> stderr.txt
[root@proxy ~]# cat stderr.txt
ls: nb.txt: 没有那个文件或目录
ls: tmpfile: 没有那个文件或目录
若希望将正常输出、错误输出重定向同一个文件,可使用 &> :
[root@proxy ~]# ls -l nb.txt /etc/fstab &> stderr.txt
[root@proxy ~]# cat stderr.txt
ls: nb.txt: 没有那个文件或目录
-rw-r–r--. 1 root root 541 1月 5 2017 /etc/fstab
3.重定向标准输入。
[root@proxy ~]# mail -s Error root < /etc/passwd
- 五.管道操作实践
借助于管道符“|”,可以将一条命令的标准输出交给另一条命令处理,在一条命令行内可依次使用多个管道。
1.统计/etc/目录下资料的数量。
[root@svr5 ~]# ls -l /etc | wc -l
2.列出Yum库里名称中含cluster的软件包。
[root@proxy opt]# yum list | grep cluster
lvm2-cluster.x86_64 7:2.02.177-4.el7 local_repo
pacemaker-cluster-libs.i686 1.1.18-11.el7 local_repo
pacemaker-cluster-libs.x86_64 1.1.18-11.el7 local_repo
什么是shell脚本?
- 提前写好可执行语句,能够完成特定任务的文件顺序,批量化处理
- 解释型程序
- 常见的脚本语言:
bash shell
Python/Perl/Ruby
JSP/PHP/ASP/CGI
JavaSvript…
shell脚本,可以大幅度提高工作效率的工具
编写shell脚本规范
1,声明解释器
#!/bin/bash
2,注释,脚本的功能介绍,变量的含义等(步骤,思路,用途)
#XXXXX
3,编写代码(可执行语句)
执行代码1
执行代码2
…
shell脚本的执行方式
- 1, 添加x权限
- 2, 使用解释器直接执行脚本, 新开启解释器进程,无需x权限
- 3, 使用source命令执行脚本, 使用当前解释器,无需x权限 (source可以用.替代)
source解释器与bash解释器的区别
- 下面通过脚本的形式解释
[root@proxy opt]# vim test01.sh
#!/bin/bash
#这是一个测试脚本
echo ABC
sleep 2000
[root@proxy opt]# source test01.sh
ABC
[root@proxy ~]# pstree ##新开一个终端查看进程树
├─sshd─┬─sshd───bash───sleep
│ └─sshd───bash───pstree
[root@proxy opt]# bash test01.sh
ABC
[root@proxy ~]# pstree
├─sshd─┬─sshd───bash───bash───sleep
│ └─sshd───bash───pstree
[root@proxy opt]# vim test02.sh
#!/bin/bash
#这是一个测试脚本
mkdir /opt/xyz
cd /opt/xyz
[root@proxy opt]# source test02.sh
[root@proxy xyz]#
[root@proxy opt]# rm -rf xyz
[root@proxy opt]# bash test02.sh
[root@proxy opt]#
[root@proxy opt]# ls
xyz
- 用当前解释器(source)去执行一个脚本,当脚本执行完成后会停留在脚本
例如:脚本完成后留在xyz目录 - 使用bash解释器去执行一个脚本,当脚本执行完成后会离开脚本
例如:脚本完成后不会停留在xyz目录中
编写部署yum仓库脚本
[root@proxy opt]# vim test03.sh
#!/bin/bash
#部署yum仓库
url=http://172.25.0.254/content/rhel7.0/x86_64/dvd/ ##按照实际需求填写,此为案例
rm -rf /etc/yum.repos.d/*.repo
echo '[abc]
name=test
baseurl=$url
enabled=1
gpgcheck=0' > /etc/yum.repos.d/abc.repo
[root@proxy opt]# bash test03.sh
[root@proxy opt]# yum repolist ##测试脚本是否成功
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
源标识 源名称 状态
abc CentOS-7 - Base 9,911
repolist: 9,911
编写部署ftp服务脚本
[root@proxy opt]# vim test04.sh
#!/bin/bash
#这是一个简单的ftp测试脚本
yum -y install vsftpd &> /dev/null
systemctl restart vsftpd
systemctl enable vsftpd
[root@proxy opt]# bash test04.sh ##执行脚本
[root@proxy opt]# systemctl status vsftpd
调试shell脚本
主要途径:
直接观察执行中的输出,报错信息
通过sh -X 开启调试模式
在可能出错的地方设置echo
什么是变量?
- 以固定名称存放,可能会变化的值
- 提高脚本对任务需求,运行环境变化的适应能力
- 方便在脚本中重复使用
常量 固定不变
变量 灵活多变,脚本使用变量可以增加性能,使其更强大
变量的种类
shell变量的分类角度:
- 存储类型:
整数型,浮点型,双精度浮点型,字符型,…
shell脚本语言对存储类型要求较松散 - 使用类型
类型 | 说明 |
---|---|
环境变量 | 变量名通常都大写,由系统维护,用来设置工作环境,只有个别变量用户可以直接更改 |
位置变量 | bash内置,存储执行脚本时提供的参数 |
预定义变量 | bash内置,一类有特殊用途的变量,可直接调用,但不能直接赋值或修改 |
自定义变量 | 由用户自主设置,修改及使用 |
1.自定义变量
- 变量名称=变量的值 等号两边不能有空格
名称可以使用大小写字母,数字,下划线,不能以数字开头,不能使用关键字和特殊符号 - 查看变量
引用变量值: $变量名
查看变量值: echo $变量名 或者 echo ${变量名}
[root@proxy opt]# a=10 ##定义变量
[root@proxy opt]# echo $a ##调用变量
10
[root@proxy opt]# a1=20
[root@proxy opt]# echo $a1
20
[root@proxy opt]# a_1=30
[root@proxy opt]# echo $a_1
30
[root@proxy opt]# b=40
[root@proxy opt]# echo $b
40
[root@proxy opt]# echo ${b}RMB ##容易混淆时加{}进行界定
40RMB
相关注意事项:
若指定的变量名已存在,相当于为此变量重新赋值
取消变量:
变量的失效
退出定义变量的shell环境时,变量会自动失效
也可手动取消: unset 变量名
[root@proxy opt]# a=20
[root@proxy opt]# echo $a
20
[root@proxy opt]# unset a ##取消变量
[root@proxy opt]# echo $a
2.环境变量
环境变量的配置文件
- /etc/profile
- ~/.bash_porfile
相关操作
- env : 列出所有环境变量 ##通常与grep连用
- set : 列出所有变量
见的环境变量:
- echo $USER 当前用户名
- echo $PATH 命令程序的存放路径
- echo $SHELL 当前用户使用的解释器
- echo $HOME 当前用户的家目录
- echo $HOSTNAME 主机名
- echo $UID 当前用户的id号
- echo $PWD 所在目录位置
- echo $PS1 一级提示符
- echo $PS2 二级提示符
预定义变量
- 用来保存脚本程序的执行信息
直接使用这些变量
不能直接为这些变量赋值
变量名 | 含义 |
---|---|
$0 | 当前所在的进程或脚本名 |
$# | 跟了多少个参数(已加载的位置变量的个数) |
$* | 所有位置变量的值 |
$? | 上一个任务是否执行成功(命令执行后返回状态),0是成功,非0是失败 |
$$ | 当前运行进程的PID号 |
位置变量
- 在执行脚本时提供的命令行参数
- 表示为$n ##n为序号
- $1. $2 … ${10}. ${11}…
[root@proxy opt]# vim test05.sh
#!/bin/bash
echo $1 ##显示脚本后跟的第1个参数
echo $2 ##显示脚本后跟的第2个参数
echo $3 ##显示脚本后跟的第3个参数
echo $0 ##显示脚本执行名称
echo $# ##统计脚本后跟了多少个参数
echo $* ##显示脚本后所有位置变量的值
echo $$ ##显示进程号 (随机数)
echo $? ##显示上一个任务是否执行成功,0是成功,非0是失败
[root@proxy opt]# bash test05.sh a b c d
a
b
c ##因为脚本没有写第4个位置变量,所以即使脚本后跟了第4个位置变量也不会有输出
test05.sh
4
a b c d
1643
0
read标准输入取值
- read 从键盘读入变量完成赋值
格式 : read [-p “提示信息”] 变量名
-p可选,-t 可指定超时秒数 - 终端显示控制
stty -echo : 关闭终端输出(屏蔽回显)
stty echo : 恢复终端输出(显示回显)
编写创建用户并配置密码的脚本
#!/bin/bash
#这是一个创建用户的测试脚本
read -p "请输入你要创建的用户名:" a
id $a &> /dev/null
if [ $? -eq 0 ];then
echo "用户已存在"
exit 2
else
useradd $a &> /dev/null
#stty -echo
read -p "请设置新用户的密码(默认123):" b
#stty echo
echo ${b:-123} | passwd --stdin $a &> /dev/null
echo "$a用户创建成功"
fi
[root@proxy opt]# bash test06.sh ##执行脚本
请输入你要创建的用户名:zhang ##输入用户名
请设置新用户的密码(默认123): ##设置密码.不设置密码则默认密码为123
变量的扩展应用
区分三种定界符
- 双引号 "": 界定范围 (允许扩展,以$ 引用其他变量)
- 单引号 '': 界定范围,屏蔽特殊符号(禁用扩展,即便$也视为普通字符)
- 反撇号 ``: 将命令的执行输出作为变量值
[root@proxy opt]# touch "a b"
[root@proxy opt]# ls
a b test01.sh test02.sh test03.sh test04.sh
test05.sh test06.sh
[root@proxy opt]# touch 'x y'
[root@proxy opt]# ls
a b x y
[root@proxy opt]# a=10
[root@proxy opt]# echo "$a"
10
[root@proxy opt]# echo '$a'
$a
[root@proxy opt]# date
2020年 01月 02日 星期四 15:31:09 CST
[root@proxy opt]# a=`date`
[root@proxy opt]# echo $a
2020年 01月 02日 星期四 15:31:19 CST
变量的作用范围
- 局部的变量
新定义的变量默认只在当前shell环境中有效
无法在子shell环境中使用 - 全局变量
全局变量在当前shell及子shell环境中均有效
使用export可将局部变量声明为全局变量
export 局部变量名[=变量值]…: 为局部变量添加全局属性
export -n 全局变量名… : 取消指定变量的全局属性
注:默认情况下,自定义的变量为局部变量,只在当前Shell环境中有效,而在子Shell环境中无法直接使用
[root@proxy opt]# a=100 ##定义变量a
[root@proxy opt]# export a ##将变量a发布为全局
[root@proxy opt]# bash ##开启新解释器
[root@proxy opt]# echo $a ##依然可以使用该变量
100
[root@proxy opt]# exit ##退出bash解释器
[root@proxy opt]# b=200 ##定义变量b
[root@proxy opt]# echo $b
200
[root@proxy opt]# bash ##开启新解释器
[root@proxy opt]# echo $b ##不能使用该变量
[root@proxy opt]# exit
[root@proxy opt]# export c=300 ## 创建+发布b为全局变量
[root@proxy opt]# echo $c ##定义变量c
300
[root@proxy opt]# bash ##开启新解释器
[root@proxy opt]# echo $c ##可以使用该变量
300
[root@proxy opt]# exit
[root@proxy opt]# export -n b ##取消变量b的全局状态,恢复为局部变量
[root@proxy opt]# echo $b ##局部状态还在
200
[root@proxy opt]# bash
[root@proxy opt]# echo $b ##不能使用该变量
数值运算
- 整数运算
1.expr运算工具 - 计算指定的表达式,并输出结果
- 格式 : expr 整数1 运算符 整数2…
- 乘法操作应采用\*转义,避免被作为shell通配符
类型 | 运算 | 示例 |
---|---|---|
加法 | + | expr 43 + 21 |
减法 | - | expr 43 - 21 |
乘法 | \* | expr 43 \* 21 |
除法 | / | expr 43 / 21 |
取模(取余数) | + | expr 43 % 21 |
[root@proxy opt]# expr 1 + 1 ## expr $X + $Y
2
[root@proxy opt]# expr 1 - 1 ## expr $X - $Y
0
[root@proxy opt]# expr 1 \* 1 ##expr $X \* $Y
1
[root@proxy opt]# expr 1 / 1 ##expr $X / $Y
1
[root@proxy opt]# expr 1 % 1 ## expr $X % $Y
0
[root@proxy opt]# a=10
[root@proxy opt]# b=20
[root@proxy opt]# expor $a + $b
30
[root@proxy opt]# expot $b - $a
10
[root@proxy opt]# $a + 100
110
2.利用echo配合运算工具
- 使用$[ ] 或 $(()) 表达式
- 格式 : $[整数1 运算符 整数2… ]
- 乘法操作*无需转义,运算符两测可以无空格
- 引用变量可省略$符号
- 计算结果替换表达式本身,可结合echo命令输出
[root@proxy opt]# echo $[1+1]
2
[root@proxy opt]# echo $((1+1))
2
[root@proxy opt]# echo $[2-1]
1
[root@proxy opt]# echo $((2-1))
1
[root@proxy opt]# echo $[2*2]
4
[root@proxy opt]# echo $((2*2))
4
[root@proxy opt]# echo $[4/2]
2
[root@proxy opt]# echo $((4/2))
2
[root@proxy opt]# echo $[5%2]
1
[root@proxy opt]# echo $((5%2))
[root@proxy opt]# a=10
[root@proxy opt]# echo $[a+a]
20
[root@proxy opt]# echo $((a+a))
20
3.利用let运算工具
-
使用let表达式
-
结合echo命令查看结果
-
格式 :
简单表达式 | 完整表达式 |
---|---|
i++ | i=i+1 |
i- - | i=i-1 |
i+=2 | i=i+2 |
i-=2 | i=i-2 |
i*=2 | i=i*2 |
i/=2 | i=i/1 |
i%=2 | i=i%2 |
[root@proxy ~]# X=1234
[root@proxy ~]# let y=X+22
[root@sproxy ~]# echo $y
1256
[root@proxy ~]# let X++; echo $X # X++(X=X+1)
1235
[root@proxy ~]# let X--; echo $X # X--(X=X-1)
1233
[root@proxy ~]# let X+=78 ; echo $X # X+=78(X=X+78)
1311
[root@proxy ~]# let X-=78 ; echo $X # X-=78(X=X-78)
1233
[root@proxy ~]# let X*=78 ; echo $X # X*=78(X=X*78)
96174
[root@proxy ~]# let X/=78 ; echo $X # X/=78(X=X/78)
1233
[root@proxy ~]# let X%=78 ; echo $X # X%=78(X=X%78)
63
整数运算的局限性
-
bash 内建机制仅支持整数值运算
-
expr命令. $[ ] 算式替换 不支持有小数的运算
-
小数运算 使用bc计算器实现小数运算
-
多数Linux系统默认安装此工具
支持运行bc可进入交互式运算界面,quit退出
设置 scale=n 可约束小数位 -
结合管道向bc发送表达式
-
多个表达式以分号分隔
-
通过echo命令+管道传递要计算的表达式
-
小数值的比较
-
基本用法
echo “数值1 比较符 数值2” | bc
如果表达式成立,则返回的计算结果为1,否则返回为0
常见比较操作: >. >=. <. <=.==.!=
bc计算器交互式运算
[root@proxy opt]# bc ##进入bc计算器交互界面
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
12.34+56.78 //加法
69.12
12.34-56.78 //减法
-44.44
12.34*56.78 //乘法
700.66
12.34/56.78 //除法
0
quit //退出交互计算器
bc计算器非交互式运算
[root@proxy opt]# echo 1.1+1 |bc
2.1
[root@proxy opt]# echo 10/3 |bc
3
[root@proxy opt]# echo "scale=3;10/3" |bc
3.333
[root@svr5 ~]# echo 'scale=4;12.34+5.678' | bc
18.018
[root@svr5 ~]# echo 'scale=4;12.34*5.678' | bc
70.0665
[root@svr5 ~]# echo 'scale=4;12.34/5.678' | bc
2.1733