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