Shell编程规范与变量
目录
1. shell脚本基础
1.1 shell脚本概述
shell是一个特殊的应用程序,介于操作系统内核与用户之间,充当了一个"命令解释器"的角色,负责接收用户输入的操作指令并进行解释,将需要执行的操作传递给内核执行,并输出执行结果。
-
shell脚本的概念
- 将要执行的命令按顺序保存到一个文本文件
- 可结合各种shell控制语句完成更复杂的操作
-
shell脚本应用场景
- 重复性操作
- 交互性任务
- 批量事务处理
- 服务运行状态监控
- 定时任务执行
1.2 shell的作用
- 用户登录后一定会产生shell程序,一般为/bin/bash
- 不同shell的内部指令、运行环境等会有所区别
[root@localhost ~]#cat /etc/shells
#查看本机shell
1.3 脚本的构成
- 脚本申明(解释器):#!/bin/bash
- 注释信息(以#开头的语句):注释语言 #
- 可执行语句(echo命令用于输出):可执行的语句
1.4 脚本执行逻辑
脚本执行逻辑三种方式
- 顺序执行:程序按从上到下顺序执行
- 选择执行:程序执行过程中,根据条件的不同,进行选择不同分支继续执行
- 循环执行:程序执行过程中需要重复执行多次某段语句(已知次数、已知条件、死循环)
脚本可以补全,做软链接,修改path路径,需要执行权限
1.5 运行脚本的几种方式
-
直接调用bash 读脚本
- 调用shell程序直接执行
shell 程序+脚本名
sh test.sh
csh test.sh
-
路径的方式(需要有x权限)
-
绝对路径 /data/test.sh
-
相对路径 ./test.sh
如果想补全 加软连接
加权限:chmod +x test.sh
-
-
source 和 .
source + 脚本名
. + 脚本名
. test.sh
source test.sh //不建议使用会影响当前环境
1.6 脚本错误调试
-
命令错误
- 不会影响脚本执行
-
语法错误
- 会影响脚本执行
-
逻辑错误
- 自己筛查
查代码正确性
bash -n 脚本名称 (不在当前目录下加绝对路径) 检查语法错误
bash -x 脚本名称 (不在当前目录下加绝对路径) 逻辑错误
在脚本前面输入set -e,一旦出错立即停止,影响效率
1.7 重定向与管道符
1.7.1 重定向
重定向:> >> <
> #标准输出
2> #错误输出
>> #追加
2>> #错误追加
&>>
混合导入:ls >1 >2 >&
1 #代表正确输入
2 #代表错误输入
& #代表混合
- 重定向定义:不通过标准输出到屏幕上,输出到你指定的位置
类型:
-
标准输入:通过输入设备(键盘、鼠标、扫描仪)将数据传给电脑
-
标准输出:输出正确的运算结果,输出显示屏上
-
标准错误输出:不正确的都算错,输出在显示屏上
类型 | 设备文件 | 文件描述编号 | 默认设备 |
---|---|---|---|
标准输入 | /dev/stdin | 0 | 键盘 |
标准输出 | /dev/stdout | 1 | 显示器 |
标准错误输出 | /dev/stderr | 2 | 显示器 |
类型 | 操作符 | 用途 |
---|---|---|
重定向输入 | < | 从指定的文件读取数据,而不是从键盘输入 |
重定向输出 | 1> | 将输出结果保存到指定的文件(覆盖原有内容) |
>> | 将输出结果追加到指定的文件尾部 | |
标准错误输出 | 2> | 将错误信息保存到指定的文件(覆盖原有内容) |
2>> | 标准错误输出结果追加到指定的文件尾部 | |
混合输出 | &>无论对错都可以重定向 | 将标准输出、标准错误的内容保存到同一个文件中 |
1.7.2 多行重定向
修改密码
[root@localhost data]#passwd lj <<EOF
> 123123
> EOF
更改用户 lj 的密码 。
新的 密码:无效的密码: 密码少于 8 个字符
重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。
1.7.3 管道符
管道符(P) "|" :连接两个程序
将左侧的命令输出结果,作为右侧命令的输入(处理对象),可以叠加使用
1.8 变量
常见shell变量类型
- 环境变量:系统维护,设置工作环境
- 自定义变量:用户自己定义,可以修改和使用
- 变量名=变量值
- 打印变量:echo $变量名
- 取消变量:unset 变量名
- 只读变量:只可以读取不可以更改,常量
- 位置变量:通过命令行给脚本传递参数
- 预定义变量:BASH中内置的一些变量,不能修改,规定好的变量
[root@localhost ~]#echo name
name
[root@localhost ~]#name=www
[root@localhost ~]#echo $name
www
[root@localhost ~]#user=lj
[root@localhost ~]#id=18
[root@localhost ~]#echo $userid
[root@localhost ~]#echo $user$id
lj18
[root@localhost ~]#echo ${user}18
lj18
${ }确定变量的范围
' ' 不识别变量
" " 可以识别变量
` ` 可以直接调用命令
[root@localhost ~]#cd /data
[root@localhost data]#ls
f11.txt f1.txt
[root@localhost data]#c=$(ls)
[root@localhost data]#echo $c
f11.txt f1.txt
1.8.1 read -p
从键盘输入的内容变成变量
方法1
[root@localhost ~]# read -p "现在时间是几点" time
现在的时间是16点
[root@localhost ]# echo $time
17点
方法2
[root@localhost ~]# vim re.sh
#!/bin/bash
echo -n "请输入内容"
read info
echo $info
[root@localhost ~]#bash re.sh
请输入内容 Hello
Hello
1.8.2 命名要求
- 区分大小写
- 不能使用程序中的保留字和内置变量:如hostname、for
- 只能使用数字、字母和下划线,不能以数字开头,不支持 "-"
- 不要使用内置变量,
- 大驼峰:StudentFirstName
- 小驼峰:studentFirstName
- 下划线student_name
变量赋值是临时生效,退出终端后,变量会自动删除,无法永久保存,脚本中的变量也会随脚本结束,自动删除
变量引用:
$name
${name}
弱引用和强引用
"$name " 弱引用,其中的变量引用会被替换为变量值
'$name ' 强引用,其中的变量引用不会被替换为变量值,而保持原字符串
赋值时使用双引号(" ")可以直接调用变量
赋值时使用单引号(' ')$只会被认为是字符$ 不会调用变量
赋值时使用(``反撇在tab上面)命令替换,提取命令执行后的输出结果和$()用法相同
{}可以分隔变量值
[root@localhost ~]#echo ls
ls
[root@localhost ~]#echo $(ls)
anaconda-ks.cfg initial-setup-ks.cfg system_info.sh 公共 模板 视频 图片 文档 下载 音乐 桌面
[root@localhost ~]#echo 'ls'
ls
[root@localhost ~]#echo "ls"
ls
[root@localhost ~]#echo `ls`
anaconda-ks.cfg initial-setup-ks.cfg system_info.sh 公共 模板 视频 图片 文档 下载 音乐 桌面
[root@localhost ~]#
1.8.3 shell变量的作用、类型
- 变量作用
- 用来存放系统和用户需要使用的特定参数
- 变量名:使用固定的名称,由系统预设或用户定义
- 变量值:能够根据用户设置、系统环境的变化而变化
- 用来存放系统和用户需要使用的特定参数
格式
export 变量名=变量值
name=VALUE
export name
[root@localhost ~]# abc=123
[root@localhost ~]# echo $abc
123
[root@localhost ~]# bash
[root@localhost ~]# echo $abc
为空
[root@localhost ~]# exit
exit
[root@localhost ~]# echo $abc
123
[root@localhost ~]# export abc
#export 变量名 定义全局变量
[root@localhost ~]# bash
[root@localhost ~]# echo $abc
123
- 变量类型
- 自定义变量:由用户自己定义、修改和使用
- 特殊变量:环境变量,只读变量,位置变量,预定义变量
1.8.4 整数运算
在 Bash Shell 环境中,只能进行简单的整数运算,不支持小数运算
整数运算主要通过内部命令 expr 进行
运算符与变量之间必须有至少一个空格。
expr:专门运算符,只能进行整数的运算
格式: expr 变量1 运算符 变量2 [运算符 变量3]
-
运算符号:$(()) 和$[]
-
运算命令:expr和let
-
运算工具:bc(系统自带)
[root@localhost ~]#seq 11 #将1-11竖着列出来
1
2
3
4
5
6
7
8
9
10
11
[root@localhost ~]#seq -s+ 11
1+2+3+4+5+6+7+8+9+10+11
[root@localhost ~]#seq -s+ 11 | bc
66
[root@localhost ~]#seq -s+ 111 | bc
6216
[root@localhost ~]#seq -s+ 1111 | bc
617716
let一般和变量一起使用
[root@localhost ~]#x=1;let x=x+1;echo $x
2
#echo将运算结果打印出来
[root@localhost ~]#vim js.sh
[root@localhost ~]#bash js.sh
#!/bin/bash
read -p "请输入第一个整数:" num1
read -p "请输入第一个整数:" num2
sum=0
sum=`expr $num1 + $num2`
echo "求和结果为:$sum"
1.8.5 环境变量
环境变量
-
由系统提前创建,用来设置用户的工作环境
-
env可以查看环境变量
-
配置文件位置:/etc/profile、~/.bash_profile
-
/etc/profile:修改此文件会作用于所有用户
-
~/.bash_profile:用户独立的配置文件,修改此文件只作用于当前用户
-
常见的环境变量
- $PWD(当前所在工作目录)、$PATH(可执行用户程序的默认路径)
- $USER(用户名称)、$HOME(用户的宿主目录)、$LANG(语言和字符集)
作用
- 可以使子进程(包括孙子进程)继承父进程变量,但父进程无法使用子进程变量
- 一旦子进程修改从父进程继承的变量,会将新的值传递给孙子进程
- 脚本中较少使用,只在系统配置文件中使用
[root@localhost ftp]#env
#可以看到所有
[root@localhost ~]#echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]#PATH="$PATH:/root"
[root@localhost ~]#echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root
[root@localhost ~]#
1.8.6 只读变量
变量值不允许修改(重新赋值)的情况
无法使用 unset删除,最快方法重启
1.8.7 位置变量
- 也称为位置参数,使用$1、$2、$3、…、$9 表示
$1..$n 注意10以上的位置变量
[root@localhost ~]#vim 1.sh
#!/bin/bash
echo "$1"
echo "$*"
[root@localhost ~]#bash 1.sh {1..10}
1
1 2 3 4 5 6 7 8 9 10
1.8.8 预定义变量
定义:系统定义好的变量
$*:表示所有位置参数的内容看成一个整体返回 返回所有
$@:表示所有位置参数的内容分割成n份,每份作为一个独立的个体返回 返回所有
$?:表示前一条命令执行后的返回状态,返回值为 0 表示执行正确,返回任何非 0值均表示执行出现异常
$#:表示命令行中位置参数的总个数
$0:表示当前执行的脚本或程序的名称 当前脚本的名字
$$:当前进程id
$!: 后台任务最后一个id
$* 和 $@ 有什么区别?
$*表示所有位置参数内容看成一个整体
$@表示所有位置参数内容分割成n份,每份作为一个独立的个体返回
1.9 编辑shell脚本查看系统性能
#!/bin/bash
ip=$(ifconfig ens33|grep netmask|tr -s ' '|cut -d' ' -f3)
mem=`free -h | grep Mem | tr -s ' ' | cut -d ' ' -f2`
host=`hostname`
kernel=`uname -r`
disk=`lsblk |grep disk|tr -s ' '|cut -d ' ' -f4`
cputy=`lscpu |grep 型号名称|tr -s ' '|cut -d ' ' -f2-7`
cpuhs=`lscpu |grep 'CPU(s):'|tr -s ' '|cut -d ' ' -f2`
echo "该主机的ip地址为:$ip"
echo "该主机的总内存为:$mem"
echo "该主机的主机名为:$host"
echo "该主机的内核版本为:$kernel"
echo "该主机的disk大小为:$disk"
echo "该主机的CPU型号为:$cputy"
echo "该主机的CPU核数为:$cpuhs"