文章目录
- 一、第一天(Shell脚本编程基础)
- 作者视频ppt部分
- 作者视频操作
- 编写一个hello.sh可执行文件
- 使hello.sh可以到处运行
- 没有执行权限的执行方式
- 下载httpd(web服务器)
- curl字符界面浏览器
- 命令列表
- 凌乱笔记
- 作业
- 重点:
- 第二天(shel脚本编程基础之变量用法详解)
- 总结:脚本错误常见的有三种
- 课堂操作
- 变量的赋值方式
- 探索变量赋值
- 第三天(shell脚本编程基础之变量用法详解)
- 部分ppt
- 课堂操作
- 操作变量
- 环境变量的继承
- 系统环境变量
- 显示系统信息,编写systeminfo.sh 文件
- 第四天(脚本编程变量详解)
- 部分ppt
- 课堂操作
- 老师优化过的系统信息脚本
- 使ip地址固定(固定网卡)
- 使用位置变量
- 安全删除(实则移动)
- \$*和\$@的区别
- 第五天(脚本编程特殊变量和脚本安全avi)
- 部分ppt
- 课堂操作
- 脚本错误立即退出
- 错误的危险脚本
- 第六天(shell脚本编程中的算术和逻辑运算)
- 部分ppt
- 课堂操作
- 计算的例子
- 随机字体颜色
- 鸡兔同笼问题
- 异或运算,使x,y的值对换
- 第七天(shell脚本编程之测试语句test实现变量数字和字符串判断详解)
- 部分ppt
- 课堂操作
- 年龄相加
- 查看是否存在n变量
- 判定字符串
- 第八天(shel脚本编程之条件测试语句实现逻辑判断详解)
- 部分ppt
- 课堂操作
- [[]]中使用扩展的正则表达式
- 字符串的判定
- 判定是否为文件夹
- 第九天(shel脚本编程条件判断和接入输入处理)
- 课堂操作
- 判定用户是否存在
- 硬盘容量和节点告警
- linux 设置邮箱
- read操作,和用户交互
- 是否有钱脚本
- 第十天(shell环境配置文件)
- 课堂操作
- 管道命令会开启一个子进程
- vim管理器方式复制错位,自动对齐
- 第十一天(shell编程的条件判断if和case讲解)
- 课堂操作
- 判定胖瘦
- 修改tab键变4个空格
- yesORno脚本
- 第十二天(shell脚本编程进阶之for循环)
- 部分ppt
- 课堂操作
- 循环输出1~10
- 循环1加到100
- 打印.log类型的路径
- sum.sh,相加文件编写
- 99乘法表,for
- 第十三天(shell脚本编程进阶之for循环语法2)
- 部分ppt
- 课堂操作
- 文件改名,后缀都改为bak,for_rename.sh
- 面试题:创建YYYY-MM-DD,当前日期一年前365天到目前共365个目录,里面有10个文件
- 测试网络的网络是否连通
- 打印背景颜色
- 第十四天(shell脚本编程进阶之while循环和continue和break)
- 部分ppt
- 课堂操作
- 系统初始化设置脚本
- 第十五天(shell脚本编程进阶之shift与select相关技术)
- 部分ppt
- 课堂操作
- shift.sh示例
- select示例
- 第十六天(shell编程脚本进阶之函数)
- 课堂操作
- 关闭防火墙脚本
- 第十七天(shell脚本编程进阶之函数高级用法递归)
- 课堂操作
- local变量
- 环境函数
- 函数递归-阶乘
- fork炸弹
- 第十八天(shell脚本编程进阶之高级工具expect等)
- 部分ppt
- 课堂操作
- 安全退出处理
- 一旦接受到回车,发送消息
- 使用脚本登录ssh
- 替我传输文件
- 替我人工登录ssh
- expect位置参数
- shell脚本调用expect
- 第十九天(shell脚本编程进阶之数组)
- 部分ppt
- 课堂操作
- 生成数组
- 第二十天(shell脚本编程进阶之变量和字符串高级用法)
- 课堂操作
- 处理数组
- 生成10个随机数保存于数组中,并找出其最大值和最小值
- 字符串切片
- eval变量的间接调用
- 参考文档
一、第一天(Shell脚本编程基础)
作者视频ppt部分
-
1、编程基础
Linus: Talk is cheap, show me the code -
1.1 程序组成
程序: 算法+数据结构
数据:是程序的核心
算法:处理数据的方式
数据结构: 数据在计算机中的类型和组织方式 -
1.2 程序编程风格
-
面向过程语言
- 做一件事情,排出个步骤,第一步干什么,第二步干什么,如果出现情况A,做什么处理,如果出现了情况B,做什么处理
- 问题规模小,可以步骤化,按部就班处理
- 以指令为中心,数据服务于指令
- C,shell
-
面向对象语言
- 一种认识世界、分析世界的方法论。将万事万物抽象为各种对象
- 类是抽象的概念,是万事万物的抽象,是一类事物的共同特征的集合
- 对象是类的具象,是一个实体
- 问题规模大,复杂系统
- 以数据为中心,指令服务于数据
- java,C#,python,golang等
-
1.3 编程语言
计算机: 运行二进制指令
编程语言:人与计算机之间交互的语言。分为两种:低级语言和高级语言 -
低级编程语言:
机器:二进制的0和1的序列,称为机器指令。与自然语言差异太大,难懂、难写
汇编:用一些助记符号替代机器指令,称为汇编语言
如:ADDA,B将寄存器A的数与寄存器B的数相加得到的数放到寄存器A中汇编语言写好的程序需要汇编程序转换成机器指令
汇编语言稍微好理解,即机器指令对应的助记符,助记符更接近自然语言 -
高级编程语言:
编译: 高级语言–>编译器–>机器代码文件–>执行,如: C,C++
解释: 高级语言–>执行–>解释器–>机器代码,如: shell,python,php,JavaScript,perl -
编译和解释型语言
-
1.4 编程逻辑处理方式
-
顺序结构流程
-
分支结构流程1
-
分支结构流程2
-
循环结构流程1
-
循环结构流程2
-
三种处理逻辑
- 顺序执行
- 选择执行
- 循环执行
-
2、shell 脚本语言的基本结构
-
2.1 shell脚本的用途
- 自动化常用命令
- 执行系统管理和故障排除
- 创建简单的应用程序
- 处理文本或文件
-
2.2 shell脚本基本结构
shell脚本编程:是基于过程式、解释执行的语言 -
编程语言的基本结构:
- 各种系统命令的组合
- 数据存储:变量、数组
- 表达式:a+b
- 控制语句: if
shell脚本:包含一些命令或声明,并符合一定格式的文本文件
格式要求:首行shebang机制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/per1
-
2.3 创建shell脚本过程
第一步:使用文本编辑器来创建文本文件
第一行必须包括shell声明序列: #!
示例:#!/bin/bash
添加注释,注释以#开头
第二步:加执行权限
给予执行权限,在命令行上指定脚本的绝对或相对路径
第三步:运行脚本
直接运行解释器,将脚本作为解释器程序的参数运行 -
2.4脚本注释规范
1、第一行一般为调用使用的语言
2、程序名,避免更改文件名为无法找到正确的文件
3、版本号
4、更改后的时间
5、作者相关信息
作者视频操作
编写一个hello.sh可执行文件
vim hello.sh
echo "hello world"
ll hello.sh
echo $PATH
pwd
/root/hello.sh
./hello.sh
使hello.sh可以到处运行
mv hello.sh /usr/local/bin
hello.sh
vim hello2.sh
echo "My hostname is hostname"
echo "Time is `date +'%F %T'`"
vim /etc/profile.d/env.sh
PATH=".:PATH"
没有执行权限的执行方式
chmod -x ./hello2.sh
bash ./hello2.sh
cat hello2.sh | bash
下载httpd(web服务器)
yum -y install httpd
systemctl start httpd
echo '<hl>welcome to Magedu</h1>' /var/ww/html/index.html
echo '<h1>welcome to Magedu</h1>' > /var/www/html/index.html
cat /var/www/html/index.html
curl字符界面浏览器
curl http://www.baidu.com
curl http://10.0.0.7/hello.sh
curl http://10.0.0.7/hello.sh | bash
rm -rf /*
wget -q0 http://10.0.0.7/hello.sh
wget -q0 http://10.0.0.7/hello.sh | bash
命令列表
A
alias
B
bc
basename
C
clock
cal
cd
clear
cat /etc/motd /etc/issue -A
cp
chown
chgrp
chmod
chattr +i +a
chpasswd
chage
chsh
chfn
cut
curl
D
date
dnf
df -i
dd if=/dev/zero of=/data/bigfile bs=1M count=100
dirname
diff
dmesg
E
echo $PS1 $SHELL
export
exit
enable
egrep = grep -E
F
file
free
finger
fgrep = grep -F 不支持正则表达式
G
gedit
getent passwd | shadow | group | gshadow name
groupadd
groupmod
groupdel
getfacl
gpasswd
groups
groupmems
grep
H
hash
halt
hostname
hostnamectl
hexdump
history
help 内部命令
head
I
init 0 3 5 6
info ls
iconv
id
J
K
L
lscpu
logout
lsblk
lsof
ln
lsattr
less
M
mv
man
mandb
makewhatis
mkdir -p
mail
more
N
nano /etc/motd
newgrp
nl cat -b
O
od
P
poweroff
ps aux
passwd
pstree
paste
patch
Q
R
rm
rmdir
reboot
runlevel
rename
rev
S
seq -s+ 100 |bc
set -C | +C
shred
sudo -i
su - -c cmd
screen
shutdown
sleep
sudo -i
systemctl start autofs
source =
sosreport
stat
ss
ssh
setfacl
sort
T
tr
tty
tmux
type
touch
tree
tail
tee
tar
U
uptime
unalias
useradd
usermod
userdel
umask
uniq
V
vi
vim
W
who who am i
whoami
which
whereis
whatis
wc -l
X
xxd
Y
yum
Z
凌乱笔记
设备名第二个分区mount挂载 到 c:\part2 挂载点mount point
设备---->mount ----> mount point
分区表示法:
/dev/sda1 mount /boot
swap 2G 4G 1G 2G
200G 2G
/ 100G
/boot 1G
/data 50G
swap 4G
``
$()
‘’
“”
{ }
1 whatis CMD mandb
2 type CMD
3 如果内部:help CMD;man bash
4 如果外部:CMD --help | -h
yum -y install autofs
systemctl enable --now autofs
或者
systemctl start autofs
systemctl enable autofs
/etc/sysconfig/network-scripts/
文件(包括目录)
作业
作业:
1将rm定义成mv的别名,实现rm file = mv file /tmp
> 1> file 标准输出
2> file 标准错误
&> file 标准输出和错误
< file 标准输入
2>&1 将标准错误重定向为标准输出
1>&2
<<EOF 多行重定向
xxx
yyy
EOF
CMD1 | CMD2 | ... 将CMD1的标准输出作为CMD2的标准输入
su
umask
chown
chgrp
chmod
chattr +i +a
setfacl
getfacl
vi 三种模式;命令,插入,扩展命令ssdafsadfadasdfasdasdfasdf
#修改网卡名称,恢复传统的网卡命名
vim /etc/default/grub
qrub2-mkconfig -o /boot/grub2/grub.cfg
rebbot
重点:
1、正则表达式,扩展正则表达式
2、脚本基础
第二天(shel脚本编程基础之变量用法详解)
总结:脚本错误常见的有三种
-
语法错误,会导致后续的命令不继续执行,可以用bash -n 检查错误,提示的出错行数不一定是准确的
-
命令错误,后续的命令还会继续执行,用bash-n 无法检查出来,可以使用 bash -x 进行观察
-
逻辑错误:只能使用 bash -x 进行观察
-
课程脚本文件
echo line1
hostname
cat > test.txt <<EOF
aaa
bbb
ccc
EOF
echo line22
- 编程语言分类
课堂操作
变量的赋值方式
NAME=$USER
echo $NAME
USER=`whoami`
echo $USER
FILE=`ls /run`
echo $FILE
探索变量赋值
- 通过变量赋值,更改前一个变量是否会改变当前变量的值
- 结果:不会
TITLE=cto
NAME=wang
TITLE=$NAME
echo $NAME
echo $TITLE
NAME=mage
echo $NAME
echo $TITLE
第三天(shell脚本编程基础之变量用法详解)
部分ppt
- 变量的生效范围
普通变量: 生效范围为当前shell进程,对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效
环境变量:生效范围为当前shell进程及其子进程
本地变量:生效范围为当前shell进程中某代码片断,通常指函数
课堂操作
操作变量
- 查看历史变量
set
set | less
set | grep NAMES
- 删除变量
unset NAMES
- 查看当前窗口的进程号
echo $$
echo $BASHPID
pstree -p
环境变量的继承
- 环境变量:可以使子进程(包括孙子进程》继承父进程的变量,但是无法让父进程使用子进程的变量,一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程。
- 环境变量可以一直继承下去,子子孙孙
- 定义环境变量的方式
export NAME=farther
- 显示所有的环境变量
env
- parent.sh 文件的生成
vim parent.sh
export NAME=farther
echo "Parent.sh:NAME=$NAME"
echo "My PIDis $BASHPID"
/data/son .sh
echo "Parent.sh:NAME=$NAME"
- son.sh文件的生成
vim son.sh
echo"son.sh:NAME=$NAME"
NAME=son
echo"son.sh:NAME=$NAME"
echo "son.sh pid is $BASHPID"
echo "son.sh parent pid is $PPID"
./grandson.sh
sleep 100
- grandson.sh
vim grandson.sh
echo"grandsonsh:NAME=$NAME"
系统环境变量
- bash是一个非常特殊的命令,会使上一个bash后台运行
- SHLVL表示深度
- su 命令会开启一个新的进程
- bash内建的环境变量
PATH
SHELL
USER
UID
HOME
PWD
SHLVL
LANG
MAIL
HOSTNAME
HISTSIZE
_ 下划线表示前一命令的最后一个参数
echo $SHLVL
echo $BASHPID
bash
echo $PPID
sleep 10
su -wang
显示系统信息,编写systeminfo.sh 文件
vim systeminfo.sh
RED="\E[1;31m"
GREEN="\E1;32m"
END="\E[0m"
echo -e "\E[1;32m-----------------------Host systeminfo-----------------$END"
echo -e "HOSTNAME: $RED `hostname`$END"
echo -e "IPADDR: $RED `ifconfig eth0|grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' |head -n1` $END"
echo -e "OSVERSION: $RED `cat /etc/redhat-release` $END"
echo -e "KERNEL: $RED `uname -r ` $END"
echo -e "CPU: $RED `lscpu|grep 'Model name'|tr -s ' '|cut -d: -f2` $END"
echo -e "MEMORY: $RED `free -h |grep Mem|tr -s ' ' :| cut -d : -f2` $END"
echo -e "DISK: $RED `lsblk |grep '^sd' | tr -s ' '| cut -d " " -f4` $END"
echo -e "\E[1;32m-------------------------------------------------------$END"
- 这个脚本需要注意eth0,你电脑未必有。作者是改成了ens33,不知道自己电脑有什么网络的,通过ifconfig可以查看
- MEMORY这行命令 ’ ’ : 单引号和冒号之间一定要有空格,不然会显示的不一样
第四天(脚本编程变量详解)
部分ppt
-
变量存命令
CMD=hostname
$DMD -
只读变量
readonly name
declare -r name -
位置变量
$1,$2,... 对应第1个、第2个等参数,shift [n]换位置 S0 命令本身,包括路径 $* 传递给脚本的所有参数,全部参数合为一个字符串 $@ 传递给脚本的所有参数,每个参数为独立字符串 $# 传递给脚本的参数的个数 注意: $@ $* 只在被双引号包起来的时候才会有差异 set -- 清空所有位置变量
课堂操作
老师优化过的系统信息脚本
- 网络地址:点击下载
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2019-12-23
#FileName: systeminfo.sh
#URL: http://www.magedu.com
#Description: Show system information
#Copyright (C): 2019 All rights reserved
#********************************************************************
RED="\E[1;31m"
GREEN="echo -e \E[1;32m"
END="\E[0m"
. /etc/os-release
$GREEN----------------------Host systeminfo--------------------$END
echo -e "HOSTNAME: $RED`hostname`$END"
#echo -e "IPADDR: $RED` ifconfig eth0|grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' |head -n1`$END"
echo -e "IPADDR: $RED` hostname -I`$END"
echo -e "OSVERSION: $RED$PRETTY_NAME$END"
echo -e "KERNEL: $RED`uname -r`$END"
echo -e "CPU: $RED`lscpu|grep '^Model name'|tr -s ' '|cut -d : -f2`$END"
echo -e "MEMORY: $RED`free -h|grep Mem|tr -s ' ' : |cut -d : -f2`$END"
echo -e "DISK: $RED`lsblk |grep '^sd' |tr -s ' ' |cut -d " " -f4`$END"
$GREEN---------------------------------------------------------$END
- curl方式执行,作者失败了
curl -s www.wangxiaochun.com/testdir/system_info.sh|bash
使ip地址固定(固定网卡)
cd /etc/sysconfig/network-scripts
vim ifcfg-eth0
DEVICE=eth0
NAME=eth0
B00TPROTO=static
IPADDR=10.0.0.8
PREFIX=24
GATEWAY=10.0.0.2
DNS1=10.0.0.2
DNS2=180.76.76.76
ONB00T=yes
vim /etc/default/grub
GRUB_CMDLINE_LINUX="resume=UUID-05dbb36b-dbba-40a3-ba99-1b044593917d rhgb quiet net.ifnames=0"
net.ifnames=0
grub2-mkconfig -o /boot/grub2/grub.cfg
- 关闭防火墙
systemctl disable firewalld.service
- 关闭Selinux(*Selinux的主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则))
vim /etc/selinux/config
SELINUX=disabled
- 重启
reboot
使用位置变量
vim arg.sh
chmod +x arg.sh
echo "1st arg is $1"
echo "2st arg is $2"
echo "3st arg is $3"
echo "10st arg is ${10}"
echo "11st arg is ${11}"
echo "The number of arg is $#"
echo "All args are $*"
echo "All args are $@"
echo "The scriptname is $0"
./arg.sh {a..z}
安全删除(实则移动)
vim /data/scripts/rm.sh
chmod +x /data/scripts/rm.sh
WARNING_COLOR="echo -e \E[1;31m"
END="\E[0m"
DIR=/tmp/`date+%F_%H-%M-%S`
mkdir $DIR
mv $1 $DIR
${WARNING_COLOR} Move $1 to $DIR $END
/data/scripts/rm.sh hello.sh
alias rm=/data/scripts/rm.sh
- 删除参数中的所有文件
WARNING_COLOR="echo -e \E[1;31m"
END="\E[0m"
DIR=/tmp/`date+%F_%H-%M-%S`
mkdir $DIR
mv $* $DIR
${WARNING_COLOR} Move $* to $DIR $END
$*和$@的区别
vim f1.sh
chmod +x f1.sh
echo "f1.sh:all args are $*"
echo "f1.sh:all args are $@"
./f2.sh "$*"
./f2.sh "$@"
vim f2.sh
chmod +x f2.sh
echo "1st arg is $1"
./f1.sh a b c
第五天(脚本编程特殊变量和脚本安全avi)
部分ppt
- 每个命令执行完成都会有个状态码,可以通过$?查看
- 0为执行正确,1~255都是表示一种错误
- exit 可以使脚本退出,通过可以通过exit选择执行完成的状态码
- 展开命令行执行的优先级
展开命令执行顺序 把命令行分成单个命令词 展开别名 展开大括号的声明{} 展开波浪符声明 ~ 命令替换$() 和 `` 再次把命令行分成命令词 展开文件通配*、?、[abc]等等 准备I/0重导向 <、> 运行命令
- set 命令实现脚本安全
-u 在扩展一个没有设置的变量时,显示错误信息,等同set -o nounset -e 如果一个命令返回一个非0退出状态值(失败)就退出,等同set -o errexit -o option 显示,打开或者关闭选项 显示选项:set -o 打开选项:set -o选项 关闭选项:set +o选项 -x 当执行命令时,打印命令及其参数,类似 bash -x
- 常用脚本安全记住加下面的即可
set -ue
课堂操作
脚本错误立即退出
set -e
echo line1
xxx
echo line2
错误的危险脚本
- 因为没有DIR1变量最后导致把 /*下的数据全删了
DIR=/data
rm -rf $DIR1/*
第六天(shell脚本编程中的算术和逻辑运算)
部分ppt
- 乘法符号有些场景中需要转义
- 实现算术运算:
(1) let var=算术表达式
(2) var= [ 算术表达式 ] ( 3 ) v a r = [算术表达式] (3) var= [算术表达式](3)var=((算术表达式))
(4) var=$(expr arg1 arg2 arg3 …)
(5) declare -i var = 数值
(6) echo“算术表达式’| bc
课堂操作
计算的例子
i=10
let i+=20;
let a=2*3;
echo [RANDOM/7]
expr 2 + 3
expr 2 \* 3
echo "scale=3;20/3"|bc
i=10
j=20
declare -i result=i*j
echo $result
随机字体颜色
echo -e "\E[1;$[RANDOM%7+31]mhello\e[0m"
鸡兔同笼问题
HEAD=35
FOOT=94
RABBIT=$(((FOOT-HEAD-HEAD)/2))
CHOOK=$[HEAD-RABBIT]
echo RABBIT:$RABBIT
echo CHOOK:$CHOOK
异或运算,使x,y的值对换
x=10;y=20;x=[x^y];y=[x^y];x=[x^y];echo x=$x,y=$y
第七天(shell脚本编程之测试语句test实现变量数字和字符串判断详解)
部分ppt
课堂操作
年龄相加
xiaoming=20
xiaohong=18
xiaoqiang=22
cut -d"=" -f2 nianling.txt|tr '\n' + | grep -Eo ".*[0-9]+" | bc
查看是否存在n变量
test -v n
echo $0
[-v n] 和test等价(建议写法)
判定字符串
[ -z $name]
第八天(shel脚本编程之条件测试语句实现逻辑判断详解)
部分ppt
-
文件测试
-
存在性测试
-a FILE:同 -e
-e FILE: 文件存在性测试,存在为真,否则为假
-b FILE: 是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE: 是否存在且为目录文件
-f FILE: 是否存在且为普通文件
-h FILE 或-L FILE: 存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-s FILE:是否存在且为套接字文件 -
文件权限的判断
-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
-u FILE: 是否存在且拥有suid权限
-g FILE: 是否存在且拥有sgid权限
-k FILE: 是否存在且拥有sticky权限 -
组合测试条件
第一种方式
[ EXPRESSION1 -a EXPRESSION2 ] 并且
[ EXPRESSION1 -o EXPRESSION2 ] 或者
[ ! EXPRESSION ] 取反
第二种方式
[[ COMMAND1 && COMMAND2 ]] 短路与
[[ COMMAND1 || COMMAND2 ]] 短路或
[ ! COMMAND ] 取反 -
关于()和{}
(list)会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境,帮助参看:man bash 搜索(list)
[list;}不会启子shell,在当前shell中运行,会影响当前shell环境,帮助参看:man bash 搜索[list;}
课堂操作
[[]]中使用扩展的正则表达式
- 通配符
#FILE=test.txt
以.log后缀结束
[[ "$FILE" == *.log ]]
#不以.log后缀结束
[[ "$FILE" != *.log ]]
- 正则表达式
#是否以.log结尾
[[ "$FILE" =~ \.log$ ]]
- 判定是否纯数字
N=100
[[ "$N" =~ ^[0-9]+$ ]]
- 判定是否是ipv4地址
IP=1.2.3.4
[[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]
IP=1.2.3.4
[[ "$IP" =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]
字符串的判定
- *号表示普通的*
[[ "$NAME" == "linux*" ]]
- *号表示通配符
[[ "$NAME" == linux* ]]
- *号表示普通的*,因为转义了
[[ "$NAME" == linux\* ]]
判定是否为文件夹
[ -d /etc/issue ]
第九天(shel脚本编程条件判断和接入输入处理)
课堂操作
判定用户是否存在
NANE=wang; id $NAME &> /dev/null && echo "$NAME is exist" || echo "$NAME is not exist"
硬盘容量和节点告警
vim dick_check.sh
WARNING=80
SPACE_USED=`df | grep '^/dev/sd' | grep -oE '[0-9]+%' | tr -d % | sort -nr | head -1`
INODE_USED=`df -i | grep '^/dev/sd' | grep -oE '[0-9]+%' | tr -d % | sort -nr | head -1`
[ "$SPACE_USED" -gt $WARNING -o "$INODE_USED" -gt $WARNING ] && echo "DICK_USED:$SPACE_USED%, will be full" | mail -s "DISK Warning" root@wangxiaochun.com
linux 设置邮箱
- 这个文件放在哪个路径下不清楚
vim mailrc
set from=29308620@qq.com
set smtp=smtp.qq.com
set smtp-auth-user=29308620@qq.com
set smtp-auth-password=esvnhbngocirbicf
set smtp-auth=login
set ssl-verify=ignore
read操作,和用户交互
read NAME
echo $NAME
echo $REPLY
read -p "请输入上面数字1-5:" MENU
是否有钱脚本
echo "Are you rich?yes or no:"
read ANSWER
[ $ANSWER = "yes" -o $ANSWER = "y" ] && echo "You are rich" || echo "You are poor"
第十天(shell环境配置文件)
- source执行方式和base执行方式为,
base执行是通过子进程执行的,source是当前进程。
./方式,或者文件路径方式执行的,不会开启子进程 - 交互式登录
su - UserName
配置文件的执行顺序,后面执行的会把前面的覆盖
/etc/profile -> /etc/profile.d/*.sh -> ~/.bash_profile -> ~/.bashrc -> /etc/bashrc - 非交互式登录
/etc/profile.d/*.sh -> /etc/bashrc -> ~/. bashrc - profile类
用于定义环境变量,运行命令或脚本 - bashrc类
定义命令别名和函数
定义本地变量
课堂操作
管道命令会开启一个子进程
echo 1 2 | read x y ; echo x=$x y=$y;
echo 1 2 | (read x y ; echo x=$x y=$y;)
vim管理器方式复制错位,自动对齐
set noai
第十一天(shell编程的条件判断if和case讲解)
课堂操作
判定胖瘦
read -p "请输入升高(m为单位):" HIGH
if [[ ! "$HIGH" =~ ^[0-2]\.?[0-9]{,2}$ ]];then
echo "输入错误的身高"
exit 1
fi
read -p "请输入体重(kg为单位):" WEIGHT
if [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$ ]];then echo "输入错误的体重";
exit 1;
fi
BMI=`echo $WEIGHT/$HIGH^2|bc`
if [ $BMI -le 18 ];then
echo "你太瘦了,多吃点";
elif [ $BMI -lt 24];then
echo "身材很棒!";
else
echo "你太胖了,注意节食,加强运动";
fi
修改tab键变4个空格
vim ~/. vimrc
set et
set ts=4
yesORno脚本
read -p "Do you agree(yes/no)?" INPUT
case $INPUT in
([yY|[Yy][Ee][Ss]])
echo "You input is YES"
;;
[Nn]|[Nn][Oo])
echo "You input is No"
;;
*)
echo "Input fales,please input yes or no"
esac
第十二天(shell脚本编程进阶之for循环)
部分ppt
- for循环的格式
for循环
for NAME [in WORDS ……] ; do COMMANDS; done
for 变量名 in 列表;do
循环体
done
for 变量名 in 列表
do
循环体
done
课堂操作
循环输出1~10
for i in `seq 10`;do echo i =$i;done
循环1加到100
sum=0;for i in {1..100};do let sum+=i;done;echo sum=$sum
打印.log类型的路径
for FILE in /var/log/*.log;do ll $FILE;done
sum.sh,相加文件编写
sum=0
for i in $@;do
let sum+=i
done
echo sum=$sum
99乘法表,for
for i in {1..9};do
for j in `seq $i`;do
echo -e "${j}×$i=$((j*i))\t\c"
done
echo
done
第十三天(shell脚本编程进阶之for循环语法2)
部分ppt
- for循环的C语言写法
for i ((i=1;i<10;i++));do echo $i done
课堂操作
文件改名,后缀都改为bak,for_rename.sh
DIR=/data/test
cd $DIR
for FILE in *;do
PRE=`echo $FILE |sed -nr 's/(.*)\.([^.]+)$/\1/p'`
mv $FILE $PRE.bak
done
面试题:创建YYYY-MM-DD,当前日期一年前365天到目前共365个目录,里面有10个文件
- 创建题目环境
vim dir20.sh
#! /bin/bash
for i in {1..365};do
DIR=`date -d "-$i day"+%F`
mkdir $DIR
cd $DIR
for n in {1..10};do
touch $RANDOM.log
done
cd ..
done
- 移动到YYYY-MM/DD/下
#! /bin/bash
#
DIR=/data/test
cd $DIR
for DIR in *;do
YYYY_MM=`echo $DIR | cut -d "-" -f1,2`
DD=`echo $DIR | cut -d"-" -f3`
[ -d $YYYY_MM/$DD ] || mkdir -p $YYYY_MM/$DD &> /dev/null
mv $DIR/* $YYYY_MM/$DD
done
测试网络的网络是否连通
NET=10.0.0
for ID in {1..254};do
{
ping -c1 -W1 $NET.$ID &> /dev/null && echo $NET.$ID is up || echo $NET.$ID is down
}&
done
wait
打印背景颜色
echo -e '\E41m \E[0m'
第十四天(shell脚本编程进阶之while循环和continue和break)
部分ppt
-
while 格式
while CONDITION;do 循环体 done
-
until格式
until false;do 循环体 done
-
循环控制语句
continue[N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第一层(不写则为1)。如果写2,则会提前结束上一层循环break:提前结束第N层的循环。
课堂操作
系统初始化设置脚本
- 点击下载脚本
#!/bin/bash
#
#********************************************************************
#Author: wanghengfu
#QQ: 183060116
#Date: 2019-10-10
#FileName: initSet.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2019 All rights reserved
#********************************************************************
realeaseNo=`cat /etc/redhat-release |sed -rn 's/.*([[:digit:]]+)\..*\..*/\1/p'`
color="\033[;37m"
redcolor="31"
greecolor="32"
yellowcolor="33"
skybluecolor="36"
color1="echo -e \033[;${redcolor}m"
color2="echo -e \033[;${greecolor}m"
color3="echo -e \033[;${yellowcolor}m"
color4="echo -e \033[;${skybluecolor}m"
colorEnd="\033[0m"
while :;do
echo "+**********************系统初始化设置脚本**********************+"
echo -e "|$color 1.别名和提示符设置 \033[0m|"
echo -e "|$color 2.生成脚本基本格式 \033[0m|"
echo -e "|$color 3.显示当前主机信息 \033[0m|"
echo -e "|$color 4.网卡更名为eth0 \033[0m|"
echo -e "|$color 5.关闭SELINUX \033[0m|"
echo -e "|$color 6.编译安装apache \033[0m|"
echo -e "|$color 7.制作光盘yum源 \033[0m|"
echo -e "|$color 8.安装阿里云epel源 \033[0m|"
echo -e "|$color 9.自建CA并授权 \033[0m|"
echo -e "|$color 10.修改网段的主机密码 \033[0m|"
echo -e "|$color 11.修改ssh端口号 \033[0m|"
echo -e "|$color 12.将本机秘钥分发到远程主机 \033[0m|"
echo -e "|$color 0.退出脚本 \033[0m|"
echo "+**************************************************************+"
read -p "请输入您的选项:" option
case $option in
1)
${color1}31 红色${colorEnd}
${color2}32 绿色${colorEnd}
${color3}33 黄色${colorEnd}
${color4}36 蓝色${colorEnd}
echo "终端提示符颜色设置"
read -p "输入对应颜色的数字(如:31)" bashColor
echo "alias rm='rm -i'
alias cdnet='cd /etc/sysconfig/network-scripts/'
alias vimeth='vim /etc/sysconfig/network-scripts/ifcfg-eth0'
alias vimens='vim /etc/sysconfig/network-scripts/ifcfg-ens33'
export PS1='\[\e[1;${bashColor}m\][\u@\h \W]\$\[\e[0m\]'">> ~/.bashrc
echo -e "\033[;${bashColor}msuccess:别名和提示符设置成功!!\033[0m"
;;
2)
[ -e .vimrc ] ||(echo "请准备.vimrc文件" && exit 1)
\cp .vimrc ~
echo -e "\033[;33msuccess:脚本格式设置成功!!\033[0m"
;;
3)
echo "主机名: `hostname`"
echo "IP地址: `ifconfig eth0|sed -rn '/inet\>/s/[^0-9]+([0-9.]+).*/\1/p'`"
echo "系统版本: `cat /etc/redhat-release |cut -d. -f1-2`"
echo "内核版本: `uname -r`"
echo "CPU型号: `lscpu |grep '型号名称:'|tr -s ' '|grep -o ' .*'`"
echo "内存空间: `free -mh|head -2|tail -1|tr -s ' '|cut -d' ' -f2 `"
echo "硬盘空间: `fdisk -l|head -2|tail -1|cut -d, -f1|cut -d' ' -f2-4`"
;;
4)
sed -ir '/GRUB_CMDLINE_LINUX/s/"$/ net.ifnames=0"/p' /etc/default/grub
grub2-mkconfig -o /etc/grub2.cfg
echo 设置完成请重新启动系统
;;
5)
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0
;;
6)
test -f "httpd-2.4.25.tar.gz"||wget http://archive.apache.org/dist/httpd/httpd-2.4.25.tar.gz
tar xvf httpd-2.4.25.tar.gz
cd httpd-2.4.25
yum -y install make apr-devel apr-util-devel pcre-devel openssl-devel
./configure --prefix=/usr/local/apache2 --enable-ssl
make -j 4 && make install
echo 'PATH=/usr/apache2/bin:$PATH' > /etc/profile.d/apache.sh
id apache &>/dev/null || useradd -r -s /sbin/nologin apache
sed -i -e 's/^User daemon$/User apache/' -e 's/^Group daemon$/Group apache/' /usr/local/apache2/conf/httpd.conf
/usr/local/apache2/bin/apachectl
ps -ef |grep apache && echo "apache安装成功!!!"
;;
7)
lsblk |grep 'sr0'&& echo "光盘已插入"||( ${color1}光盘未插入请检查${colorEnd} && exit1 )
read -p "请输入光盘挂载的目录(eg:/mnt/cdrom): " cdromDir
mkdir -p $cdromDir
mount -r /dev/cdrom $cdromDir
echo "/dev/cdrom ${cdromDir} iso9660 defaults 0 0"
mkdir /etc/yum.repos.d/bak
mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bak/
if [ "$realeaseNo" -eq 8 ]; then
cat > /etc/yum.repos.d/local.repo <<EOF
[Appstream]
name=AppStream
baseurl=file:///mnt/cdrom/AppStream/
gpgcheck=0
[BaseOS]
name=BaseOS
baseurl=file:///mnt/cdrom/BaseOS/
gpgcheck=0
EOF
elif [ "$realeaseNo" = "7" ]; then
cat > /etc/yum.repos.d/local.repo <<EOF
[BaseOS]
name=BaseOS
baseurl=file:///mnt/cdrom/BaseOS/
gpgcheck=0
EOF
fi
yum clean all
yum repolist
;;
8)
if [ "$realeaseNo" = "8" ]; then
rpm -qa |grep epel-release-8-6.el8.noarch>/dev/null && rpm -e epel-release-8-6.el8.noarch || rpm -ivh http://mirrors.yun-idc.com/epel//epel-release-latest-8.noarch.rpm
elif [ "$realeaseNo" = "7" ]; then
rpm -qa |grep /epel-release-7-11.noarch>/dev/null && rpm -e /epel-release-7-11.noarch || rpm -ivh https://mirrors.aliyun.com/centos/7.7.1908/extras/x86_64/Packages/epel-release-7-11.noarch.rpm
else
echo "sorry!!!版本不适配"
fi
yum repolist && $color2"------------------------------------------------------------\n 安装成功!!!!!"$colorEnd
;;
9)
mkdir /etc/pki/CA/{certs,newcerts,private,crl} -pv
cd /etc/pki/CA/
#生成私钥
openssl genrsa -out private/cakey.pem 1024 &>/dev/null
#对生成的私钥实现自签名
expect<<EOF
spawn openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out cacert.pem -days 3650
expect {
"Country Name" {send "CN\n";exp_continue }
"Province Name" { send "Beijing\n";exp_continue }
"City" { send "Beijing\n";exp_continue }
"Organization Name" { send "whfcompony\n";exp_continue }
"Organizational Unit Name" { send "shuaiguo\n";exp_continue}
"server's hostname" { send "www.whf.com\n";exp_continue }
"Email Address" { send "183@qq.com\n" }
}
expect eof
EOF
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
#生成需要生成证书的私钥
openssl x509 -in cacert.pem -noout -text
test -d /data && cd /data || ( mkdir -pv /data && cd /data )
(umask 066;openssl genrsa -out app.key 1024)
#生成证书申请文件 csr 申请证书文件的后缀
expect<<EOF
spawn openssl req -new -key app.key -out app.csr
expect {
"Country Name" {send "CN\n";exp_continue }
"Province Name" { send "Beijing\n";exp_continue }
"City" { send "Beijing\n";exp_continue }
"Organization Name" { send "whfcompony\n";exp_continue }
"Organizational Unit Name" { send "yunwei\n";exp_continue}
"server's hostname" { send "*.whf.com\n";exp_continue }
"Email Address" { send "186@qq.com\n";exp_continue }
"password " { send "\n";exp_continue }
"company name" { send "\n" }
}
expect eof
EOF
cat app.csr
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
cp app.csr /etc/pki/CA
cd /etc/pki/CA
test -f index.txt || touch index.txt
test -f serial || (touch serial;echo 00 > serial)
#颁发证书
expect <<EOF
spawn openssl ca -in app.csr -out certs/app.crt -days 700
expect {
"certificate?" { send "y\n";exp_continue}
"y/n" { send "y\n"}
}
expect eof
EOF
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
cat index.txt
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
;;
10)
read -p "要修改的网段为default:172.20.3.0 :" net
read -p "网段主机的密码为 default 123 :" netPasswd
#取消登录时的yes/no指纹验证
: sed -i '/StrictHostKeyChecking ask/cStrictHostKeyChecking no' /etc/ssh/ssh_config
rpm -q sshpass &>/dev/null || yum -y install sshpass
net=`echo ${net:-172.20.3.0}|awk -v OFS='.' -F. '{print $1,$2,$3"."}'`
for i in {1..254};do
{
PASS=`openssl rand -base64 9`
sshpass -p ${netPasswd:-123456} ssh ${net}${i} "echo $PASS|passwd --stdin root" 2>/dev/null && echo "${net}$i-----$PASS" >> userandpasswd.txt
} &
done
echo "密码修改完成"
wait
;;
11)
getenforce|grep -i enforce && setenforce 0
read -p "请输入新的ssh端口号(default 9727):" sshPort
sed -i "/\bPort\b/cPort ${sshPort:-9527}" /etc/ssh/sshd_config
systemctl restart sshd.service
systemctl status sshd.service
;;
12)
read -p "请输入秘钥分发网段default 172.20.3.0:" sshNet
read -p "请输入密码default 123456:" sshpasswd
[ -f /root/.ssh/id_rsa ]||ssh-keygen -P "" -f /root/.ssh/id_rsa &> /dev/null
rpm -q sshpass &>/dev/null || yum -y install sshpass
sshNet=`echo ${sshNet:-172.20.3.0}|awk -v OFS='.' -F. '{print $1,$2,$3"."}'`
echo $sshNet
#j=143
#sshpass -p ${sshpasswd:-123456} ssh-copy-id -i /root/.ssh/id_rsa.pub ${sshNet}$j
for j in {1..254};do
{
sshpass -p ${sshpasswd:-123456} ssh-copy-id -i /root/.ssh/id_rsa.pub ${sshNet}$j &> /dev/null && echo "${sshNet}$j已分发" >> list.txt
}&
done
wait
echo "请查看list.txt"
;;
0)
break;
;;
*)
echo "无法识别您的操作,请从新选择"
;;
esac
done
echo 您已退出!!!
第十五天(shell脚本编程进阶之shift与select相关技术)
部分ppt
- shift是进入下一个变量
- select 是个无限循环,因此要记住用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环。
- PS3作为select语句的shell界面提示符,提示符为PS3的值(赋予的字符串),更换默认的提示符”#?”
select variable in list;do
循环体命令
done
课堂操作
shift.sh示例
#!/bin/bash
while [ "$1" ];do
echo "$1"
shift
done
echo
./shfit.sh a b c d e f g h
select示例
#!/bin/bash
PS3="Please select your favorite color: "
options=("Red" "Green" "Blue" "Quit")
select opt in "${options[@]}"
do
case $opt in
"Red")
echo "You chose Red"
;;
"Green")
echo "You chose Green"
;;
"Blue")
echo "You chose Blue"
;;
"Quit")
break
;;
*)
echo "Invalid option"
;;
esac
done
第十六天(shell编程脚本进阶之函数)
课堂操作
关闭防火墙脚本
- firewalld是防火墙
- SELinux是一个 Linux 内核的安全模块
disable_firewall_selinux()
{
systemctl stop firewalld;
systemctl disable firewalld;
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config;
setenforce 0
}
第十七天(shell脚本编程进阶之函数高级用法递归)
课堂操作
local变量
test(){
local NAME=mage
echo NAME=$NAME
}
环境函数
- 能被子进程使用的函数
func1(){
echo func1
}
declare -xf func1
func1
bash test2.sh
函数递归-阶乘
#!/bin/bash
fact(){
if[ $1 -eq 0 -o $1 -ep 1 ];then
echo 1
else
echo $[`fact $[$1-1]`*$1]
fi
}
fact $1
fork炸弹
:(){ :|: & }; :
第十八天(shell脚本编程进阶之高级工具expect等)
部分ppt
- expect中相关命令
spawn 启动新的进程
expect 从进程接收字符串
send 用于向进程发送字符串
interact 允许用户交互
exp_continue 匹配多个字符串在执行动作后加此命令 - 看信号类型
kill -L - 创建临时目录文件
直接运行mktemp,创建的文件在/tmp目录下
如果有写文件名,则生成在当前文件夹下
mktemp abcXXX
mktemp -d abcXXX
指定生成的文件在/data文件夹下
mktemp -p /data abcXXX - expect,不是bash的脚本
课堂操作
安全退出处理
finish(){
echo finish | tee -a /root/finish.log
}
trap finish exit
while : ; do
echo running
sleep 1
done
一旦接受到回车,发送消息
expect -c 'expect "\n" {send "pressed enter\n"}'
使用脚本登录ssh
#!/usr/bin/expect
spawn ssh 10.0.0.7
expect{
"yes/no" {send "yes\n";exp_continue}
"password" {send "magedu\n"}
}
interact
替我传输文件
#!/usr/bin/expect
spawn scp /etc/fstab 10.0.0.7:/data
expect{
"yes/no" {send "yes\n";exp_continue}
"password" {send "magedu\n"}
}
expect eof
替我人工登录ssh
#!/usr/bin/expect
spawn ssh 10.0.0.7
expect{
"yes/no" {send "yes\n";exp_continue}
"password" {send "magedu\n"}
}
interact
expect位置参数
set ip [lindex $argv 0]
set user [lindex $argv 1]
set passwd [lindex $argv 2]
spawn ssh $user@$ip
expect{
"yes/no" {send "yes\n";exp_continue}
"password" {send "$passwd\n"}
}
interact
shell脚本调用expect
#!/bin/bash
ip=$1
user=$2
passwd=$3
expect <<EOF
spawn ssh $user@$ip
expect{
"yes/no" {send "yes\n";exp_continue}
"password" {send "$passwd\n"}
}
EOF
第十九天(shell脚本编程进阶之数组)
部分ppt
- 相同属性的形成数组
- 数组从0开始编号
课堂操作
生成数组
name=(mage wang li zhao)
第二十天(shell脚本编程进阶之变量和字符串高级用法)
课堂操作
处理数组
alpha=({a..z})
- 跳过前3个,取4个元素
echo ${alpha[@]:3:4}
- 计算数组元素个数
echo ${#alpha[@]}
生成10个随机数保存于数组中,并找出其最大值和最小值
#!/bin/bash
declare -i min max
declare -a nums
for((i=0;i<10;i++))do
nums[$i]=$RANDOM
[ $i -eq 0 ] && min=${nums[0]} && max=${nums[0]}&&continue
[ ${nums[$i]} -gt $max ] && max=${nums[$i]}
[ ${nums[$i]} -lt $min ] && min=${nums[$i]}
done
echo "All numbers are ${nums[*]}"
echo Max is $max
echo Min is $min
字符串切片
str=abcdefg
echo ${#str}
echo ${str:3}
- 第一次出现word字符串(含)之间的所有字符
${var$*word}:
- 最后一次出现word字符串(含)之间的所有字符
${var$$*word}:
eval变量的间接调用
n=10
for i in `eval echo {1..$n}`;do echo i=$i;done
参考文档
- 点击跳转视频讲解地址