shell脚本笔记
编辑脚本
vim /home/dmtsai/test.sh
编写shell规范:
1,声明解释器 #!/bin/bash
2,脚本功能注释, #此脚本的作用、使用场所、作者等
3,脚本内容,要执行的指令
脚本的执行方式:
1,添加x权限
2,使用bash之类的解释器读取脚本文件,比如bash test.sh 或者sh test.sh,新开启子进程(解释器)
3,使用source命令读取脚本文件,比如source test
source可以省略为 . 不开启子进程(解释器)
cat /etc/shells //显示系统所有解释器
vim /etc/profile //修改HISTSIZE决定能保存的历史命令数量,修改HISTSIZE=10决定能保存的历史命令数量
> .bash_history //清空历史记录文件
变量
什么是变量?以不变的名称存放的可能会变化的值
变量名=变量值
注意:等号两边不要有空格;
变量名仅由字母/数字/下划线组成,区分大小写;
变量名不能以数字开头,不要使用关键字和特殊字符;
若指定的变量名已存在,相当于为此变量重新赋值;
1.自定义变量,使用大小写字母,数字,下划线,不能以数字开头,不能使用特殊符号
引用变量: $变量名
查看变量:echo $变量名、echo ${变量名}
2.环境变量,变量名大写,由系统定义并且赋值完成,直接使用
PWD 当前位置
USER 当前用户名
HOSTNAME 主机名
SHELL 当前用户的解释器
HOME 当前用户的家目录
UID 当前用户的UID号
PATH 系统命令所在地
PS1 一级提示符
PS2 二级提示符
3.位置变量:在执行脚本时提供的命令行参数,表示为: $n,n为序号
4.预定义变量
$* 显示所有位置变量的值
$# 统计位置变量的个数
$$ 当前程序的进程号
$? 上一条指令的执行结果,0是正确,非0是异常
简单脚本技巧
单引号 ' ' -->用来界定范围,可以取消所有特殊字符的意义
双引号 " " -->用来界定范围
反撇号 ` `或者 $() --> 将命令的输出结果,直接参与另一条命令的运行
[root@queen ~]# date +%F 2020-06-16 [root@queen ~]# mkdir /opt/mydir-`date +%F` [root@queen ~]# ls /opt/ mydir-2020-06-16 [root@queen ~]# mkdir /opt/nsd-$(date +%F) [root@queen ~]# ls /opt/ mydir-2020-06-16 nsd-2020-06-16 [root@queen ~]# mkdir /opt/$(hostname)-$(date +%F) [root@queen ~]# ls /opt/ mydir-2020-06-16 nsd-2020-06-16 queen-2020-06-16
重定向输出:
>: 只收集前面命令的正确输出
2>: 只收集前面命令的错误输出
&>使用变量:收集前面命令的正确与错误输出
/dev/null:黑洞设备,专用于收集不要的输出信息
高级用法:
命令 | 标准输出 | 错误输出 |
---|---|---|
>/dev/null 2>&1 | 丢弃 | 丢弃 |
2>&1 >/dev/null | 丢弃 | 屏幕 |
[root@server0 ~]$ vim /root/user.sh #!/bin/bash read -p '请输入您要创建的用户名:' abc read -p '请输入您要设置的密码:' nsd useradd $abc &> /dev/null echo 用户$abc创建成功 echo $nsd | passwd --stdin $abc &> /dev/null echo 用户$abc密码设置成功 [root@server0 ~]$ sh /root/user.sh 请输入您要创建的用户名:
read -p '屏幕输出信息' #产生交互,必须要加上单引号,记录用户的输入信息
条件测试与选择
检查文件状态常用测试选项:
-e 文件名 #文档存在为真
-d 文件名 #文档存在且必须目录,才为真
-f 文件名 #文档存在且必须文件,才为真
-r 文件名 #文档存在且必须对其有读取权限,才为真
-w 文件名 #文档存在且必须对其有写入权限,才为真
-x 文件名 #文档存在且必须对其有执行权限,才为真
两个档案之间的比较:
-nt(newer than) #判断file1 是否比file2 新
-ot(older than) #判断file1 是否比file2 旧
-ef #判断file1 与file2 是否为同一档案,可用在判断hard link 的判定上。主要意义在判定,两个档案是否均指向同一个inode
多重条件判定:
-a #两状况同时成立!and
-o #两状况任何一个成立!or
! #反向条件
A任务 && B任务 A任务执行成功才执行B任务
A任务 || B任务 A任务执行失败才执行B任务
字符串判断:
-z 字符串 #判定字串是否为空 ?若string 为空字串,则为true
-n 字符串 #判定字串是否不为空 ?若string不为空字串,则为真。 -n亦可省略
字符串1 == 字符串 # 判定str1 是否等于str2 ,若相等,则为真
字符串 != 字符串 #判定str1 是否不等于str2 ,若不相等,则为真
[root@server0 ~]$ [ $USER == root ] [root@server0 ~]$ echo $? 0 [root@server0 ~]$ [ new != old ] [root@server0 ~]$ echo $? 0 #在中括号[] 内的每个元件都需要有空白键来分隔; #在中括号内的变数,最好都以双引号括号起来; #在中括号内的常数,最好都以单或双引号括号起来。
比较整数大小:
-gt #大于
-ge #大于等于
-eq #等于
-ne #不等于
-lt #小于
-le #小于等于
if分支语句:
#单分支 if 条件测试;then 命令序列 fi #双分支 if 条件测试;then 命令序列 else 命令序列2 fi #多分支 if 条件测试;then 命令序列 elif 条件测试;then 命令序列2 else 命令序列3 fi
case 分支 ,作用与if类似:
case 变量 in 模式1) 命令序列1 ;; 模式2) 命令序列2 ;; 模式3) 命令序列3 ;; *) 命令序列4 esac
函数,可以简化脚本
#格式 function 函数名 () { 命令序列 }
实例:
[root@queen ~]# vim test1.sh #!/bin/bash function printit(){ echo -n "Your choice is " #加上-n可以不断行继续在同一行显示 } echo "This program will print your selection !" case ${1} in "one") printit ; echo ${1} | tr 'az' 'AZ' #将参数做大小写转换! ;; "two") printit ; echo ${1} | tr 'az' 'A-Z' ;; "three") printit ; echo ${1} | tr 'az' 'A-Z' ;; *) echo "Usage ${0} {one|two|three}" ;; esac [root@queen ~]# sh test1.sh one This program will print your selection ! Your choice is one
循环:
for 变量名 in 变量值1 值2 。。。 do 命令序列 done #格式 while : do 命令序列 done
break 退出循环,继续执行循环之后的任务
continue 退出当前循环,继续下一次循环
exit 退出脚本
脚本测试
[dmtsai@study ~]$ sh 选项 test.sh 选项参数: -n :不要执行script,仅查询语法的问题 -v :再执行sccript 前,先将scripts 的内容输出到屏幕 -x :在执行时显示参数和命令
脚本写完后赋于x权限,可以放入计划任务中
chmod +x /opt/test2 crontab -e * * * * * /opt/test2