1. 概述
1.1 为什么要学Shell编程
- Linux运维工程师在进行服务器集群管理时,需要编写Shell程序来进行服务器管理。
- 对于java程序员,需要编写Shell脚本对服务器的维护,如编写一个定时备份的脚本。
- 对于大数据管理员,需要编写Shell脚本管理集群。
1.2 Shell是什么
Shell是一个命令行解释器,为用户提供了一个对Linux内核发送请求以便运行程序的界面系统级程序。
2. Shell脚本执行方式
2.1 脚本格式
- 以 #!/bin/bash 开头
- 脚本需要有可执行权限
- 多行注释为 :<<! 内容 !
2.2 编写脚本
案例:创建一个Shell脚本,输出hello
- 创建脚本
vim say.sh
- 脚本内容
#!/bin/bash
echo "hello"
2.3 脚本常用执行方式
方式一:脚本所在的绝对路径或相对路径
方式二:sh + 脚本所在目录/脚本名称
方式一:需要有x执行权限,如 ./say.sh, 无权限不能输入
加可执行权限后
方式二:不需要可执行权限。如 sh say.sh
3. Shell变量
- Shell 变量分为系统变量和用户自定义变量。
- 系统变量如:$PWD、$HOME 、$USER、$SHELL
- 显示当前Shell所有变量:set
3.1 Shell变量的定义规则
- 变量名由字母、数字、下划线组成,开头不能是数字。
- 等号两侧不能有空格。
- 变量名一般为大写,是个规范。
将命令的返回值赋值给变量
A=`date` , ``表示运行反引号里面的命令,并把结果赋值给变量 A。
A=$(date) 等价于 A=`date`
3.2 案例
案例1: 定义变量A
内容
结果
案例2: 撤销变量A
内容
结果
案例3: 声明静态的变量B=2,不能unset
内容
结果
案例4:
结果
4. 设置环境变量
环境变量可以理解为全局变量。
export 变量名=变量值 // 让变量变为环境变量或全局变量
source 配置文件 // 修改后的配置文件立即生效
echo $变量名 // 查询环境变量的值
5. 位置参数变量
当我们执行一个 shell脚本时,如果希望在命令行上传递参数,就可以使用到位置参数变量。比如: ./myshell.sh 100 200,这个就是一个执行shell 的命令行,其中100 和 200 就是参数。100、200 类似于java 方法体的实参。
- $n // n 为数字,$0表示命令本身,$1-$9表示1-9个参数,10个以上的参数需要加花括号,如 ${11}。$n 类似于java的形参。
- $* // 表示命令行的所有参数,$*把参数作为一个整体。
- $@ // 表示命令行的所有参数,$@把每个参数区分开了。
- $# // 表示命令行中所有参数的个数。
6. 预定义变量
Shell设计者事先设计好的变量,可以直接使用。类似于java中的预定义变量。
- $$ // 当前进程的进程号 PID。
- $! // 后台运行的最后一个进程的进程号 PID。
- $? // 上一次命令的返回状态,如果值为0表示上个命令正常执行;如果值为非0表示上个命令执行不正确,具体的数值由自己的命令所决定。
7. 运算符
$((表达式)) 或者 $[(表达式)] 或者 expr 表达式
- 如果使用expr ,运算符之间要有空格。
- 乘号需要反斜杠,\* 表示 乘号。其余不用。
- = 两边不能有空格
案例一:计算(2+3)*4的值
8. if 条件判断
if [ 条件 ] // 条件前后有空格
非空返回true, 可使用 $?验证 (0为true, 大于1为 false)
如: [ abc ] 返回 true, [ ] 返回 false
= // 字符串比较
-lt // 小于
-gt // 大于
-eq // 等于
-ne // 不等于
-le // 小于等于
-ge // 大于等于
按照文件权限判断
-r // 有读的权限
-w // 有写的权限
-x // 有执行的权限
-f // 文件存在并且是一个常规的文件
-e // 文件存在
-d // 文件存在并是一个目录
案例
9. 流程控制
9.1 if 条件判断
if [ 条件表达式 ]
then
代码
elif [ 条件表达式]
then
代码
fi
注意:[ 条件表达式 ] 中括号开头和结尾必须要有空格
案例: 命令行输入数字,小于60输出不及格,等于60输出刚刚及格,大于等于80输出优秀。
9.2 case 语句
case $变量名 in
"值1")
如果是值1,则执行程序1
"值2")
;;
如果是值1,则执行程序2
"值1")
;;
*)
以上都不符合,执行该程序
;;
esac
案例:命令行输入1则输出周一,输入2则输出周二,其他输出其他
9.3 for 循环
语法1
for 变量 in 值1 值2 值3……
do
代码
done
语法2
for(( 初始值; 循环控制条件; 变量变化 ))
do
程序代码
done
注意:初始值与左括号(、变量变化与右括号)都有空格。
语法1案例:
语法2案例:累计1到100的和
9.4 while 循环
基本语法:
while [ 条件表达式]
do
代码
done
注意:while 与 左中括号 [ 有空格,条件表达式与左中括号 [ 、 ] 右中括号都有空格。
案例:求 1 到 n 的和输出
9.5 read 获取控制台输入
read(选项)(参数)
选项
-p: 指定读取值时的提示符
-t: 指定读取值时的等待时间(秒),如果没有在指定时间输入,就不再等待。
参数
变量:指定读取值时的变量名
案例:读取控制台输入的值
10秒内未输入NUM2的值,自动退出了。
10. 函数
函数分为系统函数和自定义函数
10.1 系统函数
basename [路径名] [后缀]
dirname [路径名]
- basename 详解
作用:返回路径中最后一个 / 后面的部分。
如果单写路径名,如 basename /opt/test/case.sh,输出的结果是路径中最后一个文件名,即输出case.sh
如果路径名和后缀都写,如 basename /opt/test/case.sh .sh,输出的结果是不带后缀的文件名,即输出case
tips: 可以把basename看作是java的subString函数,截取字符串。
dirname详解
作用:返回路径中最后一个 / 前面部分。(针对文件夹,即目录)
如 dirname /opt/test/case.sh , 则结果是 /opt/test
如 dirname /opt/test/zhangsan/say.sh, 则结果是 /opt/test/zhangsan
10.2 自定义函数
// 定义方法
function 方法名()
{
方法体
[retrun int]
}
// 调用方法
方法名 [值]
案例:计算输入的两数之和