shell脚本
1.脚本介绍
1.1 shell脚本基础
- shell脚本:
包含一些命令或声明,并符合一定格式的文本文件 - 格式要求:首行shebang机制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl - shell脚本的用途有:
自动化常用命令
执行系统管理和故障排除
创建简单的应用程序
处理文本或文件
1.2 创建shell脚本
- 第一步:使用文本编辑器来创建文件文件
第一行必须包括shell声明序列:#!
#!/bin/bash
添加注注释:注释以#开头 - 第二步:运行脚本
给予执行权限,在命令行指定脚本的绝对或相对路径
直接运行解释器,将脚本作为解释器程序的参数运行(没有执行权限也可以)
eg:vim /data/bash.shchomd +x /data/bash.shbahs.sh 可用看做外部命令(不在PATH路径下找不到文件因此不能执行)/data/bash/sh 绝对路径执行cd /data/ 相对路径执行./bash.shcat hello.sh | bashcat /var/www/html/hello.sh(192.168.20.128)curl http://192.168.20.128/hello.sh(远程运行)
1.3 脚本规范
-
第一行一般为调用使用的语言
-
程序名,避免更改文件名为无法找到正确的文件
-
版本号
-
更改后的时间
-
作用相关信息
-
该程序的作用,及注意事项
-
最后是各版本的更新简要说明
#!/bin/bash#--------------------------------#filename : hello.sh#revision: 1.1#date: 2019/10/5#autor: wang#email: [email protected]#website: www.magedu.com#description: This is the first script#----------------------------------#copyright: 2019 wang#license: GPLecho \"hello world \"
1.4 脚本的基本结构
1.脚本的基本结构
#!shebang
configuration_variables
function_definitions
main_code
1.5脚本调试
- 检查脚本中的语法错误:
bash -n /path/to/some_script - 调试执行
bash -x /path/to/some_script
2.变量
2.1 变量
- 变量:命令的内存空间
数据存储方式:
字符:
数值:整型,浮点型 - 变量:变量类型
作用:
1.数据存储格式
2.参与的运算
3.表示的数据范围
类型:
字符
数值:整型、浮点型 - 强类型:变量不经过强制转化,它永远是这个数据类型,不允许隐式的类型转换。一般定义变量是时
必须符合类型要求,调用未声明变量会产生错误
如 Java,c# - 弱类型:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;参与运算会自动
进行隐式类型转换;变量无须事先定义可直接调用
如:bash不支持浮点数,PHP - 变量命令法则
不能使用程序中的保留字: 例如if,for
只能使用数字、字母及下划线,且不能以数字开头
见名知义
同一命名规则:驼峰命名法
2.2 bash中变量的种类
根据变量的生效范围等标准划分下面变量类型:
1. 局部变量:生效范围为当前shell进程;对当前shell之外的其他shell进程。包括当前shell的子shell进程均无效2. 环境(全局)变量:生效范围为当前shell进程及其子进程3. 本地变量:生效范围为当前shell进程中某代码片段,通常指函数4. 位置变量:$1,$2,$3....来表示,用于让脚本在代码中国调用通过命令行传递给它的参数5. 特殊变量:$?,$0,$@,$#,$$
2.3 局部变量:
- 变量赋值:name=‘value’
- 可以使用引用value:
可以是直接字符串:name= “root”
变量引用:name= \”USER\”命令引用:name=‘command‘name=USER\”命令引用:name=`command` name=USER\”命令引用:name=‘command‘name=(command) - 变量引用:$(name) name\”\”:弱引用,其中的变量引用会被替换为变量值′′:强引用,其中的变量引用不会被替换为变量值,而保持原字符串echo\”name\”\”: 弱引用,其中的变量引用会被替换为变量值\’\’ : 强引用,其中的变量引用不会被替换为变量值,而保持原字符串echo \”name\”\”:弱引用,其中的变量引用会被替换为变量值′′:强引用,其中的变量引用不会被替换为变量值,而保持原字符串echo\”name\” 保留格式
echo $name 不保留格式 - 显示已定义的所有变量:set
- 删除变量:unset name
2.4环境变量
-
变量声明、赋值:
export name=VALUE
declare -x name=VALUE -
变量引用: $name , $(name)
-
显示所有环境变量:
env
printenv
export
declare -x -
删除变量:
unset name -
bash内建的环境变量:
PATH
SHELL
USER
UID
HOME
PWD
SHLVL
LANG
HOSTNAME
HISTSIZE
2.5 只读和位置变量
- 只读变量:只能声明,但不能修改和删除
声明只读变量:
readonly name
declare name
查看只读变量:
readonly -p - 位置变量:在脚本代码中调用通过命令行传递给脚本的参数
$1,$2,…:对应第1、2参数,shift[n[换位置
$0 :命令本身
$*:传递给脚本的所有参数,全部参数合为一个字符串
$@:传递给脚本的所有参数,每个参数为独立字符串
$#:传递给脚本的参数的个数
@@@*只在被双引号包起来的时候才会有差异
set –清空所有位置变量
eg:(umask 666; touch /data/f1) 一次性任务,开启子shell,执行后结束,不影响当前环境(name=wang;echo $name)echo $name{name=mage;echo $name;} {}影响当前环境echo $namex=1;echo \"pid=$$\";(echo\"subpid=$$\";echo \"subx=$x\"; x=2;echo \"subx2=$x\");echo x=$x
2.6 退出状态:
- 进程使用退出状态来报告成功或失败
0代表成功,1-255代表失败
$?变量保存最近的命令退出状态 - 例如:
ping -c1 -W1hostdowm &> /dev/null
ehco $? - bash自定义退出状态码
exit
:自定义退出状态码
注意:脚本中一旦遇到exit命令,脚本会 立即终止;终止退出状态取决于exit命令后面的数字
注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
3. 运算
3.1 算法运算:
-
bash中的算术运算:help let
+,-,*,/,%取模(取余),**(乘方)实现算法运算:let var=算术表达式var=$[算术表达式]var=$((算术表达式))var=$(expr arg1 and arg3...)declare -i var=数值echo ‘算术表达式’ | bc
-
乘法符号有些场景中需要转义,如*
-
bash有内建的随机数生成器:$RANDOM (0-32767)
echo $[$RANDOM%50]
:0-49之间随机数
3.2 赋值
- 增强型赋值:
+=,-=,*=,/= ,%= - let varOPERvalue
例如:let count+3= 自加3后自赋值 - 自增,自减:
let var+=1
let var++
let var-=1
let var–
3.3 逻辑运算
- 非:!
!1=0
!0=1 - 短路运算
短路与:&&
第一个为0,结果必为0
第一个为1,第二个必须参与运算
短路或: ||
第一个为1,结果必为1
第一个为0,第二个必须参与运算 - 异或:^
异或的两个值,相同为假,不同为真
0^1=1
0^0=0
1^0=1
1^1=0a=$[a^b];b=$[a^b];a=$[a^b];echo $a $b
互换值
- true,false
1,0 - 与:&
1&1=1
1&0=1
0&1=0
0&0=0 - 或:|
1|1=1
1|0=1
0|1=1
0|0=0
4.条件测试
4.1 条件测试
- 判断某需求是否满足,需要由测试机制来实现
专用的测试表达式需要由测试命令辅助完成测试过程 - 评估布尔声明,以便用在条件性执行中
若真,则返回0
若假,则返回1 - 测试命令:
test EXPRESSION
[EXPRESSION]
注意:EXPRESSION前后必须有空白字符窜
4.2 bash的字符串测试
-eq 是否等于-ne 是否不等于-gt 是否大于-lt 是否小于-le 是否等于或小于-ge 是否大于或等于= 比较字符串内容是否相同!= 比较字符串内容是否不同=~ 左侧字符串是否能够被右侧的pattern所匹配-z“string”字符串是否为空,空为真,不空位假-n \"string\" 字符串是否不空,不空为真,空位假注意:用于字符串比较时的用到的操作数应该使用引号
4.3 条件性的执行操作符
-
根据退出状态而定,命令可以有条件地执行
&&代表条件性的AND THEN
||代表条件性的OR ELSE -
例如:
grep -q no_such_user /etc/passwd || echo \'No such user\'NO shch userping -c1 -W2 station &> /dev/null && echo \"station1 is up \" || (echo \'station1 is unreachable\';exit 1)station1 is up
4.4 test命令
- 长格式的例子:
test \"$A\" = \"$B\" && echo \"strings are equal\"
test \"$A\" -eq \"$B\" && echo \"strings are equal\"
- 简要格式的例子:
[ \"$A\" = \"$B\" ] && echo \"strings are equal\"
[ \"$A\" -eq \"$B\" ] && echo \"strings are equal\"
4.5 bash的文件测试
- 存在性测试
-a file : 同-e
-e file :文件存在性测试,存在为真,否则为假 - 存在性及类别测试
-b file: 是否存在且为块设备-c file: 字符设备文件-d file: 目录文件-f file: 普通文件-h file或 -L file: 符号链接文件-p file: 命令管道文件-S file: 套接字文件
- 文件权限测试:
-r file:是否存在且可读
-w file: 写
-x file: 执行 - 文件特殊权限测试:
-u file:是否存在且拥有suid权限
-g file: sgid权限
-k file: sticky权限 - 文件大小测试:
-s file:是否存在非空 - 文件是否打开:
-t fd:fd 文件描述是否在某终端已经打开
-N file: 文件自从上一次被读取之后是否被修改过
-O file:当前有效用户是否为文件属组
-G file:当前有效用户是否为文件属组 - 双目测试
file1 -ef file2 : file1 是否是file2 的硬链接
file1 -nt file2:file1是否新于file2(Mtime)
file1 -ot file2 : file1是否旧于file2
4.6 bash的组合测试条件
- 第一种方式:
command1 && command2 并且
command1 || command2 或者
!command 非
如 [[ -t file ] && [ [ -w file ]] - 第二种方式:
expression1 -a expression2 并且
expression1 -o expression3
!expression
必须使用测试命令进行 - 示例:
[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
4.6 使用read命令来接受输入
使用read 来把输入值分配给一个或多个shell变量
-p: 指定要显示的提示-s: 静默输入,一般用于密码-n N 指定输入的字符长度N-d ‘字符’输入结束符-t N timeout 为N秒read 从标准输入中读取值,给每个单词分配一个变量所有剩余单词都被分配给最后一个变量read -p \"enter a filename:\" FILE
ifconfig ens333 | grep -Eo\" \\>(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]\\.){3} ([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\>\"
5.配置用户环境
5.1 防止扩展
- 反斜杠()会使随后的字符按原意解释
$echo Your cost:$5.00 - 加引号来防止扩展
单引号(’)防止所有扩展
双引号(\”\”)也防止所有扩展,但是以下情况例外:
$(美元符号) —— 变量扩展
`(反引号) —— 命令替换
(反斜线) —— 禁止单个字符扩展
!(叹号) —— 历史命令替换
5.2 bash的配置文件
1)全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
2)个人配置:
~/.bash_profile
~~/.bashrc
5.3shell登录两者方式
- 交互式登录:
直接通过终端输入账号密码登录
使用“su – UserName ”切换的用户
执行顺序:/etc/profile–> /etc/profile.d/ - 非交互式登录:
su UserName
图形界面下打开的终端
执行脚本
任何其他的bash示例
执行顺序:~/.bashrc–>/etc/bashrc–>/etc/profile.d/*.sh
5.4修改配置文件生效
- 修改profile和bashrc文件后生效
两种方法:
重新启动shell进程
.或source
例如: . ~/.bashrc
5.5 profile 类
- 按照功能划分,存在两类:
profile类和bashrc类 - profile类:为交互式登录的shell提供配置
全局:/etc/profile,/etc/profile.d/*.sh
个人:~/.bash_profile
功能:
用于定义环境变量
运行命令或脚本 - bash退出任务
1)保存在~./.bash_logout文件中(用户)
2)在退出登录shell时运行
3)用于创建自动备份,清除临时文件
5.6$-变量
- h: hashall,打开这个选项后,shell会将命令所在的路径hash下来,避免每次都要查询。通过set+h将h选项关闭
- i: interactive-comments,包含这个选项说明当前的shell是一个交互式的shell。所谓的交互式shell,在脚本中,i选项是关闭的
- m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等。
- 4)B:braceexpand,大括号扩展
- H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!”返回上最近的一个历史命令,\”!n\”
5.7 bash如何展开命令行
- 把命令行分成单个命令词
- 展开别名
- 展开大括号的声明({})
- 展开波浪符声明(~)
- 命令替换$()和 “)
- 再次把命令分成命令词
- 展开文件通配(*、?、[abc]等)
- 准备 I/O重定向(<>)
- 运行命令