shell-进阶1

[root@centos8 ~]# lscpu Architecture:         x86_64 #架构 CPU op-mode(s):        32-bit, 64-bit #指令集 Byte Order:           Little Endian CPU(s):                8  #核数 On-line CPU(s) list:   0-7 Thread(s) per core:    1 #每个core 有几个线程 Core(s) per socket:    4 #每个槽位有4个core  Socket(s):             2 #服务器面板上有2个cpu 槽位 NUMA node(s):          2 #nodes的数量
反引号不能嵌套,$()可以嵌套使用
root@ubuntu2004:~# echo `date +%F`.txt 2022-04-15.txt root@ubuntu2004:~# ll `echo `date +%F`.txt` .txt: command not found ls: cannot access 'date': No such file or directory ls: cannot access '+%F': No such file or directory
root@ubuntu2004:~# echo $(date +%F).txt 2022-04-15.txt root@ubuntu2004:~# ll $(echo $(date +%F).txt) -rw-r--r-- 1 root root 0 Apr 15 12:37 2022-04-15.txt
输出信息 echo -n 不自动换行 -E 启用解释功能 -e 启用 \ 字符的解释功能 echo -e '\E[42;38;1;5m川哥\E[0m'

比较 “ ” ,‘ ’, ``三者区别
root@ubuntu2004:~# echo $HOSTNAME ubuntu2004 root@ubuntu2004:~# echo 'echo $HOSTNAME' echo $HOSTNAME root@ubuntu2004:~# echo echo $HOSTNAME echo ubuntu2004 root@ubuntu2004:~# echo `echo $HOSTNAME` ubuntu2004

#结论:

单引号:强引用,六亲不认,变量和命令都不识别,都当成了普通的字符串,最傻 双引号:弱引用,不能识别命令,可以识别变量,半傻不精 反向单引号:里面的内容必须是能执行的命令并且有输出信息,变量和命令都识别,并且会将反向单引号的内容当成命令进行执行后,再交给调用反向单引号的命令继续,最聪明
括号扩展:{ } root@ubuntu2004:~# echo {1..10} 1 2 3 4 5 6 7 8 9 10
变量引用
变量的生效范围等标准划分变量类型 1.普通变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell 进程均无效 2.环境变量:生效范围为当前shell进程及其子进程 3.本地变量:生效范围为当前shell进程中某代码片断,通常指函数
多个变量使用的时候一定用花括号括起来,不然会把下划线也当变量名的一部分
root@ubuntu2004:~# echo ${name}_$age chuange_21
root@ubuntu2004:~# echo $name_$age 21

环境变量

可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量。 一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程 一般只在系统配置文件中使用,在脚本中较少使用
root@ubuntu2004:~# export name=chuan root@ubuntu2004:~# declare -x name2=chuange

查看

env printenv export declare -x

位置变量

$1,$2,...对应第1个、第2个等参数,shift [n]换位置 $0 命令本身,包括路径 $* 传递给脚本的所有参数,全部参数合为一个字符串 $@ 传递给脚本的所有参数,每个参数为独立字符串 $# 传递给脚本的参数的个数
注意: $@ $*只在被双引号包起来的时候才会有差异
  $*`:表示将变量看成一个整体 `$@`:表示变量是独立的   $$当前所在进程的进程号,如`echo $$  

循环 while

说明: CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环,因此:CONDTION一般应该有循环 控制变量;而此变量的值会在循环体不断地被修正 进入条件:CONDITION为 true 退出条件:CONDITION为 false 无限循环
root@ubuntu2004:~# sum=0;i=1;while ((i<=100));do let sum+=i;let i++;done;echo $sum 5050
root@ubuntu2004:~# sum=0;for i in {1..100};do let sum+=i;done;echo $sum 5050
root@ubuntu2004:~# for ((sum=0,i=1;i<=100;i++));do let sum+=i;done;echo $sum 5050
root@ubuntu2004:/mysql# df |grep '^\/dev\/sd' |tr -s ' ' |cut -d   -f5 |tr -d % |sort -nr|head -1 13
root@ubuntu2004:/mysql# df |sed -En '/^\/dev\/sd/p' /dev/sda2                            999320  110432    820076  12% /boot /dev/sdb1                          20960256 2685944  18274312  13% /mysql
df |sed -En '/^\/dev\/sd/s#@#\1#p'
root@ubuntu2004:/mysql# df |sed -En '/^\/dev\/sd/s#.* ([0-9]+)%.*#\1#p' 12                                ^开头 \说明/无特殊含义  + [0-9]一个或多个 ()分组  第一个分组打印 s# #\1/p 13
-n 不输出模式空间内容到屏幕,即不自动打印 -E  使用扩展正则表达式
-r:使用扩展正则表达式

 

