shell编程
Shell 也是一种程序设计语言,它有变量,关键字,各种控制语句,有自己的语法结构,利用shell程序设计语 可以编写功能很强、代码简短的程序 #! Shebang 定义解释器 #!/usr/bin/python #!/bin/bash
执行脚本的方式 1> sh,bash (这俩种可以不指定解释器,默认就是/bin/bash) (这俩子shell里面的命令不会影响到父shell) 2>.空格 ,source (这俩子shell里面的命令会影响到父shell) 3> ./(需要执行权限) sh -n :检查语法 sh -x : 打印脚本,打印变量的值
变量
预定义变量 echo $? 打印上一次命令是否执行成功 echo $$ 当前进程的pid echo $! 后台运行的最后一个pid号 $0: 脚本的名字 set 查看所有变量
环境变量 任何环境都可以使用环境变量,父子都可以 子shell里面定义的环境变量不会影响父shell的 查看当前系统的环境变量 : env 常用的环境变量: $USR,$UID,$HOSTNAME,$HOME,PWD PS1 PATH 父shell里面定义的环境变量会影响子shell的(全局生效) 永久生效需要写到配置文件里面:写到4个登陆脚本中 ~/.bashrc ~/profile 更好放在/etc/profile.d/* 下建立独立的环境变量配置文件
自定义变量 变量名=值 推荐:驼峰命名法 变量名以字母,下划线,数字组成 引用变量:$变量名 或${变量名} unset : 取消变量
练习:查看ip ip -f inet a dev show dev ens33 | awk 'NR==2{print $2}' | cut -d/ -f1 -f指定ipv4的网 (2)安装 yum -y install net-tools ifconfig ens33 | awk 'NR==2{print $2}' NF:倒数第一列 如果网卡名字不是ens33呢? ip a | grep "2:" | awk '{print $2}' | tr -d ";" ---把:给删除 ----------------- a=12345asdfg echo ${a} | tr -d [:digit:] --去除数字 asdfg
变量read (交互) -p : 打印 -t :等待时间 -s :隐藏输入,没有回显 取消回显: 1.ho $ 2.stty -echo(一遍设置,再输一遍就取消了)
变量运算 $ (()) , $[] ,expr它的乘法要转义 , '*' \* scale =3;bc
case $num in 1): ;; 2): ----- : 冒号:跳过,可以不执行 ;; 3): ;; 4)con_ip ;; *): ;; esac
[root@master1 ~]# name=cat [root@master1 ~]# cat=dog [root@master1 ~]# eval echo '$' $name $ cat [root@master1 ~]# echo '$'$name $cat [root@master1 ~]# eval echo '$'$name dog eval : 执行字符串的内容
位置变量 判断位置变量$1是否存在,如果不存在,则给变量赋值为0 x=${1:-0} y=${2:-0} echo $(($x+$y)) — :没有给默认值,给它赋值为0 = :不用管给它传输值,直接给它赋值 + :有默认值的时候 ,给它赋值0;没有默认值的时候,不赋值,什么也没有 ---------------------------- name=aaa unset name echo ${name:? 无法获取} ?:打印错误信息 ------------------------- 取值 a=www.baidu.com echo ${a##*.} baidu.com echo ${a%%.*} com #:切左边 %:切右边 ------------ a=1234567 echo ${a:2:2} 34
for循环
### for 循环 ``` 格式: a.sh for i in {1..100} #循环范围 空格 tab 回车 do #循环体 done sh a.sh ----------------- for i in seq do echo $i done seq 2 2 100 ---------------------- for i in {1..254} do ping -c2 -w2 192.168.19.$i done ---------------------- for i in seq do echo i done [root@master1 ~]# seq -w 1 5 01 02 03 04 05 ------------------------- cat <<EOF ; ====================================== ; == 1.touch a.txt * ; == 2.echo "hello" * ; == 3.systemctl stop firewarld * ; == 4.systemctl enable network * ; == 5.systemctl disable selinux * ; == q.exit * ; ====================================== ; EOF ; read -p "请输入数字:" num ; case $num in ; 1) touch a.txt ; ;; ; 2) echo "hello" ; ;; ; 3) systemctl stop firewalld ; ;; ; 4) systemctl enable network ; ;; ; 5) systemctl disable selinux ; ;; ; q) exit ; ;; ; *) echo "输入错误" ; esac --------------------------- ``` ```ini while 循环语句,可以做有限循环和无限循环,循环的条件是条件为真 a=0 while [ $a -lt 100 ] do echo "$a hello" a=$[ $a + 1 ] done ``` ```ini yum install -y net-tools | while read line do echo "安装成功 $line" done while 把前面的输出以行的格式交给while,read来读取每一行, 并把这些行重新打印,还可以把结果加内容,改颜色 ``` ```ini a=0 while read 1 do echo 开始安装 $1 yum install -y $1 &>/dev/null if [ $? -eq 0] ; then echo "安装成功" else echo "安装失败" fi let a++ / a=$[$a + 1] done < ./a.txt
break
#!/bin/bash # break n,默认为1 for (( a=1; a<=3; a++ )) do echo "Outer loop : $a" for (( b=1; b < 100; b++ )) do if [ $b -gt 4 ] then break 2 fi echo " Inner loop:$b" done done ————————————————
判断是否为root用户 if [ $USER == "root" ] ; then echo "当前登录为root用户" else echo "当前登录不是root用户"
eval echo '$'$name --eval:执行字符串的内容 name=cat cat=dog echo $name cat eval echo '$'$name dog
[root@master1 ~]# name=peiqi [root@master1 ~]# echo ${name:?无法获取节目} peiqi [root@master1 ~]# unset name [root@master1 ~]# echo ${name:?无法获取节目} bash: name: 无法获取节目 ?:提示错误信息
a=1234567 echo ${a:2:2} 34
basename&direname
脚本必须在某个路径下执行
basename --目录 direname --文件 dirname 获取当前脚本的路径 $( cd $( dirname $0 ) ; pwd ) #判断脚本的位置 path=$( cd $( dirname $0 ) ; pwd ) [[ $path = '/root' ]] && echo "继续执行" || echo "请在/root目录下执行"
##判断test##
test -f /etc/passwd test -d /etc/opt if [ -d /opt/backup ] ; then echo "文件已存在" else mkdir /optbackup test -e 只要存在就是真的 [$age =~^[0-9]+$ ] 数字开头,数字结尾
数组
a=(sd ff dd jj ff mm we) echo $a #默认打印第一个 sd echo ${a [@]} #打印每一个 echo ${a [1]} #打印 ff echo ${a [-1]} #打印倒数第一个 echo ${#a [@]} #打印数组内元素的数量 echo ${!a [@]} #打印元素的索引 切片 切片 echo ${a[@]:2:3}
正则表达式
[root@master1 ~]# grep -n -i "r[fagsvar]" /etc/passwd --匹配[]里面的任意一个字符 10:operator:x:11:0:operator:/root:/sbin/nologin 17:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
[root@master1 ~]# grep -n -i "^r" /etc/passwd --匹配以r开头的 [root@master1 ~]# grep -n -i "." /etc/passwd --匹配所有 [root@master1 ~]# grep -n "[A-Z]" /etc/passwd 12:ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin 13:nobody:x:99:99:Nobody:/:/sbin/nologin 14:systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin 15:dbus:x:81:81:System message bus:/:/sbin/nologin 16:polkitd:x:999:998:User for polkitd:/:/sbin/nologin 17:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
[root@master1 ~]# grep -n "\<r..t\>" /etc/passwd --以r开头,以t结尾 1:root:x:0:0:root:/root:/bin/bash 10:operator:x:11:0:operator:/root:/sbin/nologin ---------------------- \s:匹配空格 [root@master1 ~]# egrep "^[0-9]+$" /etc/passwd [root@master1 ~]# egrep "-d" /etc/passwd 都是查找数字 ------------------------------------- =:等于 =~:匹配 [root@master1 ~]#[[ "abc" =~ a.c* ]] 匹配abc是否在后面的里面
<<! ! --shell的多行注释