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