[root@Rocky8 ~]# cat while_diskcheck.sh  #!/bin/bash WARDING=2 while :;do USE=`df |sed -rn '/^\/dev\/sd/s#.* ([0-9]+)%.*#\1#p'` if [ ${USE} -gt ${WARDING} ];then     echo Disk will be full 192.168.80.171 | mail -s disk warning [email protected] fi sleep 1 done
-n可用于测试shell脚本是否存在语法错误,但不会实际执行命令。
-x选项使shell在执行脚本的过程中把它实际执行的每一个命令行显示出来


$[]和$(()) 是一组 标识的是 算术运算 +-*/%
[root@Rocky8 script]# echo $(($RANDOM%33+1)) 15

 

[root@Rocky8 script]# cat  600W双色球.sh  #!/bin/bash #FileName :600W.sh  RED='\033[31m'  BLUE='\033[34m'  END='\033[0m'  echo -en $RED 红色:$END   #sleep 3    while true;do     red=$[$RANDOM%33+1]     echo $redstring | grep -qw $red && continue     echo -ne  $RED$red$END     redstring=$redstring $red     sleep 1     [ `echo $redstring | awk {print NF}` -eq 6 ] && break done echo  echo -ne $BLUE 篮球:$END \t; sleep 1 echo -e $BLUE $[ $RANDOM%16+1 ] $END 

[root@Rocky8 etc]# echo --- 22 --- 33 --- 44| awk '{print NF}'
6
[root@Rocky8 etc]# echo --- 22 --- 33 --- 44| awk '{print $NF}'
44

前者是输出了域个数,后者是输出最后一个字段的内容

grep -q 不打印,静默 -w 精准匹配

 

[root@Rocky8 script]# bash 600W双色球.sh   红色: 5 26 3 2 10  篮球:      3 

 

[root@Rocky8 script]# cat chess1.sh  #!/bin/bash  for i in {1..8};do         temp1=$[ $i % 2 ]          for j in {1..8};do         temp2=$[ $j % 2 ]          if [ $temp1 -eq  $temp2  ];then                 echo -e -n \033[47m  \033[0m         else                 echo -e -n \033[41m  \033[0m         fi          done          echo  done [root@Rocky8 script]# cat chess6.sh  #!/bin/bash #Author:wang red(){     echo -e \033[41m        \033[0m\c } yel(){     echo -e \033[43m        \033[0m\c     } redyel(){     for ((i=1;i<=4;i++));do         for ((j=1;j<=4;j++));do             red;yel         done         echo     done } yelred(){     for ((i=1;i<=4;i++));do         for ((j=1;j<=4;j++));do             yel;red         done         echo      done } for ((line=1;line<=8;line++));do     [ $[$line%2] -eq 0 ] && redyel || yelred done
View Code

&>  标准输出错误输出都丢弃

[root@Rocky8 script]# cat url.sh  #!/bin/bash while read url;do curl $url &> /dev/null || echo $url is failed done < curl.txt [root@Rocky8 script]# bash  url.sh  www.chuan.com is failed

 

[root@Rocky8 script]# cat url.sh  #!/bin/bash cat curl.txt | while read url;do curl $url &> /dev/null || echo $url is failed done

while read 双变量报警

[root@Rocky8 script]# df |sed -En '/^\/dev\/sd/s#^([^ ]+).* ([0-9]+).*#\1 \2#p' /dev/sda1 26
[root@Rocky8 ~]# cat  while_diskcheck2.sh #!/bin/bash WARDING=2 df | sed -En '/^\/dev\/sd/s#^([^ ]+).* ([0-9]+).*#\1 \2#p' | while read DISK USE ;do  [ ${USE} -gt ${WARDING} ] && echo $DISK will be full ,use $USE | mail -s disk warning [email protected] done

 

循环 until

while 取反

[root@Rocky8 ~]# sum=0;i=1;until ((i>100));do let sum+=i;let i++;done;echo $sum
5050

[root@Rocky8 ~]# sum=0;i=1;until  ! ((i<=100));do let sum+=i;let i++;done;echo $sum 5050

 

循环控制语句 continue

提前结束第N层的本轮循环,而直接进入下一轮判断
[root@Rocky8 ~]# for i in {1..10};do [ $i -eq 5 ] && continue;echo $i;done 1 2 3 4 6 7 8 9 10 [root@Rocky8 ~]# for i in {1..10};do [ $i -eq 5 ] && break;echo $i;done 1 2 3 4

循环控制 shift 命令

shift [n] 用于将参量列表 list 左移指定次数,缺省为左移一次。 参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用到 shift
[root@Rocky8 script]# bash  useradd.sh e f g h e is created g is created [root@Rocky8 script]# cat useradd.sh  #!/bin/bash while [ $1 ];do     useradd $1 && echo $1 is created     shift 2   done

 

