SHELL
2023-07-17 11:07:53 0 举报
AI智能生成
LINUX
作者其他创作
大纲/内容
DAY01
shell
Linux内核与用户之间的解释器程序
/bin/bash,负责向内核翻译及传达用户/程序指令
操作系统的‘外壳’
/bin/bash,负责向内核翻译及传达用户/程序指令
操作系统的‘外壳’
使用方式
交互式:人工干预,执行效率底---命令行
非交互式:安静地在后台执行,执行效率高---脚本
命令
cat /etc/shells #查看所有解释器
sh #切换成sh解释器
ksh #切换ksh,需安装
sh #切换成sh解释器
ksh #切换ksh,需安装
bash特性
Tab键、快捷键、历史命令、支持别名、管道、重定向、标准输入/输出
脚本
1.申明解释器:#!/bin/bash
2.注释: #
(作者信息、步骤、思路、用途、变量含义等)
3.可执行语句:
执行:
1.chmod +x test01.sh
./test01.sh
2.不加执行权限
bash test01.sh
source test01.sh
. test01.sh
区别:
1.bash: 父 子
账户登录(root)---bash---bash---xx.sh 子进程执行脚本,结束后退出
2.source:
账户登录(root)---bash---xx.sh 父进程执行脚本,结束后不退出
2.注释: #
(作者信息、步骤、思路、用途、变量含义等)
3.可执行语句:
执行:
1.chmod +x test01.sh
./test01.sh
2.不加执行权限
bash test01.sh
source test01.sh
. test01.sh
区别:
1.bash: 父 子
账户登录(root)---bash---bash---xx.sh 子进程执行脚本,结束后退出
2.source:
账户登录(root)---bash---xx.sh 父进程执行脚本,结束后不退出
EG
shell变量
以固定名称存放,可能会变化的值
调用变量:$
常量:固定不变的内容
[...]a=10 创建变量a/对变量a赋值
[...]2=20 对变量a重新赋值
[...]echo $a 调用变量
[...]2=20 对变量a重新赋值
[...]echo $a 调用变量
环境变量
$USER 当前用户名
$UID 当前用户id
$SHELL 当前解释器
$HOME 当前用户家目录
$PWD 当前路径
$HOSTNAME 当前主机名
$UID 当前用户id
$SHELL 当前解释器
$HOME 当前用户家目录
$PWD 当前路径
$HOSTNAME 当前主机名
$PS1 一级提示符
$PS2 二级提示符
$PS2 二级提示符
PATH:存储了命令的路径
位置变量与预定义变量
echo $0 #脚本的名称
echo $1 #第一个参数
echo $2 #第二个参数
echo $* #所有参数
echo $# #所有参数的个数
echo $$ #当前进程的进程号
echo $? #上一个程序的返回状态码
echo $1 #第一个参数
echo $2 #第二个参数
echo $* #所有参数
echo $# #所有参数的个数
echo $$ #当前进程的进程号
echo $? #上一个程序的返回状态码
引号:界定范围
""
'' 单引号会取消特殊符号功能
反撇号 `` ==== &()
read -p
#!/bin/bash
read -p "请输入用户名" u
useradd $u
stty -echo 屏蔽回显
read -p "请输入密码" n
stty echo 显示回显
echo "$n" | passwd --stdin $u
read -p "请输入用户名" u
useradd $u
stty -echo 屏蔽回显
read -p "请输入密码" n
stty echo 显示回显
echo "$n" | passwd --stdin $u
全局变量
export a=100 设置全局
pstree | grep bash 查看进程位置
pstree | grep bash 查看进程位置
数值运算
expr
X=1234 #定义变量X
expr $X + 78 #加法
1312
expr $X - 78 #减法
1156
expr $X \* 78 #乘法,操作符应添加\转义
96252
expr $X / 78 #除法,仅保留整除结果
15
expr $X % 78 #求模
64
expr $X + 78 #加法
1312
expr $X - 78 #减法
1156
expr $X \* 78 #乘法,操作符应添加\转义
96252
expr $X / 78 #除法,仅保留整除结果
15
expr $X % 78 #求模
64
$[]、$(())
[...]# X=1234
[...]# echo $[X+78]
1312
[...]# echo $[X-78]
1156
[...]# echo $[X*78]
96252
[...]# echo $[X/78]
15
[...]# echo $[X%78]
64
[...]# echo $[X+78]
1312
[...]# echo $[X-78]
1156
[...]# echo $[X*78]
96252
[...]# echo $[X/78]
15
[...]# echo $[X%78]
64
let
常规写法 主流写法
let a=a+1 let a++ #变量a加1
let a=a-1 let a-- #变量a减1
let a=a+10 let a+=10 #变量a加10
let a=a-10 let a-=10 #变量a减10
let a=a*2 let a*=2 #变量a乘以2
let a=a/2 let a/=2 #变量a除以2
let a=a%3 let a%=3 #变量a除以3取余数
let a=a+1 let a++ #变量a加1
let a=a-1 let a-- #变量a减1
let a=a+10 let a+=10 #变量a加10
let a=a-10 let a-=10 #变量a减10
let a=a*2 let a*=2 #变量a乘以2
let a=a/2 let a/=2 #变量a除以2
let a=a%3 let a%=3 #变量a除以3取余数
bc
交互式
bc
非交互式
echo "1.1+1" | bc
echo "10/3" | bc
echo "scale=2;10/3" | bc #scale可以定义结果是小数点后多少位
echo "10/3" | bc
echo "scale=2;10/3" | bc #scale可以定义结果是小数点后多少位
DAY02
条件测试
使用“test 表达式”或者[ 表达式 ]都可以,注意空格不要缺少。
条件测试操作本身不显示出任何信息。所以可以在测试后查看变量$?的值来做出判断。
条件测试操作本身不显示出任何信息。所以可以在测试后查看变量$?的值来做出判断。
字符串测试
== 比较两个字符串是否相同
!= 比较两个字符串是否不相同
- z
! - z
-n
! - z
-n
&& 逻辑与
|| 逻辑或
|| 逻辑或
# A && B #仅当A命令执行成功,才执行B命令
# A || B #仅当A命令执行失败,才执行B命令
# A ; B #执行A命令后执行B命令,两者没有逻辑关系
# A || B #仅当A命令执行失败,才执行B命令
# A ; B #执行A命令后执行B命令,两者没有逻辑关系
[ root == $USER ] || exit
[ root != $USER ] && exit 结果一致
[ root != $USER ] && exit 结果一致
touch a b c
ls a && ls b && ls c #结果是都显示
ls a || ls b || ls c #结果是显示a
ls a && ls b || ls c #结果是显示a和b
ls a || ls b && ls c #结果是显示a和c
ls a && ls b && ls c #结果是都显示
ls a || ls b || ls c #结果是显示a
ls a && ls b || ls c #结果是显示a和b
ls a || ls b && ls c #结果是显示a和c
整数值比较
-eq 等于
-ne 不等于
-gt 大于
-ge 大于等于
-lt 小于
-le 小于等于
文件/目录的测试
-e 判断文件是否存在,不关心文件类型
[ -e "/opt/a" ] && echo "yes" || echo "no"
[ -e "/opt/a" ] && echo "yes" || echo "no"
-d 判断对象是否为目录(存在且是目录)
[ -d "/opt/b" ] && echo "yes" || echo "no"
[ -d "/opt/b" ] && echo "yes" || echo "no"
-f 判断对象是否为文件(存在且是普通文件)
-r 判断当前用户对文件是否有读权限
-w 判断当前用户对文件是否有写权限
-x 判断当前用户对文件是否有 x 权限
if 分支
if 单分支
if 条件测试;then
指令1
指令2
...
fi
指令1
指令2
...
fi
#!/bin/bash
if [ $UID -eq 0 ];then
echo "我是管理员"
echo ok
fi
if [ $UID -eq 0 ];then
echo "我是管理员"
echo ok
fi
if 双分支
if 条件测试;then
指令1
...
else
指令1
...
fi
指令1
...
else
指令1
...
fi
#!/bin/bash
if [ $UID -eq 0 ];then
echo "我是管理员"
echo ok
else
echo "我不是管理员"
echo no
fi
if [ $UID -eq 0 ];then
echo "我是管理员"
echo ok
else
echo "我不是管理员"
echo no
fi
if 多分支
if 条件测试;then
指令1
...
elif 条件测试2;then
指令1
...
elif 条件测试n;then
指令1
..
else
指令1
...
fi
指令1
...
elif 条件测试2;then
指令1
...
elif 条件测试n;then
指令1
..
else
指令1
...
fi
#!/bin/bash
read -p "yuekao chengji " x
if [ $x -ge 90 ] && [ $x -le 100 ];then
echo "A"
elif [ $x -ge 80 ] && [ $x -le 89 ];then
echo "B"
elif [ $x -ge 60 ] && [ $x -le 79 ];then
echo "C"
elif [ $x -ge 0 ] && [ $x -le 59 ];then
echo "come on!!!"
else
echo "please--again!!!"
fi
read -p "yuekao chengji " x
if [ $x -ge 90 ] && [ $x -le 100 ];then
echo "A"
elif [ $x -ge 80 ] && [ $x -le 89 ];then
echo "B"
elif [ $x -ge 60 ] && [ $x -le 79 ];then
echo "C"
elif [ $x -ge 0 ] && [ $x -le 59 ];then
echo "come on!!!"
else
echo "please--again!!!"
fi
ping
ping -c 10 -i 0.1 -W 1 192.168.88.88
#!/bin/bash
ping -c 5 -i 0.1 -W 1 192.168.88.222 &> /dev/null
if [ $? -eq 0 ];then
echo "ok"
else
echo "no"
fi
ping -c 5 -i 0.1 -W 1 192.168.88.222 &> /dev/null
if [ $? -eq 0 ];then
echo "ok"
else
echo "no"
fi
vim中变量: ping -c 5 -i 0.1 -W 1 $1 &> /dev/null
执行:bash test3.sh 192.168.88.55
执行:bash test3.sh 192.168.88.55
vim中: read -p “请输入ip地址:” ip
ping -c 5 -i 0.1 -W 1 $ip &> /dev/null
ping -c 5 -i 0.1 -W 1 $ip &> /dev/null
for循环
格式一:
for 变量名 in 值1 值 2 ... #值的数量决定循环任务的次数
do
命令
.......
done
for 变量名 in 值1 值 2 ... #值的数量决定循环任务的次数
do
命令
.......
done
#!/bin/bash
for i in 1 2 3 4 5
do
echo "hello world"
done
for i in 1 2 3 4 5
do
echo "hello world"
done
#!/bin/bash
for i in {1..100} #值为1~100
do
echo "abc"
done
for i in {1..100} #值为1~100
do
echo "abc"
done
#!/bin/bash
a=10
for i in $(seq $a)
do
echo
echo $i
done
a=10
for i in $(seq $a)
do
echo
echo $i
done
seq: a=10 生成数字序列的工具
seq $a
seq $a
#!/bin/bash
for i in {1..10}
do
ping -c 3 -i 0.1 -W 1 192.168.88.$i &> /dev/null
if [ $? -eq 0 ];then
echo "ok"
else
echo "no"
fi
done
for i in {1..10}
do
ping -c 3 -i 0.1 -W 1 192.168.88.$i &> /dev/null
if [ $? -eq 0 ];then
echo "ok"
else
echo "no"
fi
done
综合:
#!/bin/bash
x=0
y=0
for i in {1..10}
do
ping -c 2 -i 0.1 -W 1 192.168.88.$i &> /dev/null
if [ $? -eq 0 ];then
echo "通了!"
let x++
else
echo“不通!”
let y++
fi
done
echo $x "台通了!" $y "台不通!"
#!/bin/bash
x=0
y=0
for i in {1..10}
do
ping -c 2 -i 0.1 -W 1 192.168.88.$i &> /dev/null
if [ $? -eq 0 ];then
echo "通了!"
let x++
else
echo“不通!”
let y++
fi
done
echo $x "台通了!" $y "台不通!"
格式二: c语言风格
for ((初值;条件;步长控制)) ---步长控制a++
do
命令序列
done
for ((初值;条件;步长控制)) ---步长控制a++
do
命令序列
done
#!/bin/bash
for ((i=1;i<=5;i++))
do
echo $i
done
for ((i=1;i<=5;i++))
do
echo $i
done
可以根据需求定义循环次数
补:vim /root/.vimrc
au filetype sh set ai ts=4 #shell文件,自动缩进四个字符
au filetype sh set ai ts=4 #shell文件,自动缩进四个字符
while
#根据条件的结果决定是否要执行任务,条件测试成功的话就一直执行,如果失败立刻结束循环
while 条件测试 ------情况不确定的时候使用
do
命令序列
done
do
命令序列
done
DAYO3
中断及退出
exit结束循环以及整个脚本
break可以结束整个循环,继续执行循环后任务
continue结束本次循环,进入下一次循环
break可以结束整个循环,继续执行循环后任务
continue结束本次循环,进入下一次循环
#!/bin/bash
for i in {1..5}
do
echo $i
[ $i -eq 3 ]&& break #这里将break替换为continue,exit分别测试脚本执行效果 echo $i
echo $i
done
echo "Game Over"
for i in {1..5}
do
echo $i
[ $i -eq 3 ]&& break #这里将break替换为continue,exit分别测试脚本执行效果 echo $i
echo $i
done
echo "Game Over"
x=0
while :
do
read -p "请输入一个整数求和(0是结束并输出结果):" n
[ -z $n ] && continue #如果n是空值则重新进行循环任务
[ $n -eq 0 ] && break #如果n是0则退出循环执行循环后任务
let x+=n #不断的将n的值保存在x里
done
echo "总和是$x"
while :
do
read -p "请输入一个整数求和(0是结束并输出结果):" n
[ -z $n ] && continue #如果n是空值则重新进行循环任务
[ $n -eq 0 ] && break #如果n是0则退出循环执行循环后任务
let x+=n #不断的将n的值保存在x里
done
echo "总和是$x"
case分支,类似if
区分:
if根据条件测试的条件调用
case是根据值调用
if根据条件测试的条件调用
case是根据值调用
case 调用的变量名 in
模式1)
命令序列1 ;;
模式2)
命令序列2 ;;
.. ..
.. .. ..
*) *通配符,一律匹配,类似于else
默认命令序列 此处可以省略双分号;;
esac
模式1)
命令序列1 ;;
模式2)
命令序列2 ;;
.. ..
.. .. ..
*) *通配符,一律匹配,类似于else
默认命令序列 此处可以省略双分号;;
esac
case $1 in
t) #如果$1是t就执行touch任务
touch $2;;
m) #如果$1是m就执行mkdir任务
mkdir $2;;
r) #如果$1是r就执行rm任务
rm -rf $2;;
*)
echo "请输入t或者m或者r"
esac
t) #如果$1是t就执行touch任务
touch $2;;
m) #如果$1是m就执行mkdir任务
mkdir $2;;
r) #如果$1是r就执行rm任务
rm -rf $2;;
*)
echo "请输入t或者m或者r"
esac
编写一键部署软件脚本
#!/bin/bash
yum -y install gcc openssl-devel pcre-devel #依赖包
tar -xf nginx-1.22.1.tar.gz
cd nginx-1.22.1
./configure
make
make install
yum -y install gcc openssl-devel pcre-devel #依赖包
tar -xf nginx-1.22.1.tar.gz
cd nginx-1.22.1
./configure
make
make install
/usr/local/nginx/sbin/nginx #启动服务
/usr/local/nginx/sbin/nginx -s stop #关闭服务
/usr/local/nginx/sbin/nginx -s stop #关闭服务
启动脚本
case $1 in
start|kai|k)
/usr/local/nginx/sbin/nginx;;
stop|guan|g)
/usr/local/nginx/sbin/nginx -s stop;;
restart|cq|r)
/usr/local/nginx/sbin/nginx -s stop
/usr/local/nginx/sbin/nginx;;
status|cha)
ss -unltp | grep -q nginx
[ $? -eq 0 ] && echo "nginx is running" || echo "nginx is down";;
*)
echo "write start/stop"
esac
start|kai|k)
/usr/local/nginx/sbin/nginx;;
stop|guan|g)
/usr/local/nginx/sbin/nginx -s stop;;
restart|cq|r)
/usr/local/nginx/sbin/nginx -s stop
/usr/local/nginx/sbin/nginx;;
status|cha)
ss -unltp | grep -q nginx
[ $? -eq 0 ] && echo "nginx is running" || echo "nginx is down";;
*)
echo "write start/stop"
esac
[ $? -eq 0 ] && echo "nginx is running" || echo "nginx is down";;
相当于:
if [ $? -eq 0 ];then
echo 服务已启动
else
echo 服务未启动
fi;;
相当于:
if [ $? -eq 0 ];then
echo 服务已启动
else
echo 服务未启动
fi;;
ss命令
ss命令可以查看系统中启动的端口信息,该命令常用选项如下:
-n以数字格式显示端口号
-t显示TCP连接的端口
-u显示UDP连接的端口
-l显示服务正在监听的端口信息,如httpd启动后,会一直监听80端口
-p显示监听端口的服务名称是什么(也就是程序名称)
-n以数字格式显示端口号
-t显示TCP连接的端口
-u显示UDP连接的端口
-l显示服务正在监听的端口信息,如httpd启动后,会一直监听80端口
-p显示监听端口的服务名称是什么(也就是程序名称)
shell函数
将常用的语句块放入名称中,方便后期调用
格式
格式1:
function 函数名 {
命令序列
... ...
}
function 函数名 {
命令序列
... ...
}
格式2:
函数名 (){
命令序列
... ...
}
函数名 (){
命令序列
... ...
}
#!/bin/bash
a(){
echo -e "\033[$1m$2\033[0m"
}
a
a
a(){
echo -e "\033[$1m$2\033[0m"
}
a
a
31--37:普通色
41-4?:背景色
91-9?:高亮色
41-4?:背景色
91-9?:高亮色
#!/bin/bash
a(){
echo -e "\033[$1m$2\033[0m"
}
case $1 in
start|kai|k)
/usr/local/nginx/sbin/nginx;;
stop|guan|g)
/usr/local/nginx/sbin/nginx -s stop;;
restart|cq|r)
/usr/local/nginx/sbin/nginx -s stop
/usr/local/nginx/sbin/nginx;;
status|cha)
ss -unltp | grep -q nginx
[ $? -eq 0 ] && a 32 "nginx is running" || a 31 "nginx is down";;
#==if [ $? -eq 0 ];then echo 服务已启动 else echo 服务未启动 fi;;
*)
echo "write start/stop"
esac
a(){
echo -e "\033[$1m$2\033[0m"
}
case $1 in
start|kai|k)
/usr/local/nginx/sbin/nginx;;
stop|guan|g)
/usr/local/nginx/sbin/nginx -s stop;;
restart|cq|r)
/usr/local/nginx/sbin/nginx -s stop
/usr/local/nginx/sbin/nginx;;
status|cha)
ss -unltp | grep -q nginx
[ $? -eq 0 ] && a 32 "nginx is running" || a 31 "nginx is down";;
#==if [ $? -eq 0 ];then echo 服务已启动 else echo 服务未启动 fi;;
*)
echo "write start/stop"
esac
字符串
变量中的字符串
截取:${变量名:起始位置:长度} #起始位置从0开始
得到一个密码:
#!/bin/bash
x=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
pass= #使用变量pass 防止使用source运行时候数字叠加
for i in {1..8}
do
n=$[RANDOM%62] #得到0~61随机数存在变量n中
p=${x:n:1} #通过截取,将1个随机字符赋值给变量p
pass+=$p #将随机得到的字符赋值给变量pass
done
echo $pass
#!/bin/bash
x=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
pass= #使用变量pass 防止使用source运行时候数字叠加
for i in {1..8}
do
n=$[RANDOM%62] #得到0~61随机数存在变量n中
p=${x:n:1} #通过截取,将1个随机字符赋值给变量p
pass+=$p #将随机得到的字符赋值给变量pass
done
echo $pass
得到100个密码:
#!/bin/bash
x=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
for j in {1..100}
do
pass=
for i in {1..8}
do
n=$[RANDOM%62]
p=${x:n:1}
pass+=$p
done
echo $pass
done
#!/bin/bash
x=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
for j in {1..100}
do
pass=
for i in {1..8}
do
n=$[RANDOM%62]
p=${x:n:1}
pass+=$p
done
echo $pass
done
字符串的替换
临时
${变量名/旧/新} 只替换第一个目标
${变量名//旧/新} 替换全部目标
${变量名/旧旧/新} 替换连续两个值
${变量名//旧/新} 替换全部目标
${变量名/旧旧/新} 替换连续两个值
掐头:
去尾:
去尾:
永久
A=${A/旧/新} 只替换第一个目标
A=${A//旧/新} 替换全部目标 重新赋值
A=${A//旧/新} 替换全部目标 重新赋值
DAY04
正则表达式
^ 匹配行首
$ 匹配行尾
[ ] 集合,匹配集合中的任意单个字符
[ ^ ] 对集合取反
. 匹配任意单个字符
* 匹配前一个字符任意次数;不单独使用
\{ n,m\} 匹配前一个字符n到m次;不单独使用
\{ n,\} 匹配前一个字符n次及以上;不单独使用
\{ n\} 匹配前一个字符n次;不单独使用
\( \ ) 组合为整体,保留
$ 匹配行尾
[ ] 集合,匹配集合中的任意单个字符
[ ^ ] 对集合取反
. 匹配任意单个字符
* 匹配前一个字符任意次数;不单独使用
\{ n,m\} 匹配前一个字符n到m次;不单独使用
\{ n,\} 匹配前一个字符n次及以上;不单独使用
\{ n\} 匹配前一个字符n次;不单独使用
\( \ ) 组合为整体,保留
grep ^root user #找以root开头的行
grep bash$ user #找以bash结尾的行
grep ^$ user #找空行
grep -v ^$ user #显示除了空行的内容
grep "[root]" user #找r、o、t任意一个字符
grep "[rot]" user #效果同上
grep "[^rot]" user #显示r或o或t以外的内容
grep "[0123456789]" user #找所有数字
grep "[0-9]" user #效果同上
grep "[^0-9]" user #显示数字以外内容
grep "[a-z]" user #找所有小写字母
grep "[A-Z]" user #找所有大写字母
grep "[a-Z]" user #找所有字母
grep "[^0-9a-Z]" user #找所有符号
grep bash$ user #找以bash结尾的行
grep ^$ user #找空行
grep -v ^$ user #显示除了空行的内容
grep "[root]" user #找r、o、t任意一个字符
grep "[rot]" user #效果同上
grep "[^rot]" user #显示r或o或t以外的内容
grep "[0123456789]" user #找所有数字
grep "[0-9]" user #效果同上
grep "[^0-9]" user #显示数字以外内容
grep "[a-z]" user #找所有小写字母
grep "[A-Z]" user #找所有大写字母
grep "[a-Z]" user #找所有字母
grep "[^0-9a-Z]" user #找所有符号
grep "." user #找任意单个字符,文档中每个字符都可以理解为任意字符
grep "r..t" user #找rt之间有2个任意字符的行
grep "r.t" user #找rt之间有1个任意字符的行,没有匹配内容,就无输出
grep "*" user #错误用法,*号是匹配前一个字符任意次,不能单独使用
grep "ro*t" user #找rt,中间的o有没有都行,有几次都行
grep ".*" user #找任意,包括空行 .与*的组合在正则中相当于通配符的效果
grep "r..t" user #找rt之间有2个任意字符的行
grep "r.t" user #找rt之间有1个任意字符的行,没有匹配内容,就无输出
grep "*" user #错误用法,*号是匹配前一个字符任意次,不能单独使用
grep "ro*t" user #找rt,中间的o有没有都行,有几次都行
grep ".*" user #找任意,包括空行 .与*的组合在正则中相当于通配符的效果
grep "ro\{1,2\}t" user #找rt,中间的o可以有1~2个
grep "ro\{2,6\}t" user #找rt,中间的o可以有2~6个
grep "ro\{1,\}t" user #找rt,中间的o可以有1个以及1个以上
grep "ro\{3\}t" user #找rt,中间的o必须只有有3个
grep "ro\{2,6\}t" user #找rt,中间的o可以有2~6个
grep "ro\{1,\}t" user #找rt,中间的o可以有1个以及1个以上
grep "ro\{3\}t" user #找rt,中间的o必须只有有3个
grep 只支持基本正则
补: bash -x 执行脚本,显示详细步骤
扩展正则
+ 最少匹配一次
? 最多匹配一次
{n,m} 匹配前一个字符n到m次
( ) 组合为整体,保留
| 或者
\b 单词边界
? 最多匹配一次
{n,m} 匹配前一个字符n到m次
( ) 组合为整体,保留
| 或者
\b 单词边界
使用 egrep grep -E
grep "ro\{1,\}t" user #使用基本正则找o出现1次以及1次以上
egrep "ro{1,}t" user #使用扩展正则,效果同上,比较精简
egrep "ro+t" user #使用扩展正则,效果同上,最精简
grep "roo\{0,1\}t" user #使用基本正则找第二个o出现0~1次
egrep "roo{0,1}t" user #使用扩展正则,效果同上,比较精简
egrep "roo?t" user #使用扩展正则,效果同上,最精简
egrep "(0:){2}" user #找连续的2个0: 小括号的作用是将字符组合为一个整体
egrep "root|bin" user #找有root或者bin的行
egrep "the\b" abc.txt #找单词the,右边不允许出现数字、字母、下划线
egrep "\bthe\b" abc.txt #the两边都不允许出现数字、字母、下划线
egrep "\<the\>" abc.txt #效果同上
egrep "ro{1,}t" user #使用扩展正则,效果同上,比较精简
egrep "ro+t" user #使用扩展正则,效果同上,最精简
grep "roo\{0,1\}t" user #使用基本正则找第二个o出现0~1次
egrep "roo{0,1}t" user #使用扩展正则,效果同上,比较精简
egrep "roo?t" user #使用扩展正则,效果同上,最精简
egrep "(0:){2}" user #找连续的2个0: 小括号的作用是将字符组合为一个整体
egrep "root|bin" user #找有root或者bin的行
egrep "the\b" abc.txt #找单词the,右边不允许出现数字、字母、下划线
egrep "\bthe\b" abc.txt #the两边都不允许出现数字、字母、下划线
egrep "\<the\>" abc.txt #效果同上
sed的基本用法
用法:前置命令 | sed [选项] '条件指令'
sed [选项] '条件指令' 文件.. ..
sed [选项] '条件指令' 文件.. ..
选项:
-n 屏蔽默认输出,默认情况下会输出读取的内容
-r 支持扩展正则
-i 修改源文件
-n 屏蔽默认输出,默认情况下会输出读取的内容
-r 支持扩展正则
-i 修改源文件
sed -n 'p' user #输出所有行
sed -n '1p' user #输出第1行
sed -n '2p' user #输出第2行
sed -n '3p' user #输出第3行
sed -n '2,4p' user #输出2~4行
sed -n '2p;4p' user #输出第2行与第4行
sed -n '3,+1p' user #输出第3行以及后面1行
sed -n '1~2p' /etc/passwd #输出奇数行
sed -n '1p' user #输出第1行
sed -n '2p' user #输出第2行
sed -n '3p' user #输出第3行
sed -n '2,4p' user #输出2~4行
sed -n '2p;4p' user #输出第2行与第4行
sed -n '3,+1p' user #输出第3行以及后面1行
sed -n '1~2p' /etc/passwd #输出奇数行
sed -n '/^root/p' user #输出以root开头的行
sed -n '/root/p' user #输出包含root的行
sed -nr '/^root|^bin/p' user #输出以root开头的行或bin开头的行,|是扩展正则,需要r选项
sed -n '/root/p' user #输出包含root的行
sed -nr '/^root|^bin/p' user #输出以root开头的行或bin开头的行,|是扩展正则,需要r选项
特殊用法:
sed -n '1!p' user #输出除了第1行的内容,!是取反
sed -n '$p' user #输出最后一行
sed -n '=' user #输出行号,如果是$=就是最后一行的行号
sed -n '1!p' user #输出除了第1行的内容,!是取反
sed -n '$p' user #输出最后一行
sed -n '=' user #输出行号,如果是$=就是最后一行的行号
指令:
p:输出
d:删除
s:替换
p:输出
d:删除
s:替换
sed -n 'p' a.txt #输出所有行,等同于cat a.txt
sed -n '4p' a.txt #输出第4行
sed -n '4,7p' a.txt #输出第4~7行
sed -n '/^bin/p' a.txt #输出以bin开头的行
sed -n '$=' a.txt #输出文件的行数
sed -n '4p' a.txt #输出第4行
sed -n '4,7p' a.txt #输出第4~7行
sed -n '/^bin/p' a.txt #输出以bin开头的行
sed -n '$=' a.txt #输出文件的行数
sed '3,5d' a.txt #删除第3~5行
sed '/xml/d' a.txt #删除所有包含xml的行
sed '/xml/!d' a.txt #删除不包含xml的行,!符号表示取反
sed '/^install/d' a.txt #删除以install开头的行
sed '$d' a.txt #删除文件的最后一行
sed '/^$/d' a.txt #删除所有空行
sed '/xml/d' a.txt #删除所有包含xml的行
sed '/xml/!d' a.txt #删除不包含xml的行,!符号表示取反
sed '/^install/d' a.txt #删除以install开头的行
sed '$d' a.txt #删除文件的最后一行
sed '/^$/d' a.txt #删除所有空行
s
基本功能
(s/旧内容/新内容/选项)
(s/旧内容/新内容/选项)
[root@svr5 ~]# vim shu.txt #新建素材
2017 2011 2018
2017 2017 2024
2017 2017 2017
sed 's/2017/6666/' shu.txt #把所有行的第1个2017替换成6666
sed 's/2017/6666/2' shu.txt #把所有行的第2个2017替换成6666
sed '1s/2017/6666/' shu.txt #把第1行的第1个2017替换成6666
sed '3s/2017/6666/3' shu.txt #把第3行的第3个2017替换成6666
sed 's/2017/6666/g' shu.txt #所有行的所有个2017都替换
sed '/2024/s/2017/6666/g' shu.txt #找含有2024的行,将里面的所有2017替换成6666
2017 2011 2018
2017 2017 2024
2017 2017 2017
sed 's/2017/6666/' shu.txt #把所有行的第1个2017替换成6666
sed 's/2017/6666/2' shu.txt #把所有行的第2个2017替换成6666
sed '1s/2017/6666/' shu.txt #把第1行的第1个2017替换成6666
sed '3s/2017/6666/3' shu.txt #把第3行的第3个2017替换成6666
sed 's/2017/6666/g' shu.txt #所有行的所有个2017都替换
sed '/2024/s/2017/6666/g' shu.txt #找含有2024的行,将里面的所有2017替换成6666
sed -i '1s/bin/sbin/' user #传统方法可以一个一个换,先换一个
sed -i '1s/bash/sh/' user #再换一个
sed 's//bin/bash//sbin/sh/' user #直接替换,报错
sed 's/\/bin\/bash/\/sbin\/sh/' user #使用转义符号可以成功,但不方便
sed 's!/bin/bash!/sbin/sh!' user #最佳方案,更改s的替换符
sed 's(/bin/bash(/sbin/sh(' user #替换符号可以用键盘上大部分字符
sed -i '1s/bash/sh/' user #再换一个
sed 's//bin/bash//sbin/sh/' user #直接替换,报错
sed 's/\/bin\/bash/\/sbin\/sh/' user #使用转义符号可以成功,但不方便
sed 's!/bin/bash!/sbin/sh!' user #最佳方案,更改s的替换符
sed 's(/bin/bash(/sbin/sh(' user #替换符号可以用键盘上大部分字符
脚本
找到使用bash作登录Shell的本地账户名
列出这些账户的shadow密码记录
按每行“账户名 --> 密码记录”保存到文件中
列出这些账户的shadow密码记录
按每行“账户名 --> 密码记录”保存到文件中
#!/bin/bash
u=$(sed -n '/bash$/s/:.*//p' /etc/passwd)
#找到passwd文档中以bash结尾的行,然后将行中冒号以及冒号后面内容都删除,此处的p代表仅仅显示s替换成功的行,最后赋值给u
for i in $u #将那些用bash的账户名交给for循环
do
pass=$(grep $i /etc/shadow) #用每个账户名去shadow中找对应信息
pass=${pass#*:} #掐头,从左往右删除到第1个冒号
pass=${pass%%:*} #去尾,从右往左删除到最后一个冒号经过上述步骤,pass就是最终要的密码了
echo "$i --> $pass" #按格式喊出,如果要存到文件中就用追加重定向
done
u=$(sed -n '/bash$/s/:.*//p' /etc/passwd)
#找到passwd文档中以bash结尾的行,然后将行中冒号以及冒号后面内容都删除,此处的p代表仅仅显示s替换成功的行,最后赋值给u
for i in $u #将那些用bash的账户名交给for循环
do
pass=$(grep $i /etc/shadow) #用每个账户名去shadow中找对应信息
pass=${pass#*:} #掐头,从左往右删除到第1个冒号
pass=${pass%%:*} #去尾,从右往左删除到最后一个冒号经过上述步骤,pass就是最终要的密码了
echo "$i --> $pass" #按格式喊出,如果要存到文件中就用追加重定向
done
DAY05
正则表达补充
\w 匹配数字、字母、下划线
\s 匹配空格、tab键
egrep "\s" user
\d 匹配数字,和[0-9]等效;grep -P才能支持使用
\s 匹配空格、tab键
egrep "\s" user
\d 匹配数字,和[0-9]等效;grep -P才能支持使用
egrep "(25[0-5]\.|2[0-4][0-9]\.|1?[0-9]?[0-9]\.){3}(25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])" #匹配ip地址
grep -P "(25[0-5]\.|2[0-4]\d\.|1?\d?\d\.){3}(25[0-5]|2[0-4]\d|1?\d?\d)" #匹配ip地址
grep -P "(25[0-5]\.|2[0-4]\d\.|1?\d?\d\.){3}(25[0-5]|2[0-4]\d|1?\d?\d)" #匹配ip地址
a行下追加 i行上添加 c替换整行
sed 'a 666' user #所有行的下面追加666
sed '1a 666' user #第1行的下面追加666
sed '/^bin/a 666' user #在以bin开头的行的下面追加666
sed 'i 666' user #所有行的上面添加666
sed '5i 666' user #第5行的上面添加666
sed '$i 666' user #最后1行的上面添加666
sed 'c 666' user #所有行都替换成666
sed '1c 666' user #替换第1行为666
sed '1a 666' user #第1行的下面追加666
sed '/^bin/a 666' user #在以bin开头的行的下面追加666
sed 'i 666' user #所有行的上面添加666
sed '5i 666' user #第5行的上面添加666
sed '$i 666' user #最后1行的上面添加666
sed 'c 666' user #所有行都替换成666
sed '1c 666' user #替换第1行为666
替换特殊用法
cat abc.txt #先准备素材
100 laowang
98 gangge
59 laoniu
sed -r 's/([0-9]+)(\s+)([a-z]+)/\3\2\1/' abc.txt
#使用替换功能更改文本列,此处小括号相当于保留(复制),\1相当于粘贴之前第1个小括号里的内容
100 laowang
98 gangge
59 laoniu
sed -r 's/([0-9]+)(\s+)([a-z]+)/\3\2\1/' abc.txt
#使用替换功能更改文本列,此处小括号相当于保留(复制),\1相当于粘贴之前第1个小括号里的内容
awk
精确搜索
精确搜索
格式1:awk [选项] '[条件]{指令}' 文件
格式2:前置指令 | awk [选项] '[条件]{指令}'
格式2:前置指令 | awk [选项] '[条件]{指令}'
选项: -F 定义分隔符
指令: print 输出
内置变量: $1第一列
$2第二列
$0所有列
NR 行号
NF 列号
$2第二列
$0所有列
NR 行号
NF 列号
awk '{print}' abc.txt #输出所有
awk '/to/{print}' abc.txt #输出有to的那行
awk '{print $2}' abc.txt #输出所有行的第2列
awk '/to/{print $1}' abc.txt #输出有to的那行的第1列
awk '{print $0}' abc.txt #输出所有行所有列
awk '{print $0,$1}' abc.txt #输出所有行所有列,第1列
awk '{print NR}' abc.txt #输出所有行的行号
awk '{print NR,$0}' abc.txt #输出所有行的行号,所有列
awk '{print NR,NF}' abc.txt #输出所有行的行号,列号(有几列)
awk '/^bin/{print NR,$0}' user #找以bin开头的行,显示该行的行号,所有列
awk '/to/{print}' abc.txt #输出有to的那行
awk '{print $2}' abc.txt #输出所有行的第2列
awk '/to/{print $1}' abc.txt #输出有to的那行的第1列
awk '{print $0}' abc.txt #输出所有行所有列
awk '{print $0,$1}' abc.txt #输出所有行所有列,第1列
awk '{print NR}' abc.txt #输出所有行的行号
awk '{print NR,$0}' abc.txt #输出所有行的行号,所有列
awk '{print NR,NF}' abc.txt #输出所有行的行号,列号(有几列)
awk '/^bin/{print NR,$0}' user #找以bin开头的行,显示该行的行号,所有列
-F
空格可以写在常量双引号中
空格可以写在常量双引号中
awk -F: '{print $1}' user #文档中如果没有空格,可以用F修改分隔符
awk -F: '{print $1,$6}' user #使用冒号作为列的分隔符,显示第1、6列
awk -F [:/] '/^root/{print $1,$10}' user
awk -F: '{print $1" 的家目录是 "$6}' user #输出常量,加双引号即可
awk -F: '{print $1" 的解释器是 "$7}' user
awk -F: '{print $1,$6}' user #使用冒号作为列的分隔符,显示第1、6列
awk -F [:/] '/^root/{print $1,$10}' user
awk -F: '{print $1" 的家目录是 "$6}' user #输出常量,加双引号即可
awk -F: '{print $1" 的解释器是 "$7}' user
ifconfig eth0 | awk '/RX p/{print "eth0网卡接收的数据量是"$5"字节"}'
ifconfig eth0 | awk '/TX p/{print "eth0网卡发送的数据量是"$5"字节"}'
注:
RX为接收的数据量,TX为发送的数据量
ifconfig eth0 | awk '/TX p/{print "eth0网卡发送的数据量是"$5"字节"}'
注:
RX为接收的数据量,TX为发送的数据量
df -h | awk '/\/$/{print $4}' #使用df -h 作为前置指令交给awk处理找到以/结尾的行,并输出第4列
df -h | awk '/\/$/{print "根分区剩余容量是"$4}' #然后加常量输出
df -h | awk '/\/$/{print "根分区剩余容量是"$4}' #然后加常量输出
处理时机
BEGIN任务: BEGIN{ } 行前处理,读取文件内容前执行,指令执行1次;可执行额外任务
逐行任务: { } 逐行处理,读取文件过程中执行,指令执行n次
END任务: END{ } 行后处理,读取文件结束后执行,指令执行1次;可执行额外任务
逐行任务: { } 逐行处理,读取文件过程中执行,指令执行n次
END任务: END{ } 行后处理,读取文件结束后执行,指令执行1次;可执行额外任务
awk -F: 'BEGIN{print "start"}{print $1}END{print "over"}' user
awk 'BEGIN{print NR}{print NR}END{print NR}' user
awk 'BEGIN{print NR}{print NR}END{print NR}' user
补:“\t”显示Tab制表位;需要双引号
awk 'BEGIN{print "User\tUID\tHome"}'
awk -F: '{print $1"\t"$3"\t"$6}' user
awk -F: '{print $1"\t"$3"\t"$6}' user
条件
使用正则设置条件
/正则/ ~ 包含 !~不包含
/正则/ ~ 包含 !~不包含
awk -F: '$6~/root/{print}' user #输出第6列包含root的行
awk -F: '$6~/bin/{print}' user #输出第6列包含bin的行
awk -F: '$6!~/bin/{print}' user #输出第6列不包含bin的行
awk -F: '$6~/bin/{print}' user #输出第6列包含bin的行
awk -F: '$6!~/bin/{print}' user #输出第6列不包含bin的行
使用数值/字符串比较设置条件
比较符号:==(等于) !=(不等于) >(大于)
>=(大于等于) <(小于) <=(小于等于)
比较符号:==(等于) !=(不等于) >(大于)
>=(大于等于) <(小于) <=(小于等于)
awk -F: '$3<3{print}' user #输出第3列小于3的行
awk -F: '$3<=3{print}' user #输出第3列小于等于3的行
awk -F: 'NR==2{print}' user #输出第2行
awk -F: 'NR>2{print}' user #输出行号大于2的行
awk -F: '$3<=3{print}' user #输出第3列小于等于3的行
awk -F: 'NR==2{print}' user #输出第2行
awk -F: 'NR>2{print}' user #输出行号大于2的行
逻辑测试条件
awk -F: 'NR>=3&&NR<=5{print}' user #找行号是3~5行
awk -F: 'NR==2||NR==4{print}' user #找行号是2或者4的行
awk -F: 'NR==2||NR==40{print}' user #如果只有一个条件满足就显示一个
awk -F: 'NR==2||NR==4{print}' user #找行号是2或者4的行
awk -F: 'NR==2||NR==40{print}' user #如果只有一个条件满足就显示一个
当定义了条件且指令就是print时可以省略指令不写,{print}省略
awk -F: '$7~/bash/&&$3<=500' user #找第7列包含bash并且第3列小于等于500的行
awk 'NR==2&&NR==4' user #找行号既是2又是4的行,不存在,无输出
awk -F: '$7~/bash/&&NR<=3' user #找第7列包含bash并且行号是1~3的
awk -F: '$7~/bash/||NR<=3' user #找第7列包含bash或者行号是1~3的
awk -F: '$7~/bash/&&$3<=500' user #找第7列包含bash并且第3列小于等于500的行
awk 'NR==2&&NR==4' user #找行号既是2又是4的行,不存在,无输出
awk -F: '$7~/bash/&&NR<=3' user #找第7列包含bash并且行号是1~3的
awk -F: '$7~/bash/||NR<=3' user #找第7列包含bash或者行号是1~3的
数学运算
awk 'NR%2==0{print NR,$0}' user
#在条件中使用运算,找到将行号除以2余数等于0的行,然后输出该行的行号和所有列,相当于输出偶数行
#在条件中使用运算,找到将行号除以2余数等于0的行,然后输出该行的行号和所有列,相当于输出偶数行
数组
数组是一个可以存储多个值的变量
定义数组的格式:数组名[下标]=元素值
调用数组的格式:数组名[下标]
定义数组的格式:数组名[下标]=元素值
调用数组的格式:数组名[下标]
awk数组的下标除了可以使用数字,也可以使用字符串,字符串需要使用双引号
awk 'BEGIN{a[1]=10;a[2]=20;print a[2],a[1]}'
awk 'BEGIN{a["abc"]="abcabc";a["xyz"]="xyzxyz";print a["xyz"]}'
awk 'BEGIN{a[1]=10;a[2]=20;print a[2],a[1]}'
awk 'BEGIN{a["abc"]="abcabc";a["xyz"]="xyzxyz";print a["xyz"]}'
使用for循环:可以显示数组的下标
awk '{a[$1]++}END{for(i in a){print i,a[i]}}' /var/log/httpd/access_log | sort -nr -k 2
/var/log/httpd/access_log #httpd日志文件
sort -nr -k 2:排序 默认升序
-n 按数字方式排
-k 按照第二列排
-r 按照降序排列
/var/log/httpd/access_log #httpd日志文件
sort -nr -k 2:排序 默认升序
-n 按数字方式排
-k 按照第二列排
-r 按照降序排列
/var/log/secure #安全日志
awk '/Failed password for root/{ip[$11]++}END{for(i in ip){print i,ip[i]}}' /var/log/secure
#统计安全日志中访问root账户且密码输入错误的ip地址与次数
awk '/Failed password for root/{ip[$11]++}END{for(i in ip){print i,ip[i]}}' /var/log/secure
#统计安全日志中访问root账户且密码输入错误的ip地址与次数
DAY06
项目
系统初始化
要求
编写一个脚本可以匹配不同系统的服务器(包含7版本与8版本的系统)实现以下需求:
1,所有服务器永久关闭防火墙服务和SELinux
2,关闭7版本系统的命令历史记录,修改8版本的命令历史记录最多保存2000条并加上时间戳
3,关闭8版本系统的交换分区
4,定义root远程登录系统后的ssh保持时间为300秒
5,设置时间同步,ntp服务器地址是192.168.88.240
1,所有服务器永久关闭防火墙服务和SELinux
2,关闭7版本系统的命令历史记录,修改8版本的命令历史记录最多保存2000条并加上时间戳
3,关闭8版本系统的交换分区
4,定义root远程登录系统后的ssh保持时间为300秒
5,设置时间同步,ntp服务器地址是192.168.88.240
vim
#!/bin/bash
#1)判断身份,关闭防火墙和selinux
[ $UID -ne 0] && echo"必须用管理员操作" && exit
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
#2)根据不同版本的系统执行各自任务
egrep -q "\s+8\.[0-9]" /etc/redhat-release #-q不显示内容,\s 表示tab键或者空格,+至少一个,\转译.
if [ $? -ne 0 ];then
sed -ri 's/HISTSIZE=[0-9]+/HISTSIZE=0/' /etc/profile #-r 支持扩展正则:+ ;/etc/profile 全局配置文件系统范围的初始化脚本,用于设置用户的环境变量和路径
else
sed -ri 's/HISTSIZE=[0-9]+/HISTSIZE=2000/' /etc/profile
sed -i '/^export /i HISTTIMEFORMAT="%F %T " ' /etc/profile #历史命令时间戳,/i :i是export开头的行上添加
sed -i '/^export /s/$/ HISTTIMEFORMAT/' /etc/profile #找到export开头那行,在最后加 HISTTIMEFORMAT,可以在子进程中也显示时间戳
swap=$(swapon | awk 'NR!=1{print $1}') #找到交换分区,不是第一行的第一列打印
for i in $swap
do
swapoff $i #关闭所有交换分区
done
sed -i '/swap/s/^/#/' /etc/fstab #注释交换分区自动挂载
fi
#3)所有系统设置ssh超时时间与时间同步
echo "export TMOUT=300" >> ~/.bash_profile #TMOUT超时时间,全局变量export,~/.bash_profile当前用户配置文件
yum -y install chrony
systemctl enable chronyd
sed -ri '/^(pool|server).*iburst/s/^/#/' /etc/chrony.conf #^(pool|server)==^pool|^server
sed -i '1i server 192.168.88.240 iburst' /etc/chrony.conf #1i 将加入的内容放在第一行
systemctl restart chronyd
#1)判断身份,关闭防火墙和selinux
[ $UID -ne 0] && echo"必须用管理员操作" && exit
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
#2)根据不同版本的系统执行各自任务
egrep -q "\s+8\.[0-9]" /etc/redhat-release #-q不显示内容,\s 表示tab键或者空格,+至少一个,\转译.
if [ $? -ne 0 ];then
sed -ri 's/HISTSIZE=[0-9]+/HISTSIZE=0/' /etc/profile #-r 支持扩展正则:+ ;/etc/profile 全局配置文件系统范围的初始化脚本,用于设置用户的环境变量和路径
else
sed -ri 's/HISTSIZE=[0-9]+/HISTSIZE=2000/' /etc/profile
sed -i '/^export /i HISTTIMEFORMAT="%F %T " ' /etc/profile #历史命令时间戳,/i :i是export开头的行上添加
sed -i '/^export /s/$/ HISTTIMEFORMAT/' /etc/profile #找到export开头那行,在最后加 HISTTIMEFORMAT,可以在子进程中也显示时间戳
swap=$(swapon | awk 'NR!=1{print $1}') #找到交换分区,不是第一行的第一列打印
for i in $swap
do
swapoff $i #关闭所有交换分区
done
sed -i '/swap/s/^/#/' /etc/fstab #注释交换分区自动挂载
fi
#3)所有系统设置ssh超时时间与时间同步
echo "export TMOUT=300" >> ~/.bash_profile #TMOUT超时时间,全局变量export,~/.bash_profile当前用户配置文件
yum -y install chrony
systemctl enable chronyd
sed -ri '/^(pool|server).*iburst/s/^/#/' /etc/chrony.conf #^(pool|server)==^pool|^server
sed -i '1i server 192.168.88.240 iburst' /etc/chrony.conf #1i 将加入的内容放在第一行
systemctl restart chronyd
文档处理:
#!/bin/bash
while read name pass
do
[ -z $pass ] && continue #如果密码为空,则结束本次循环,开启下一次循环下一次循环
useradd $name
echo $pass | passwd --stdin $name
done < user.txt #输入重定向
#!/bin/bash
while read name pass
do
[ -z $pass ] && continue #如果密码为空,则结束本次循环,开启下一次循环下一次循环
useradd $name
echo $pass | passwd --stdin $name
done < user.txt #输入重定向
#!/bin/bash
x=$(awk '/^[a-zA-Z0-9]/&&!/已创建/{print NR}' user.txt) #$3!~ == ! 不包含/已创建/
if [ -z "$x" ];then #判断变量x
echo "没有新用户需要创建!"
column -t user.txt #文本数据转换为表格方式显示,每列自动对齐
exit
fi
for i in $x
do
pass=$(strings /dev/urandom | tr -cd '_a-zA-Z0-9' | head -c 10)
sed -i "${i}s/$/\t$pass/" user.txt
read name pass << EOF
$(sed -n "${i}p" user.txt)
EOF
useradd $name
echo $pass | passwd --stdin $name
sed -i "${i}s/$/\t已创建/" user.txt
done
column -t user.txt
x=$(awk '/^[a-zA-Z0-9]/&&!/已创建/{print NR}' user.txt) #$3!~ == ! 不包含/已创建/
if [ -z "$x" ];then #判断变量x
echo "没有新用户需要创建!"
column -t user.txt #文本数据转换为表格方式显示,每列自动对齐
exit
fi
for i in $x
do
pass=$(strings /dev/urandom | tr -cd '_a-zA-Z0-9' | head -c 10)
sed -i "${i}s/$/\t$pass/" user.txt
read name pass << EOF
$(sed -n "${i}p" user.txt)
EOF
useradd $name
echo $pass | passwd --stdin $name
sed -i "${i}s/$/\t已创建/" user.txt
done
column -t user.txt
菜单服务:定义函数menu
一
x=1 #高亮行号,默认为1即可
y=0 #第几行
menu (){ #循环显示菜单的函数
clear
for i in 1,安装ftp服务 2,开关ftp服务 3,退出
do
echo "----------------"
let y++
[ $x -eq $y ] && echo -e "\033[43;93m$i\033[0m" && continue
echo "$i"
done
y=0
echo "----------------"
}
三
ftp_install(){
if rpm -q vsftpd &> /dev/null;then
msg="vsftpd已安装"
else
yum -y install vsftpd &> /dev/null
[ $? -eq 0 ] && msg="vsftpd安装成功" || msg="vsftpd安装失败"
fi
}
五
ser_manager(){
if ! rpm -q vsftpd &> /dev/null;then
msg="未安装vsftpd软件包"
return
fi
case $1 in
start)
systemctl start vsftpd
msg="ftp服务已经启动"
ser_manager=start;;
stop)
systemctl stop vsftpd
msg="ftp服务已经关闭"
ser_manager=stop;;
esac
}
一
x=1 #高亮行号,默认为1即可
y=0 #第几行
menu (){ #循环显示菜单的函数
clear
for i in 1,安装ftp服务 2,开关ftp服务 3,退出
do
echo "----------------"
let y++
[ $x -eq $y ] && echo -e "\033[43;93m$i\033[0m" && continue
echo "$i"
done
y=0
echo "----------------"
}
三
ftp_install(){
if rpm -q vsftpd &> /dev/null;then
msg="vsftpd已安装"
else
yum -y install vsftpd &> /dev/null
[ $? -eq 0 ] && msg="vsftpd安装成功" || msg="vsftpd安装失败"
fi
}
五
ser_manager(){
if ! rpm -q vsftpd &> /dev/null;then
msg="未安装vsftpd软件包"
return
fi
case $1 in
start)
systemctl start vsftpd
msg="ftp服务已经启动"
ser_manager=start;;
stop)
systemctl stop vsftpd
msg="ftp服务已经关闭"
ser_manager=stop;;
esac
}
二
#!/bin/bash
. menu #读入菜单函数
while :
do
menu
read -n 3 c #-n 3是输入足够3个字符就自动进行下一步,c是存储字符的变量
if [ "$c" == $'\033[A' ];then #$'\033[A'代表键盘的 "上" 按键
[ $x -eq 1 ] && continue #根据变量x定义高亮行,在第1行就没变化
let x-- #如果不在第1行,就把x-1
elif [ "$c" == $'\033[B' ];then #$'\033[B'代表键盘的 "下" 按键
[ $x -eq 3 ] && continue #如果在第3行,没变化
let x++ #如果不在第3行,就把x+1
fi
done
四
#!/bin/bash
. menu #menu文件,读入菜单函数
. ftp_install #读入ftp安装函数文件
while :
do
menu #调用函数menu
echo "$msg"
read -n 3 c #定义变量c,-n 3当定义变量时,只要写入超多3个字符,自动写入变量,并回车
if [ "$c" == $'\033[A' ];then #$'\033[A'代表键盘的 "上" 按键
[ $x -eq 1 ] && continue
let x--
elif [ "$c" == $'\033[B' ];then #$'\033[B'代表键盘的 "下" 按键
[ $x -eq 3 ] && continue
let x++
elif [ $x -eq 1 ] && [ -z $c ];then
msg="ftp服务安装中..."
echo "$msg"
ftp_install
fi
done
六
#!/bin/bash
. menu #menu文件,读入菜单函数
. ftp_install #读入ftp安装函数文件
. ser_manager
while :
do
menu #调用函数menu
echo "$msg"
read -n 3 c #定义变量c,-n 3当定义变量时,只要写入超多3个字符,自动写入变量,并回车
if [ "$c" == $'\033[A' ];then #$'\033[A'代表键盘的 "上" 按键
[ $x -eq 1 ] && continue
let x--
elif [ "$c" == $'\033[B' ];then #$'\033[B'代表键盘的 "下" 按键
[ $x -eq 3 ] && continue
let x++
elif [ $x -eq 1 ] && [ -z $c ];then
msg="ftp服务安装中..."
echo "$msg"
ftp_install
elif [ $x -eq 2 ] && [ -z $c ];then
[ "$ser_manager" != "start" ] && ser_manager start || ser_manager stop
elif [ $x -eq 3 ] && [ -z $c ];then
exit
fi
done
#!/bin/bash
. menu #读入菜单函数
while :
do
menu
read -n 3 c #-n 3是输入足够3个字符就自动进行下一步,c是存储字符的变量
if [ "$c" == $'\033[A' ];then #$'\033[A'代表键盘的 "上" 按键
[ $x -eq 1 ] && continue #根据变量x定义高亮行,在第1行就没变化
let x-- #如果不在第1行,就把x-1
elif [ "$c" == $'\033[B' ];then #$'\033[B'代表键盘的 "下" 按键
[ $x -eq 3 ] && continue #如果在第3行,没变化
let x++ #如果不在第3行,就把x+1
fi
done
四
#!/bin/bash
. menu #menu文件,读入菜单函数
. ftp_install #读入ftp安装函数文件
while :
do
menu #调用函数menu
echo "$msg"
read -n 3 c #定义变量c,-n 3当定义变量时,只要写入超多3个字符,自动写入变量,并回车
if [ "$c" == $'\033[A' ];then #$'\033[A'代表键盘的 "上" 按键
[ $x -eq 1 ] && continue
let x--
elif [ "$c" == $'\033[B' ];then #$'\033[B'代表键盘的 "下" 按键
[ $x -eq 3 ] && continue
let x++
elif [ $x -eq 1 ] && [ -z $c ];then
msg="ftp服务安装中..."
echo "$msg"
ftp_install
fi
done
六
#!/bin/bash
. menu #menu文件,读入菜单函数
. ftp_install #读入ftp安装函数文件
. ser_manager
while :
do
menu #调用函数menu
echo "$msg"
read -n 3 c #定义变量c,-n 3当定义变量时,只要写入超多3个字符,自动写入变量,并回车
if [ "$c" == $'\033[A' ];then #$'\033[A'代表键盘的 "上" 按键
[ $x -eq 1 ] && continue
let x--
elif [ "$c" == $'\033[B' ];then #$'\033[B'代表键盘的 "下" 按键
[ $x -eq 3 ] && continue
let x++
elif [ $x -eq 1 ] && [ -z $c ];then
msg="ftp服务安装中..."
echo "$msg"
ftp_install
elif [ $x -eq 2 ] && [ -z $c ];then
[ "$ser_manager" != "start" ] && ser_manager start || ser_manager stop
elif [ $x -eq 3 ] && [ -z $c ];then
exit
fi
done
按要求每天备份文件
1.备份数据/var/www/html 里面除了.tmp类型的所有文件到/opt/backup_data
tar -cf xxx.tar --exclude *.tmp
2.备份文件要带时间戳,打tar包,格式为web_file_年-月-日.tar.gz
3.如果/opt/backup_data中备份的tar包凑齐5个之后,就都上传到ftp中并删除本地的这些tar包
4.任务执行成功或失败都要给出提示信息
使用tar工具可以通过文件选择功能的--exclude对不需要文件进行排除
1.备份数据/var/www/html 里面除了.tmp类型的所有文件到/opt/backup_data
tar -cf xxx.tar --exclude *.tmp
2.备份文件要带时间戳,打tar包,格式为web_file_年-月-日.tar.gz
3.如果/opt/backup_data中备份的tar包凑齐5个之后,就都上传到ftp中并删除本地的这些tar包
4.任务执行成功或失败都要给出提示信息
使用tar工具可以通过文件选择功能的--exclude对不需要文件进行排除
设置:
ftp服务端:
vim /etc/vsftpd/vsftpd.conf
anonymous_enable=YES #允许匿名
anon_upload_enable=YES #允许匿名上传
systemctl restart vsftpd
chmod o+w /var/ftp/pub
ftp客户端:
yum -y install lftp
#vim /etc/lftp.conf #修改lftp配置
set net:reconnect-interval-base 0 #重试时间0秒
set net:max-retries 1 #失败后是否重试,1不重试
lftp 192.168.99.5
cd pub #切换目录
mput test.txt #上传文件
quit #退出
ftp服务端:
vim /etc/vsftpd/vsftpd.conf
anonymous_enable=YES #允许匿名
anon_upload_enable=YES #允许匿名上传
systemctl restart vsftpd
chmod o+w /var/ftp/pub
ftp客户端:
yum -y install lftp
#vim /etc/lftp.conf #修改lftp配置
set net:reconnect-interval-base 0 #重试时间0秒
set net:max-retries 1 #失败后是否重试,1不重试
lftp 192.168.99.5
cd pub #切换目录
mput test.txt #上传文件
quit #退出
#!/bin/bash
sou_path=/var/www/html #定义备份数据的目录变量
tar_path=/opt/backup_data #定义tar包存储目录变量
date=$(date +%Y-%m-%d) #时间格式变量 年-月-日
ex_file=*.tmp #排除文件变量,除了.tmp结尾的文件
tar -zcPf ${tar_path}/web_file_${date}.tar.gz --exclude=$ex_file ${sou_path} #P是绝对路径保留
file_total=$(ls ${tar_path} | wc -l) #定义tar包总数变量
echo "${date}的文件已打tar包放入${tar_path},目前备份文件总数是${file_total}个"
if [ $file_total -ge 5 ];then
lftp 192.168.99.5 << EOF
cd pub
mput -q ${tar_path}/* #上传时用-q可屏蔽信息输出
quit
EOF
if [ $? -ne 0 ];then
echo "上传ftp出错,请检查文件或服务"
exit
else
rm -rf ${tar_path}/web_file*
echo "上传ftp成功!"
fi
fi
sou_path=/var/www/html #定义备份数据的目录变量
tar_path=/opt/backup_data #定义tar包存储目录变量
date=$(date +%Y-%m-%d) #时间格式变量 年-月-日
ex_file=*.tmp #排除文件变量,除了.tmp结尾的文件
tar -zcPf ${tar_path}/web_file_${date}.tar.gz --exclude=$ex_file ${sou_path} #P是绝对路径保留
file_total=$(ls ${tar_path} | wc -l) #定义tar包总数变量
echo "${date}的文件已打tar包放入${tar_path},目前备份文件总数是${file_total}个"
if [ $file_total -ge 5 ];then
lftp 192.168.99.5 << EOF
cd pub
mput -q ${tar_path}/* #上传时用-q可屏蔽信息输出
quit
EOF
if [ $? -ne 0 ];then
echo "上传ftp出错,请检查文件或服务"
exit
else
rm -rf ${tar_path}/web_file*
echo "上传ftp成功!"
fi
fi
注释
tr -cd '_a-zA-Z0-9' < /dev/urandom | head -c 10
tr:截取字符 c:取反 d:删除
/dev/urandom : 动态文件,海量
strings :查看动态文件
-c 10 10个字符
tr:截取字符 c:取反 d:删除
/dev/urandom : 动态文件,海量
strings :查看动态文件
-c 10 10个字符
0 条评论
下一页