概述
一、什么是shell
在 Linux 内核与用户之间的解释器程序
- 通常指 /bin/bash
- 负责向内核翻译及传达用户/程序指令
- 相当于操作系统的“外壳”
二、shell的使用方式
交互式 —— 命令行
---人工干预、智能化程度高
---逐条解释执行、效率低
非交互式 —— 脚本---需要提前设计、智能化难度大
---批量执行、效率高
---方便在后台静悄悄的运行
三、常见的shell程序种类
如何切换 Shell 环境
---通过usermod、chsh更改登录 Shell
---手动执行目标 Shell 程序
查看所有可用的Shell
---cat /etc/shells下
[root@pc2 ~]# cat /etc/shells
/bin/sh #多数 Unix 默认的 Shell
/bin/bash #多数 Linux 默认的 Shell
/usr/bin/sh
/usr/bin/bash
四、bash基本特性
命令行环境回顾
- 快捷键、Tab 键补齐
- 命令历史
- 命令别名
- 标准输入输出
- 重定向
- 管道操作
shell脚本
提前写好可执行语句,能够完成特定任务的文件
---顺序、批量化处理
---解释器程序
一、编写规范
1、声明解释器(#!解释器路径)
2、注释(#可以描述脚本的功能,作者信息,变量作用等)
3、任务指令(可执行语句)
二、执行方法
1、添加 x 权限,然后用相对路径或绝对路径执行
[root@pc2 opt]# cat test01.sh
#!/bin/bash
#测试脚本
echo ABC
echo nb
[root@pc2 opt]# chmod +x test01.sh
[root@pc2 opt]# /opt/test01.sh
ABC
nb
[root@pc2 opt]# ./test01.sh
ABC
nb
2、使用解释器执行,无需 x 权限,会开启解释器子进程
用户(root)——bash进程——bash进程——echo(脚本结束解释器子进程结束退出)
[root@pc2 opt]# cat test01.sh
#!/bin/bash
#测试脚本
echo ABC
echo nb
[root@pc2 opt]# chmod -x test01.sh
[root@pc2 opt]# /opt/test01.sh
-bash: /opt/test01.sh: 权限不够
[root@pc2 opt]# bash /opt/test01.sh
ABC
nb
[root@pc2 opt]# ls /bin/bash
/bin/bash
[root@pc2 opt]#
3、使用 source 或 . 命令执行,无需 x 权限,不会开启解释器子进程
调用系统当前Shell解释器程序,不开解释器子进程
用户(root)——bash进程——echo
[root@pc2 opt]# cat test01.sh
#!/bin/bash
#测试脚本
echo ABC
echo nb
[root@pc2 opt]# source test01.sh
ABC
nb
[root@pc2 opt]# . ./test01.sh
ABC
nb
source #当前正在使用的解释器
4、2与3比较
#!/bin/bash
#测试脚本
echo ABC
mkdir abc
cd abc
[root@pc2 opt]# source test01.sh
ABC
[root@pc2 abc]# pwd
/opt/abc
[root@pc2 opt]# bash test01.sh
ABC
[root@pc2 opt]# ls
abc test01.sh
[root@pc2 opt]# pwd
/opt
[root@pc2 opt]#
三、调式脚本
主要途径
---直接观察执行中的输出、报错信息
---通过 bash -x 开启调试模式 -v选项
---在可能出错的地方设置echo
重定向
- > 重定向标准输出
- 2> 重定向错误输出
- &> 重定向所有输出
变量
一、什么是变量
常量:固定不变的内容
以固定名称存放,可能会变化的值
- 提高脚本对任务需求、运行环境变化的适应能力
- 方便在脚本中重复使用
二、定义/赋值/查看/取消变量
1、定义/赋值
名称可以用数字、字母、下划线,不能以数字开头,不能使用特殊符号,等号两边不能有空格,区分大小写
变量名=变量值
a=10 创建变量(对变量赋值)
a=20 对变量重新赋值
2、查看
echo $a(echo $变量名) 调用变量
echo ${a}RMB 大括号可以防止变量名和常量混淆
3、取消
变量的失效
- 退出定义变量的Shell环境时,变量会自动失效
- unset a(unset 变量名) 取消变量
- a= 将变量 a 赋值为空,也相当于取消变量
三、变量的种类
1、环境变量
常见的环境变量
- USER 当前用户名
- UID 当前用户 id 号
- HOME 当前用户家目录
- SHELL 当前用户解释器
- PWD 当前位置
- HOSTNAME 主机名
- PS1 一级提示符
- PS2 二级提示符
- PATH 存储了命令的路径
配置文件---/etc/profile(全局环境变量信息)
---~/.bash_profile(当前用户的环境信息,用户登录时读取)
相关操作
- env:列出所有的环境变量
- set:列出所有变量
环境变量PS1表示Shell环境的一级提示符,即命令行提示符(\u 用户名、\h 主机名、\W 工作目录、\$ 权限标识)
[root@svr5 src]# echo $PS1 #查看默认的一级提示
[\u@\h \W]\$
[root@svr5 src]#PS1='hehe#' #修改一级提示
hehe# #更改结果
hehe# PS1='[\u@\h \W]\$ ' #恢复原有设置
[root@svr5 src]#
环境变量PS2表示二级提示符,出现在强制换行场合:
[root@svr5 ~]# echo $PS2 #查看默认的二级提示
>
[root@svr5 src]# cd \ #强制换行,观察提示符效果
> /root/
[root@svr5 ~]# PS2='=> ' #手动修改二级提示
[root@svr5 ~]# cd \ #再次验证提示符效果
=> ~
[root@svr5 ~]# PS2='> ' #恢复原有设置
2、预定义变量
用来保存脚本程序的执行信息
- 直接使用这些变量
- 不能直接为这些变量赋值
$0 当前所在的脚本名称或解释器进程
$* 所有位置变量的值
$# 已加载的位置变量的个数
$$ 随机的进程号(当前运行进程的PID号)
$? 可以检测上一个指令是否执行成功,0是正常,非0是异常(前一条命令执行后的返回状态)
$! 后台运行的最后一个进程的进程号
[root@svr5 ~]# vim location.sh
#!/bin/bash
echo $0 # 脚本的名称
echo $1 # 第一个参数
echo $2 # 第二个参数
echo $* # 所有参数
echo $# # 所有参数的个数
echo $$ # 当前进程的进程号
echo $? # 上一个程序的返回状态码
[root@svr5 ~]# chmod +x location.sh # 添加可执行权限
[root@svr5 ~]# ./location.sh a b c
3、位置变量
在执行脚本时提供的命令行参数
$1 脚本后第1个位置参数
$2 脚本后第2个位置参数
$3 脚本后第3个位置参数
四、变量值及范围控制
1、定界符
- ' ' 界定范围 禁用扩展,即便 $ 也视为普通字符,可以屏蔽特殊符号的功能
- " " 界定范围 允许扩展,以 $ 引用其他变量
- ` ` 或者 $() 将命令的执行输出作为变量值
2、read标准输入取值
read 从键盘读入变量值完成赋值
格式:read [-p "提示信息"] 变量名
选项:
--- -p 输出提示信息
--- -t 可指定超时秒数
--- -n 限制读取字符
执行后从会等待并接受用户输入(无任何提示的情况),并赋值给变量str:
[root@svr5 ~]# read str
What's happen ? # 随便输入一些文字,按Enter键提交
[root@svr5 ~]# echo $str # 查看赋值结果
What's happen ?
为了不至于使用户不知所措、莫名其妙,推荐的做法是结合 -p 选项给出友好提示:
[root@svr5 ~]# read -p "请输入一个整数:" i
请输入一个整数:240
[root@svr5 ~]# echo $i
240
#!/bin/bash
read -p "请输入用户名" u # -p是可以定义提示信息,u相当于自定义变量名称,可以存储用户看到提示信息后输入的字符
useradd $u
read -p "请输入密码" n
echo "$n" | passwd --stdin $u
3、终端显示控制
stty -echo(关闭终端输出——无显示)
stty echo(恢复终端输出——显示)
#!/bin/bash
read -p "请输入用户名" u
useradd $u
stty -echo
read -p "请输入密码" n
stty echo
echo "$n" | passwd --stdin $u
4、局部变量
新定义的变量默认只在当前Shell环境中有效
无法在子Shell环境中使用
5、全局变量
全局变量在当前Shell及子Shell环境中均有效
使用 export 可将局部变量声明为全局变量
export 局部变量名[=变量值] #为局部变量添加全局属性
export -n 全局变量名 #取消指定变量的全局属性
数值运算
一、整数运算
1、使用expr命令
乘法操作应采用 \* 转义,避免被作为Shell通配符;参与运算的整数值与运算操作符之间需要以空格分开,引用变量时必须加$符号。
[root@svr5 ~]# X=1234 #定义变量X
[root@svr5 ~]# expr $X + 78 #加法
1312
[root@svr5 ~]# expr $X - 78 #减法
1156
[root@svr5 ~]# expr $X \* 78 #乘法,操作符应添加\转义
96252
[root@svr5 ~]# expr $X / 78 #除法,仅保留整除结果
15
[root@svr5 ~]# expr $X % 78 #求模
64
2、使用$[ ]或$(( ))表达式
乘法操作*无需转义,运算符两侧可以无空格;引用变量可省略 $ 符号;计算结果替换表达式本身,可结合echo命令输出。
[root@svr5 ~]# X=1234
[root@svr5 ~]# echo $[X+78]
1312
[root@svr5 ~]# echo $[X-78]
1156
[root@svr5 ~]# echo $[X*78]
96252
[root@svr5 ~]# echo $[X/78]
15
[root@svr5 ~]# echo $[X%78]
64
3、使用let命令
expr或$[ ]、$( ())方式只进行运算,并不会改变变量的值;而let命令可以直接对变量值做运算再保存新的值。
常规写法 主流写法
let a=a+1 let a++ #变量a加1
let a=a-1 let a-- #变量a减1
let a=a+10 let a+=10 #变量a加10
let a=a-10 let a-=10 #变量a减10
let a=a*2 let a*=2 #变量a乘以2
let a=a/2 let a/=2 #变量a除以2
let a=a%3 let a%=3 #变量a除以3取余数
二、小数运算
整数运算的局限性
bash内建机制仅支持整数值运算
expr命令、$[ ] 算式替换 不支持有小数的运算
使用 bc 实现小数运算多数Linxu系统默认安装此工具
---支持高精度的数值运算
---直接运行bc可进入交互式运算界面,quit退出
---设置 scale=n 可约束小数位
结合管道向bc发送表达式
---多个表达式以分号分隔
---通过echo命令+管道传递要计算的表达式
1、bc交互式运算
先执行bc命令进入交互环境,然后再输入需要计算的表达式。quit 退出
[root@svr5 ~]# bc
2、bc非交互式运算
将需要运算的表达式通过管道操作交给bc运算。注意,小数位的长度可采用scale=N限制。
[root@svr5 ~]# echo "1.1+1" | bc
[root@svr5 ~]# echo "10/3" | bc
[root@svr5 ~]# echo "scale=2;10/3" | bc # scale可以定义结果是小数点后多少位
3、小数值的比较
如果表达式成立,则返回的计算结果为1,否则返回0
常见比较操作:>、>=、<、<=、==、!=
[root@svr5 ~]# A=12.34 ; B=56.78
[root@svr5 ~]# echo "$A <= $B" | bc # A是否小于或等于B
1
[root@svr5 ~]# echo "$A <= $B" | bc # A是否大于或等于B
0