[root@Rocky8 script]# cat   guess.sh  #!/bin/bash COLOR='echo -e \E[1;36m' END='\E[0m'  read -p 请输入你想猜的数字大小区间(10或10的倍数),此大小区间决定你能猜的次数(q退出游戏): INPUT_NUM  if [ $INPUT_NUM = q ] &> /dev/null;then exit elif [[ $INPUT_NUM =~ ^[1-9]+[0]+$ ]] &> /dev/null;then  NUM=$[RANDOM%$INPUT_NUM] var=0 if [ $INPUT_NUM -lt 500 ];then     var=6 elif [ $INPUT_NUM -lt 1000 ];then     var=8 else     var=10 fi $COLOR 本轮你可以猜想$var次 $END     while [ $var -ne 0 ] ;do     echo              read -p 请输入你猜的数字: TEST_NUM             if [ $TEST_NUM -gt $INPUT_NUM ] &> /dev/null;then                 $COLOR 你输入了错误的数值,你浪费了一次机会! $END                 let var-=1               elif [ $TEST_NUM -eq $NUM ] &> /dev/null;then                 echo -e \E[1;33m 你猜对了! $END                 break              elif [ $TEST_NUM -lt $NUM ] &> /dev/null;then                 $COLOR 数字太小了! $END                 let var-=1              elif [ $TEST_NUM -gt $NUM ] &> /dev/null;then                  $COLOR 数字太大了! $END                 let var-=1              elif [ $TEST_NUM = q ] &> /dev/null;then                 $COLOR 再见~ $END                 exit             else                 $COLOR 请输入数字! $END             fi                [ $var -gt 0 ] && echo -e 你还剩余次数:\E[1;31m$var\E[0m || echo -e \E[1;31m你已经失败了!\E[0m     done else     $COLOR 请输入正确的区间! $END     ./guess.sh fi

 select 菜单

[root@Rocky8 script]# select menu in a b c d e 退出; do echo $menu;[ $REPLY -eq 6 ] && break;done 1) a 2) b 3) c 4) d 5) e 6) 退出 请输入字母编号6 退出

函数调用

[root@Rocky8 script]# cat   install_nginx2.sh  #!/bin/bash NGINX_VERSION=1.20.2 INSTALL_DIR=/apps/nginx  color () {     RES_COL=60     MOVE_TO_COL=echo -en \\033[${RES_COL}G     SETCOLOR_SUCCESS=echo -en \\033[1;32m     SETCOLOR_FAILURE=echo -en \\033[1;31m     SETCOLOR_WARNING=echo -en \\033[1;33m     SETCOLOR_NORMAL=echo -en \E[0m     echo -n $1 && $MOVE_TO_COL     echo -n [     if [ $2 = success -o $2 = 0 ] ;then         ${SETCOLOR_SUCCESS}         echo -n $  OK       elif [ $2 = failure -o $2 = 1  ] ;then         ${SETCOLOR_FAILURE}         echo -n $FAILED     else         ${SETCOLOR_WARNING}         echo -n $WARNING     fi     ${SETCOLOR_NORMAL}     echo -n ]     echo }  install_nginx(){     wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz || { echo 下载失败!;exit 20;  }     tar xf nginx-${NGINX_VERSION}.tar.gz -C /usr/local/src     yum -y install gcc openssl-devel pcre-devel     cd /usr/local/src/nginx-${NGINX_VERSION}     ./configure --prefix=${INSTALL_DIR} --with-http_ssl_module     make -j `grep -c processor /proc/cpuinfo`&& make install     if [ $? -ne 0 ];then         color Install nginx is failed! 1         exit 10      else         color Install nginx is finished! 0     fi } prepare_html(){     echo <h1>welcome to 川哥 nginx website </h1> > ${INSTALL_DIR}/html/index.html } start_nginx(){     /apps/nginx/sbin/nginx }  main () {     install_nginx     prepare_html     start_nginx }  main

 

 trap 捕捉信号
[root@Rocky8 script]# cat trap.sh  #!/bin/bash trap echo 'Press ctrl+c or ctrl+\ '  int quit  #两个信号 trap -p for((i=0;i<=10;i++)) do         sleep 1         echo $i done trap ''  int  #忽略并打印 trap -p for((i=11;i<=20;i++)) do         sleep 1         echo $i done trap '-'  int  #忽略 trap -p for((i=21;i<=30;i++)) do         sleep 1   #撤销         echo $i done

退出触发finish函数

[root@Rocky8 script]# cat trap_finish.sh  #!/bin/bash finish(){     echo Finish at  `date +%F_%T` | tee -a  /root/finish.log }  trap finish exit  while true ;do     echo running     sleep 1 done

创建临时文件,确保唯一

[root@Rocky8 data]# mktemp chuanXXX chuanLqq [root@Rocky8 data]# mktemp -d XXXchuandir Dwrchuandir