SciRui 2019-11-12
shell 翻译官 shell脚本 工具,提高工作效率 命令 交互式 脚本 非交互式 cat /etc/shells 查看拥有的解释器 yum -y install ksh 安装新解释器 bash优点 历史命令,快捷键,tab键,重定向,管道
脚本的格式:
1,声明解释器类型 #!/bin/bash 2,注释,说明该脚本的作用,变量的含义等
3,编写代码
写完后,赋予脚本执行权限 chmod +x test1.sh
执行脚本的方法:
1, ./test1.sh 使用绝对路径或者相对路径执行脚本 ,需要x权限 2, bash test1.sh 调用另外一个bash执行脚本,开启子进程 3, source test1.sh 使用当前解释器执行脚本,不开启子进程
#!/bin/bash mkdir /opt/abc cd /opt/abc
#!/bin/bash echo 123 sleep 1000
#!/bin/bash #部署yum软件仓库 rm -rf /etc/yum.repos.d/*.repo echo "[abc] name=abc baseurl=http://172.25.254.254/content/rhel7.0/x86_64/dvd/ enabled=1 gpgcheck=0" > /etc/yum.repos.d/abc.repo
#!/bin/bash #部署vsftpd服务 yum -y install vsftpd &> /dev/null systemctl restart vsftpd systemctl enable vsftpd
==============================
常量 固定不变
变量 灵活多变,增加灵活,增加功能
变量的种类
1,自定义变量
变量名称=变量的值 名称必须是字母数字下划线,不能以数字开头,不能使用特殊符号 a=10 定义变量 echo $a 查看变量的值 echo ${a}RMB 输出变量+常量,大括号用来界定容易混淆的名称 unset a 取消变量 echo $a 再次查看
2,环境变量,系统自带
USER当前用户名 UID当前用户的id号 HOME当前用户的家目录 PWD当前位置 SHELL当前用户使用的解释器 HOSTNAME主机名 PS1一级提示符 PS2二级提示符 PATH存放命令的路径
echo $PS1 显示一级提示符 [\\h \W]\$ PS1=dachui 修改 PS1=‘[\\h \W]\$‘ 还原
3,位置变量与预定义变量
$1 $2 $3 ..... $0脚本名 $$进程号 $#位置变量的个数 $*所有的位置变量 $?上一条指令的结果,0是成功, 非0是失败
env 查看所有环境变量 set 查看所有变量
变量的扩展应用
"" 界定范围 ‘‘ 界定范围,屏蔽特殊符号 touch "a b" 创建一个带空格文件 touch ‘x y‘ 创建一个带空格文件 a=10 echo "$a" 显示变量a中的值 echo ‘$a‘ 显示$a `` 反撇号, 可以获取命令的执行结果 a=ls 变量a的值是ls a=`ls` 变量a的值是ls执行的结果 a=$(ls) 变量a的值是ls执行的结果
stty -echo 屏蔽回显 stty echo 恢复回显
a=100 通常创建的变量是局部变量 ,只在某个解释器中生效 export 发布全局变量,使任何解释器(子进程中均可使用) a=100 export a 将a发布为全局变量 export b=200 创建并发布全局变量 bash 进入新解释器(子进程) echo $a 可以使用之前发布的变量 echo $b exit 返回 export -n b 取消变量b的全局状态,恢复为局部变量
===============================
shell中的运算
方法一: expr 1 + 1 加 expr 2 - 1 减 expr 2 \* 2 乘 \ 转义符号 ,可以屏蔽之后1个字符的特殊含义 expr 4 / 2 除 expr 4 % 2 求模(取余数) a=10 b=20 expr $a + $b expr $a + 10 expr $a + $a
方法二: echo $[1+1] echo $[2-1] echo $[2*2] echo $[2/2] echo $[2%2] echo $[a+b] echo $[a+20]
方法三: let 运算结果不显示, 通常用于变量创建或者变量自增减
let a=5+5 创建变量a
变量自增减
主流写法: let a-- 相当于 let a=a-1 let a++ 相当于 let a=a+1 let a+=2 相当于 let a=a+2 let a-=2 相当于 let a=a-2 let a/=5 相当于 let a=a/5 let a*=4 相当于 let a=a*4 let a%=4 相当于 let a=a%4
bc 计算器 ,可以小数运算 echo "scale=3;10/3" | bc
/bin/bash 历史记录,快捷键,tab键,重定向,管道
规范的shell脚本:
声明解释器 #!/bin/bash 注释,脚本功能,变量的作用 代码
1,添加x权限 2,调用解释器直接执行 bash XXX.sh 3,source XXX.sh
1, 自定义变量 变量名=变量的值 echo ${a}XXX unset a 2,环境变量 USER UID HOME HOSTNAME SHELL PWD PS1 PS2 PATH 3,位置变量与预定义变量 $1 $2 $3..... $0 $$ $# $* $?
"" ‘‘ ` $() read -p "XXX" n stty -echo stty echo export a 发布全局变量
expr 1 + 1 echo $[1+1] let a=10+3 let a++ let a*=10 bc
=================================
1,字符串的测试 == 判断两边的内容是否相等 != [ a == a ] a是否等于a echo $? 结果是0 [ a == b ] echo $? 结果非0 [ root == $USER ] 我是不是管理员,结果是0 su - abc 切换普通用户之后在测试,结果非0
a=10 b= [ -n "$a" ] 判断$a是否非空 echo $? [ -n "$b" ] 判断$b是否非空 echo $? [ ! -n "$b" ] 上述判断取反,判断$b是否为空 echo $? [ -z "$a" ] 判断$a是否为空 echo $? [ -z "$b" ] 判断$b是否为空 4, 逻辑测试 && 符号之前的任务成功后,才执行之后的任务 || 符号之前的任务失败后,才执行之后的任务 ls && ls 第一个任务成功了,会继续执行第2个任务, 一共执行两次ls ls || ls 第一个任务成功了,不会继续执行第2个任务, 一共执行1次ls [ -z $1 ] && exit 如果$1为空, 就会执行exit退出脚本 两个逻辑符号: 在ls都执行成功的情况下 ls && ls && ls 执行3次ls ls && ls || ls 第1次执行,第2次执行,第3次不执行 ls || ls || ls 第1次执行,后面都不执行 ls || ls && ls 第1次执行,第2次不执行,第3次执行 [ root == $USER ] && echo "我是管理员" || echo "我不是管理员"
2,数字的测试 -eq等于 -ne不等于 -gt大于 -ge大于等于 -lt小于 -le小于等于 [ 1 -eq 1 ] 1等于1, echo $? 结果是成功 [ 0 -eq $USER ] 我的id号是否为0,管理员运行的话,结果是成功
两种不同写法,可以实现相同目的: [ -z $n ] && echo "你倒是给个名字啊!" && exit [ -n "$n" ] || echo "你倒是给个名字啊!" [ -n "$n" ] || exit
要求,每2分钟检查系统登录账户数量,如果超过3人登录,给管理员发报警邮件 #!/bin/bash x=`who | wc -l` [ $x -gt 3 ] && echo "有人***服务器!隔壁老王来了!" | mail -s test root mail 查邮件 crontab -e */2 * * * * /opt/test1.sh chmod +x test1.sh
3,文件的测试 -e 是否存在 -f 是否存在且为普通文件 -d 是否存在且为目录 -r -w -x 判断当前用户对某文件是否有相关权限 [ -e abc ] abc是否存在,不关心文件类型 [ -f abc ] abc是否存在,必须是文件 [ -d abc ] abc是否存在,必须是目录 [ -r abc ] 当前用户对文件abc是否有读权限,管理员无效 [ -w abc ] 当前用户对文件abc是否有写权限,管理员无效 [ -x abc ] 当前用户对文件abc是否有执行(目录是进入的)权限
================================
== != -z -n
-eq -ne -gt -ge -lt -le
-e -f -d -r -w -x
&& || ;
种类1: 单分支 if 条件测试 ;then 执行指令 fi
#!/bin/bash if [ ! -d /opt/xyz ] ;then mkdir /opt/xyz echo 123 fi
双分支 if 条件测试 ;then 执行指令1 else 执行指令2 判断当前目录是否有a目录,没有就创建 fi
#!/bin/bash if [ -f a ] ;then rm -rf a mkdir a else [ -d a ] || mkdir a fi
多分支 if 条件测试1 ;then 执行指令1 elif 添加测试2 ;then 执行指令2 else 执行指令3 fi
============================
ping -c 3 -i 0.2 -W 1 172.25.0.13
#!/bin/bash read -p "请输入ip地址" ip ping -c 3 -i 0.2 -W 1 $ip &> /dev/null if [ $? -eq 0 ] ;then echo "通了!" else echo "不通!" fi
#!/bin/bash x=$[RANDOM%10] read -p "请输入一个数字(0-9)" n if [ $x -eq $n ] ;then echo "猜中了!" elif [ $n -lt $x ] ;then echo "猜小了" else echo "猜大了" fi
========================
for循环 有次数限制 可以关注循环次数或者变量 for 变量名 in 值1 值2 值3...... do 执行指令 done
!/bin/bash```
for i in {1..10} 循环10次,此方式不支持变量比如{1..$a}
do
echo 123
echo $i
done
#!/bin/bash a=10 for i in `seq $a` 使用变量循环10次 do echo 123 echo $i done
172.25.0.1~172.25.0.15 #!/bin/bash for i in {1..15} do ping -c 3 -i 0.2 -W 1 172.25.0.$i &> /dev/null if [ $? -eq 0 ] ;then echo "172.25.0.$i 通了" else echo "172.25.0.$i 不通" fi done
#!/bin/bash x=0 y=0 for i in {1..15} do ping -c 3 -i 0.2 -W 1 172.25.0.$i &> /dev/null if [ $? -eq 0 ] ;then echo "172.25.0.$i 通了" let x++ else echo "172.25.0.$i 不通" let y++ fi done echo "$x台通了,$y台不通"
test 表达式 [ 表达式 ] 1,字符串 == != -n -z 2,逻辑测试 && || ; 3,数字 -eq -ne -gt -ge -lt -le 4,文件 -e -d -f -r -w -x
if 单分支 双分支 多分支 if 条件测试1 ;then 执行指令1 elif 条件测试2 ;then 执行指令2 else 执行指令n fi
循环 for 变量名称 in 值 do 执行指令 done while : do 执行指令 done
ping -c -i -W RANDOM 200行
===========================
case分支 ,功能类似if,不如if强大,代码比if精简
模式1) 执行指令1 ;; 模式2) 执行指令2 ;; *) 执行指令n esac
#!/bin/bash case $1 in t|T) touch $2;; m|M|mm) mkdir $2 echo 123;; r) rm -rf $2;; *) echo "请输入t|m|r" esac
scp lnmp_soft.tar.gz :/opt
在虚拟机中释放该目录,并将其中的nginx-1.10.3.tar.gz拷贝到/opt下
#!/bin/bash yum -y install gcc openssl-devel pcre-devel &> /dev/null tar -xf nginx-1.10.3.tar.gz cd nginx-1.10.3 ./configure make make install 执行完脚本后运行 /usr/local/nginx/sbin/nginx 关闭防火墙 systemctl stop firewalld 使用真机浏览器访问172.25.0.11可以看到欢迎页面
echo -e "\033[92mABCD\033[0m"
函数名称 (){ 指令 } cecho (){ echo -e "\033[$1m$2\033[0m" }
中断和退出 exit 退出脚本 break 退出循环,继续执行循环之后的任务 continue 退出当前循环,继续下一次循环
从键盘循环取整数(0结束)并求和,输出最终结果 #!/bin/bash x=0 while : do read -p "请输入一个数字" n [ -z $n ] && exit [ $n -eq 0 ] && break let x+=n done echo $x
找出1~20以内6的倍数,并输出她的平方值
#!/bin/bash
for i in {1..20}
do
x=$[i%6] x是余数
[ $x -eq 0 ] || continue 余数等于0就继续下面的任务
echo $[i*i]
done
===============================
1,字符串的截取,第一个字符系统定义序号是0 ${变量名:起始位置:长度} echo ${a:1:1} 截取变量a,从第2个字符向后符截取1位 echo ${a:4:2} 截取变量a,从第5个字符向后符截取2位 echo ${a:0:2} 截取变量a,从第1个字符向后符截取2位 ,且0可以省略
获取一位随机字符的脚本: #!/bin/bash a=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV WXYZ0123456789 x=$[RANDOM%62] echo ${a:x:1}
获取8为随机密码的脚本: #!/bin/bash a=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV WXYZ0123456789 for i in {1..8} do x=$[RANDOM%62] p=${a:x:1} pa=$pa$p done echo $pa
2 字符串的替换 a=aabbccdd ${变量名/old/new} 替换一个old为new ${变量名/a/6} a换成6 ${变量名//old/new} 替换所有old为new ${变量名//a/6} 所有a换成6 ${变量名/old/} 删除一个old ${变量名//old/} 删除所有old
3,字符串的删除 ${变量名#被删除的内容} 掐头 a=`head -1 /etc/passwd` echo $a root:x:0:0:root:/root:/bin/bash
echo ${a#root} 删除第一个root echo ${a#root:x} 删除root:x echo ${a##*root} 删除到最后一个root,以及该root左边所有
思考如何删除之后剩余 echo ${a#*:root:} /root:/bin/bash
${变量名%被删除的内容} 去尾 echo ${a%bash} 从右往左删除,到bash echo ${a%%/*} 从右往左删除,到最后一个/ ,以及/右边所有