Shell(第一天)
1、解释器
1)shell是解释器的总称,bash只是其中的一种
shell编程 bash脚本
为什么使用bash?
[root@server0 ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
/bin/ksh
2)更改使用某一个解释器 usermod -s
useradd -s /user/bi/bin/sh
/bin/kshn/ksh nb
su - nb
2、History
默认历史记录1000条
history -c //清空自己的历史命令
保存位置:/家目录/.bash_history
配置文件:/etc/profile
3、重定向
重定向输入 < 将文本输入来源由键盘改为指定文件
重定向输出 > 将命令行的正常执行输出保存到文件,而不是显示在屏幕
重定向输出 >> 追加
重定向错误 2>
重定向错误 2>>追加
混合重定向 &> 无论错误正确都覆盖到一个文件中
[root@server0 ~]# ls /etc/hosts nofile >log1 2>log2
#将一个存在的文件和不存在的文件 正确的导入log1,错误的导入log2
收发邮件的两种方法
echo hello | mail -s hello root
mail -s hello root < mail.txt //需要具备一个文件
4、变量
1)变量赋值
[root@desktop0 ~]# a=11
[root@desktop0 ~]# b=22
引用变量$a $b
[root@desktop0 ~]# echo $ab #查看变量
输出11b
[root@desktop0 ~]# echo ${a}${b} #注意括号
输出1122
2)取消变量:unset
3)存储类型变量:整数型,浮点型。。。
4)使用类型:环境变量,位置变量,预定义变量,自定义
5)环境变量 配置文件/etc/profile ~/.bash_profile
常见的环境变量:PWD、PATH、USER、LOGNAME、UID、
SHELL、HOME、PS1、PS2
PS1=XX#
6)预定义变量
$0 //当前所在进程或脚本名
$* //所有位置变量的值
$# //已加载的位置变量的个数
$? //上一条命令的输出状态,0表示正常,1或其他表示异常
$! //后台运行的最后一个进程
7)位置变量 在执行脚本时提供的命令行参数
$1 //第一个变量
$2 //第二个变量
env //查看当前系统的所有变量
set //列出所有变量
8)脚本的执行方式:
当没有加x权限的情况
sh 脚本文件路径
source 脚本文件路径
. 脚本文件路径
9)双引:使用双引号可以界定一个完整的字符串
touch a b //创建两个文件
touch “a b” //创建一个文件
单引:一个完整的字符串,并且屏蔽特殊符号
a=11
echo “$a” //输出a的值
echo ‘$a’ //输出$a
echo “ab” == echo ‘ab’
echo “$a” != echo ‘$a’
反引:` ` 和$效果一样
将命令的执行输出作为变量值
[root@desktop0 ~]# echo $(ls) #注意括号
1.sh anaconda-ks.cfg
[root@desktop0 ~]# echo `ls`
1.sh anaconda-ks.cfg
案例:每周五备份/etc/log
0 4 * * 5 tar -zcf /root/log.tar.gz /etc/log
//这样容易造成每周五将原有的数据覆盖
0 4 * * 5 tar -zcf /root/log.`date +%F`.tar.gz /etc/log
//这样就起到了每周五不会覆盖原有的数据
10)read 标准输入取值
格式:read [-p 提示信息] 变量名
11)stty -echo //关闭回显
stty echo //恢复
局部变量 a=11
全局变量 export a=11
Shell(第二天)
1、整数运算工具
1)expr命令
乘法操作应采用 \* 转义,避免被作为Shell通配符;参与运算的整数值与运算操作符之间需要以空格分开,引用变量时必须加$符号
X=1234
expr $X + 78
2)使用$[]或$(())表达式
乘法操作*无需转义,运算符两侧可以无空格;引用变量可省略 $ 符号([]内不需要在变量前加$);计算结果替换表达式本身,可结合echo命令输出。
[root@server0 ~]# x=1234
[root@server0 ~]# echo $[x+78] #注意和输出变量{}的区分
1312
[root@server0 ~]# echo $x+78
1234+78
3)let命令
expr或$[]、$(())方式只进行运算,并不会改变变量的值;而let命令可以直接对变量值做运算再保存新的值。因此变量X=1234,在执行let运算后的值会变更;另 外,let运算操作并不显示结果,但是可以结合echo命令来查看
[root@server0 ~]# x=1234
[root@server0 ~]# let y=x+22
[root@server0 ~]# echo $y
1256
[root@server0 ~]# x=7
[root@server0 ~]# let x*3 //不能这样写
[root@server0 ~]# echo $x //值为7
[root@server0 ~]# let x*=3
[root@server0 ~]# echo $x //值为21
2、小数运算工具
1)bc交互式运算
先执行bc命令进入交互环境,然后再输入需要计算的表达式。
scale=2 //小数点后面留出来2位数字
2)bc非交互式运算
将需要运算的表达式通过管道操作交给bc运算
[root@server0 ~]# echo 'scale=4;12.34+5.6789' | bc
18.0189
可以进行数值比较
[root@server0 ~]# echo "2>3" | bc
0 //2是否大于3 输出0错误
[root@server0 ~]# echo "3>2" | bc
1 //2是否大于3 输出1正确
和$?相反
3、条件测试操作
1)字符串测试
使用“test 表达式”或者[ 表达式 ]都可以,表达式两边至少要留一个空格。
== 比较两个字符串是否相同
[root@server0 ~]# [ $USER == "root" ] // [ ] 内双引号有无都可以,[ 后面需要有空格
[root@server0 ~]# [ $USER != "root" ]
[root@server0 ~]# echo $? //查看上一条命令的结果0为对,非0为错
-z 检查变量的值是否未设置(空值)
[root@server0 ~]# [ -z $dachui ]
[root@server0 ~]# echo $?
0
2)整数值比较
-eq -ne -ge -le -gt -lt
3)文件状态
-e -d -f -r -w -x
4)多个条件/操作的逻辑组合
&& || ;
A && B //执行A,当A成功后执行B
A || B //执行A,当A失败后执行B
A ;B //执行A ,执行B
-x 判断对象是否具有可执行权限(特殊)
[root@svr5 ~]# chmod 644 /1.sh
[root@server0 ~]# chmod -x 1.sh
[root@server0 ~]# ./1.sh
-bash: ./1.sh: 权限不够
//没有x权限root也执行不了
#判断有没有装包,有没有起服务的脚本
#!/bin/bash
rpm -q httpd
if [ $? -ne 0 ];then
yum -y install httpd &> /dev/null
fi
systemctl status httpd
if [ $? -ne 0 ];then
systemctl restart httpd
systemctl status httpd
echo $?
fi
Ping -c2 IP //count ping的次数
Ping -i0.1 IP //每次间隔的时间
Shell(第三天)
1、echo ;seq
echo {1..5}
seq 5
都是输出1到5
2 for
for i in 条件
do
done
[root@server0 ~]# for i in {1..5}
[root@server0 ~]# for i in `seq 5`
3、while
while 条件 (while : //死循环)
do
done
for 和while 的区别:
for 循环有限制 while 循环无限制
[root@server0 ~]# echo $[2**3]
8
4、case
case 变量值 in
模式1)
命令序列1;;
模式2)
命令序列2;;
*)
默认命令序列
esac
case 简单,功能少
5、输出颜色
[root@server0 ~]# echo -e "\033[38mOK\033[0m"
[root@server0 ~]# echo -e "\033[34mOK\033[0m"
两次输出的OK的颜色不一样
-e extend(扩展)
3x代表字体色
4x代表背景色
0x代表样式
三个可以写在一起
格式:
[root@server0 ~]# echo -e "\033[34m:44m:01mOK\033[0m"
6、中断
中断[break,continue,exit]
1)break结束整个循环
#!/bin/bash
for i in {1..5}
do
[ $i -eq 3 ] && break
echo $i
done
echo OK
运行结果:1 2 OK
2)continue结束本次循环,跳到下一个循环
#!/bin/bash
for i in {1..5}
do
[ $i -eq 3 ] && continue
echo $i
done
echo OK
运行结果:1 2 4 5 OK
3)exit结束脚本
#!/bin/bash
for i in {1..5}
do
[ $i -eq 3 ] && exit
echo $i
done
echo OK
运行结果:1 2
Shell(第四天)
1、子串截取的三种用法
1)${var:起始位置:长度} //从第0位开始
[root@server0 ~]# X=135556684456
[root@server0 ~]# echo ${#X} #获取变量x有多少位
12
//统计X的长度
[root@server0 ~]# echo ${X:0:4}
1355
2)expr substr "$var" 起始位置 长度 #该方法起始从1开始
[root@server0 ~]# expr substr $X 2 4
3)echo $var | cut -b 起始位置-结束位置 #该方法起始从1开始
[root@server0 ~]# echo $X | cut -b 4-6
2、字符串的替换
1)只替换第1个子串
格式:${var/old/new}
[root@server0 ~]# x=123456123456
[root@server0 ~]# echo ${x/3/*}
12*456123456
2)替换全部子串
格式:${var//old/new}
[root@server0 ~]# echo ${x//3/*}
12*45612*456
(替换不影响x的值,只会影响输出的显示效果)
3、字符串的匹配删除
1)从左向右,最短匹配删除(掐头)
格式:${变量名#*关键词}
删除从左侧第1个字符到最近的关键词的部分,* 作通配符理解:
[root@server0 ~]# x='root:x:0:0:root:/root:/bin/bash'
[root@server0 ~]# echo ${x#*:} //只删除最近:之前的
x:0:0:root:/root:/bin/bash
2)从左向右,最长匹配删除
[root@server0 ~]# echo ${x##*:} //删除到:之前所有的
/bin/bash
3)从右向左,最短匹配删除(去尾)
[root@server0 ~]# echo ${x%:*}
root:x:0:0:root:/root
4)从右向左,最长匹配删除
[root@server0 ~]# echo ${x%%:*}
root
4、字符串初值的处理
通过${var:-word}判断变量是否存在,决定是否给变量赋初始值
若变量var已存在且非Null,则返回 $var 的值;否则返回字串“word”,原变量var的值不受影响。
[root@server0 ~]# echo ${NB:-123} //var值不存在
123
[root@server0 ~]# NB=hehe //var值存在
[root@server0 ~]# echo ${NB:-123} //输出原变量的值
hehe
5、数组
整体赋值的格式为“数组名=(值1 值2 值3 .. ..)”
[root@server0 ~]# x=(11 22 33 44 55 66)
[root@server0 ~]# echo ${x[0]}
也可以直接为单个数组元素赋值,格式为“数组名[下标]=值”
[root@server0 ~]# x[0]=1
[root@server0 ~]# x[1]=2
[root@server0 ~]# x[2]=3
变量名里不能再包含变量(例如x$i)
查看数组内的内容:
[root@server0 ~]# echo ${x[*]}
6、expect预期交互
expect可以为交互式过程(比如FTP、SSH等登录过程)自动输送预先准备的文本或指令,而无需人工干预。触发的依据是预期会出现的特征提示文本。
yum -y install expect
#!/bin/bash
ip=176.19.1.65
expect << EOF (开头结尾保持一致)
spawn ssh root@$ip //spawn对屏幕监控
expect "password" {send "Taren1\n"} //当屏幕出现password发送密码
expect "#" {send "touch /root/a.txt\n"}
expect "#" {send "exit\n"}
EOF
3个问题
1)continue的问题
rm -rf /root/.ssh/known_hosts //删除第一登录输入保存yes的文件
2)timeout (在远程连接之前等待一会)
man expect //
set timeout 30 //需要放在远程命令之前
3)最后一行不执行 (上边脚本的expect "#" {send "exit\n"})
7、正则表达式
(需加双引号)
[]集合查找的是单个字符
* :例如 grep “a*” a.txt //匹配a出现的(a,aa,aaa)
. 匹配任意单个字符,可以取出非空行
.* 代表匹配任意所有 空行,非空行一起取出
a\{2,m\} m可以不写 //匹配a出现2到m次 m无限制
使用 \> 匹配单词右边界
\(\) abcabcjklkjl
grep ‘(abc)\1(jkl)\2’ a.txt
最开始和最后一个字母对调
[root@server0 ~]# sed -r 's/^(.)(.*)(.)$/\3\2\1/' 1.txt
8、扩展正则
(简化基本,扩展新的)
? 前面字符出现0或者1次
+ 前面字符出现1次或多次
() 整体 (abc)+ abc abcabc ...
\b 单词边界,精确过滤
[root@room8pc205 桌面]# grep 'the' 1.txt #无论the在哪都匹配
hello the world
theapple is great
tast atheorang
[root@room8pc205 桌面]# grep '\bthe' 1.txt #只匹配the前没有字符
hello the world
theapple is great
[root@room8pc205 桌面]# grep '\bthe\b' 1.txt
hello the world
扩展正则:简单,兼容性差(并不是)
基本正则:复杂,兼容性强(所有软件都支持)
Shell(第五天)
1、sed (Stream EDitor) 流式编辑器
1)非交互
逐行处理
Vim ——硬盘到内存,一次全部显示
Sed ——一行到内存的显示
2)[root@server0 ~]# sed -n '3p' /etc/passwd #显示第3行
不加-n的时候,会在第三行将第三行重复打印 (-n取消自动打印模式空间)
屏蔽默认输出
-r, --regexp-extended 在脚本中使用扩展正则表达式 -i 直接修改文件内容
p 显示(print)
sed -n '3p;5p' /etc/passwd #显示第3,第5行 多个指令用分隔符
sed -n '3,5p' /etc/passwd #显示第3到第5行
sed -n '3,+5p' /etc/passwd #显示第3行以及其后的5行
sed -n 'p;n' /etc/passwd #输出奇数行,sed自动读行,给n拒绝
sed -n 'n;p' /etc/passwd #输出偶数行
sed -n '$=' /etc/passwd #输出文件的行数 wc -l
sed -n '/834/!p' /etc/passwd #输出不包括843的行
根据正则相结合使用(不知道行号)
[root@server0 ~]# sed -n '/root/p' /etc/passwd #找出/root并显示出来
d 删除(delete)
sed '3,5d' /etc/passwd #删除3到5行
sed ‘/xml/d’ /etc/passwd #删除所有包含xml的行(整行删除)
sed ‘/xml/!d’ /etc/passwd #删除不包含xml的行
s 替换 (substitution)
sed ‘s/old/new/’ #文件每行第一个old替换为new
sed ‘3s/old/new/’ #文件第3行第一个old替换为new
sed ‘s/old/new/g’ #文件所有old替换为new
sed ‘s/old/new/3’ #文件每行第三个old替换为new
sed ‘s/old//g #文件所有old替换为空
sed ‘s/old/&s/g’ #文件所有old替换为olds
sed 's#/bin/bash#/sbin/sh#' #可以使用任何特殊符号作为分隔符必须3个
sed 's/\/bin\/bash/\/sbin\/sh/' #太复杂
i(insert) a(append) c
sed '2i xxx' 1.txt #在第2行的前面插入xxx
sed '2a xxx' 1.txt #在第2行的后面插入xxx
sed '2c xxx' 1.txt #第2行替换为xxx (整行替换)
sed '2i xx\nyy' 1.txt #在第2行的前面插入xx和yy
r w h g
sed '1r /etc/hostname' 1.txt #在第一行后加入/etc/hostname的内容
sed 'w /qq.txt' 1.txt #在根下另存为qq.txt(不用i已经存了)
sed '2H;4G' 1.txt #在第2行复制内容加回车在第4行粘贴第2行内容加回车
sed '2h;4g' 1.txt #在第2行复制内容覆盖第4行为第2行的内容
Shell(第六天)
1、awk 数据过滤软件
逐行处理 (grep只能整行)
可以过滤列
格式: awk [选项] ‘条件{指令}’ 文件
条件可以没有,代表所有
也可以没有指令,打印整行
不能同时没有条件和指令
df | awk '/\/$/{print $4}' #查看以/结尾的第4列的信息 根的磁盘剩余
tailf /var/log/secure #查看远程登录日志
用途:监控脚本:
登录日志
分区剩余容量:df
内存剩余容量:free
CPU负载大于xx: top ,uptime
load average: 0.07, 0.21, 0.21
[1,5,15分钟的平均负载]
2、awk 命令,变量
默认使用空格或者tab作为分割符号
-F 指定分隔符(默认空格或者tab)
awk -F: '{print $1}' /etc/passwd #使用:作为分隔符
awk -F: '{print $1,$3,$7}' /etc/passwd #打印多列
打印变量:
print $0 #整行
print $1 #第一列
print $2 #第二列
print NR #当前行的行号
print NF #当前行的列号
print $NF #打印最后一列
打印常量:(字符串需要加引号)
awk '{print "dachui"}' /etc/passwd #每一行都出来(只有)dachui
awk -F ":" '{print "第"NR"行""第"NF"列"}' /etc/passwd
3、awk处理的时机
awk会逐行处理文本,支持在处理第一行之前做一些准备工作,以及在处理完最后一行之后做一些总结性质的工作。在命令格式上分别体现如下:
行前处理,BEGIN{ } #读取文件之前,执行1次
逐行处理,{ } #读取文件过程中执行,执行n次
行后处理,END{ } #读取文件之后,执行1次
awk -F: 'BEGIN{print "用户名\tUID\t家目录"} {print $1,$3,$6} END{print "总用户 "NR}' /etc/passwd
awk 'BEGIN{x=2;y=3.3;print x*y}' #不加其它选项作为运算使用
awk变量可以不定义,就直接用(默认0)
awk 'BEGIN{x=0} /bash$/{x++} END{print x}' /etc/passwd
awk '/bash$/{x++} END{print x}' /etc/passwd
4、awk处理条件
1)使用正则表达式设置条件
~(模糊)匹配 !~不匹配
awk '/root/' /etc/passwd #对整行匹配
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
awk -F: '$1~/root/' /etc/passwd #匹配第一列是root
root:x:0:0:root:/root:/bin/bash
awk -F: '$7!~/bash$/' /etc/passwd #匹配第7列不是bash结尾的行
2)使用数值/字符串比较设置条件 (字符串需要引号,精确匹配)
== != >= <= > <
awk -F: '$1=="root" /etc/passwd #精确匹配第一列是root的行
3)逻辑测试条件
&&逻辑与
awk -F: '$3>=10 && $3<=20' /etc/passwd
|| 逻辑或
awk -F: '$3==0 || $3==1000' /etc/passwd
4)数学运算
+ - * / % ++ --
seq 200 | awk '$1%7==0 || $1~/7/' #200以内能够整除7并且包含7的
5、awk流程控制
1)if分支结构(双分支、多分支)
找出多少系统用户,多少普通用户
awk -F: '{if ($3>=1000){x++}else{y++}}END{print x,y}' /etc/passwd
找出第一列是M.Tansley并且第六列-1,输出1,6,7列
awk '{if($1=="M.Tansley")$6-=1;print $1,$6,$7}' awk_exe.txt
2)while循环结构
统计词频[文章,日志,文件]
例:统计/etc/passwd中的root出现的次数
[root@svr5 ~]# awk -F [:/] \
'BEGIN{j=0}\
{i=1}{while(i<=NF){if($i~/root/){j++};i++}}\
END{print j}' /etc/passwd
4
awk -F : ‘{i=1;while(i<=NF){if($i~/root/){j++};i++}}
END{print j}’ /etc/passwd
3)break、continue等其他控制语句
6、awk公式
ab -c 100 -n 10000 http://172.25.0.11/ #模拟100个人同时访问网站,点击页面1000次。IP后必须写/
拒绝服务***(DOS***)
例:提取IP地址及访问量
awk '{A[$1]++} #统计第一列的IP
END{for(i in A){print i,A[i]}}' #对每个IP循环得到每个IP的次数
/var/log/httpd/access_log |
awk '$2>=500{print $1}' #找出访问次数大于500的IP
例:写一个进度条脚本
#!/bin/bash
jindu(){
while :
do
echo -n '#'
sleep 0.3
done
}
jindu &
cp -r $1 $2
kill $!