01 | Linux系统和Shell环境准备
运行shell
test.sh
#!/bin/bash
echo "hello"
运行脚本
方式一:
chmod+x ./test.sh
./test.sh
方式二:
/bin/sh test.sh 若以此方式运行,test.sh(shell脚本)中的 #!/bin/bash则不起作用
02 | Linux常用命令(文件/网络/性能)
文件
常用命令
ls | cd | pwd | mkdir | rmdir | cp | rm | mv-
文件属性
修改文件属性
- 字母模式
chmod a+rwx file # 所有人 赋予 file1 读、写、执行 的权限
chmod a-rwx file # 所有人 取消 file1 读、写、执行 的权限
chmod u+r file # 只给 file1的拥有者 赋予 读 的权限
chmod g-w file # 只取消 同组人 写 的权限
chmod o+x file # 只给 其他人 赋予 file1 执行 的权限
chmod ug+x,o-w file # 给文件拥有者和同组人赋予执行权限,取消其他人的写权限
- 数字模式
chmod 777 file 等价于 chmod a+rwx file1 -rwxrwxrwx
chmod 765 file 等价于 chmod u+rwx,g+rw,o+rx file1 -rwxrw-r-x
chmod 432 file 等价于 chmod u+r,g+wx,o+w -r---wx-w-
网络
ping
1.-c ping的次数
2.-l 每次ping的时间间隔netstat 打印Linux网络系统的状态信息
1.-t 列出所有tcp
2.-u 列出所有udp
3.-l 只显示监听端口
4.-n 拒绝显示别名,能显示数字的全部转化成数字(重要)
5.-p 显示进程的pid和名字练习
netstat -apn | grep ssh 查看指定程序的端口
netstat -apn | grep ":80" 查看运行在指定端口的进程
性能
- top 持续监视系统性能
- ps 查看进程信息
1.-aux 显示所有进程,包括用户、分组情况
03 | Linux三剑客与管道使用
- 管道“|”:左边的输出作为右边的输入
正则表达式
举例
1.\bword\b 找出所有的word单词,word前后要有空格
2.\bword\b.*\bluck\b 第1个单词是word,最后1个单词是luck,中间为任意内容
3.0\d{2}-\d{8} 以0开头+两个数字+“-”+8个数字常用的元字符
符号 | 说明 |
---|---|
. | 匹配换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\s | 匹配任意的空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配行首 |
$ | 匹配行尾 |
- 常用的限定符
符号 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复1次或更多次 |
? | 重复零次或1次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次,重复上限或下限 |
{n,m} | 重复n到m次 |
- 实例
1.匹配以字母a开头的单词:\ba\w*\b
2.匹配刚好6个字符的单词:\b\w{6}\b
3.匹配1个或更多连续的数字:\d+
4.5到12位QQ号:\d{5,12}
grep
grep [options] pattern [file...]
pattern 可以是正则表达式
- 参数
1.-v 显示不被pattern匹配到的行
2.-i 忽略字符大小写
3.-n 显示行号
4.-c 统计匹配的行数
5.-o 仅显示匹配到的字符串
6.-E 使用ERE,相当于egrep
sed
流处理器,一次处理一行内容
若sed后不加任何参数,则只操作模式空间的内容,不操作原文件;若想修改原文件,需加参数-i
-
处理流程
格式
sed [-hn..][-e<script>][-f<script FILE>][FILE]命令解析
1.-h 显示帮助
2.-n 静默模式,仅显示script处理后的结果
3.-e<script> 以选项中指定的script来处理输入的文本文件
4.-f<script文件> 以选项中指定的script文件来处理输入的文本文件常用命令
1.a:新增; sed -e '4a newline' ;在第4行后新增1行,内容为“newline”
2.c:取代;sed -e '2,5c number';用“number”取代2到5行的内容
3.d:删除;sed -e '2,5d';删除2到5行
4.i:插入;sed -e '2i newline';在第2行前插入1行,内容为“newline”
5.p:打印;sed -n '/root/p';打印与root匹配的行
6.s:取代;sed -e 's/old/new/g';全局替换,若没有g则只替换每行的第一个
注:-e可省略练习
sed -i '$a abc\ndef\nghi' file 在文件末尾插入
sed -i '1i abc\ndef\nghi' file 在文件开头插入
-sed和grep的区别
1.grep只能查询
2.sed能够增删改查
awk
把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行后续处理
-
处理流程
格式
awk 'pattern + action' [FILE]常用参数
1.BEGIN 处理文本之前要执行的操作
2.END 处理文本之后要执行的操作
3.FS(field separator) 输入字段分隔符,默认空格,相当于-F
4.NF(number fields) 当前输入记录的字段数(列数)
5.NR(number records) 目前为止看到的记录总数(行数)
6.OFS 输出域分隔符(不常用)
7.ORS 输出记录分隔符(不常用)
8.RS(record separator) 输入记录分隔符,默认换行符
9.$0
整条记录
10.$1
表示当前行的第一个字段练习1
1.搜索/etc/passwd有root关键字的所有行:awk -F: '/root/{print $0}' /etc/passwd
2.打印/etc/passwd的第2行信息:awk -F: 'NR==2{print $0}' /etc/passwd
练习2
1.使用begin加入标题:awk -F: 'BEGIN {print "BEGIN,BEGIN"}{print $1,$2}' /etc/passwd
2.自定义分割符:echo "123|456|789" | awk 'BEGIN{RS="|"}{print $0}'
04 | Bash编程语法
变量
变量的作用范围只在当前窗口
规则
1.命名只能使用英文字母、数字、下划线,首个字符不能以数字开头
2.中间不能有空格,可以使用下划线
3.不能使用标点符号
4.不能使用bash里的关键字(可用help命令查看保留关键字)定义与使用
your_name="abc"
echo $your_name只读变量(不能修改和删除)
a="123"
readonly a
若想删除只读变量,把窗口关闭即可删除变量(不能删除只读变量)
unset variable_name变量类型
1.字符串:your_name="timothy"
2.拼接字符串:greeting="hello,"$your_name""
3.数组:array_name=(value0 value1 value2 value3)
4.取数组:value=${array_name[n]}
5.单独赋值:array_name[0]=value0
6.获取数组长度:${#array_name[*]}
练习
数组初始化
array=(a b c d e)
echo ${array[0]}
echo ${array[@]} 打印所有元素
echo ${array[*]} 同上
数组单个定义
array[0]=a
array[2]=c
echo ${array[*]}
if
- 格式
if condition
then
command1
command2
...
commandN
fi
注意
1.if [ a==1 ];若判断条件是双等号,可使用单中括号
2.if [[ a>1 ]];若判断条件是大于或小于时,要用双中括号;若想使用单中括号,需用-gt、-lt,如if [ a -gt 1]
3.中括号左右必须有空格,不能写成if[a==1]运算符
符号 | 解释 |
---|---|
-gt | greater than |
-lt | less than |
-ge | greater or equal |
-le | less or equal |
-eq | equal |
-ne | not equal |
- 练习
比较两个变量的大小并输出不同的值
if [ $a -eq $b ];then echo "equal"; elif [ $a -lt $b ];then echo "small";elif [ $a -gt $b ];then echo "big"; fi
for
- 格式
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
- 练习
循环读取文件内容并输出
for i in ${cat test.txt};do echo "$i";done
while
- 定义
while condition
do
command
done
- 例子
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
- 练习
循环读取文件内容并输出
while read line;do echo $line;done<test.txt
05 | Bash脚本编写
read命令
概要
1.read命令是用于从终端或文件中读取输入的内部命令
2.读取整行输入
3.每行末尾的换行符不被读入使用
1.读取标准输入内容并赋值给变量:read var
2.读取多个标准输入内容:read var1 var2 var3
3.不指定标量(默认赋值给REPLY):read练习
read a
123
echo $a
read a b c
123 456 789
echo $a $b $c
read
012
echo $REPLY
脚本参数传递
1.$0
脚本名称
2.$1~$n
获取参数
3.$#
传递到脚本的参数个数
4.$$
脚本运行的当前进程ID号
5.$*
显示所有的参数
6.$?
显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误
- 练习
test.sh
#!/bin/bash
echo "文件名:"$0
echo "入参个数:"$#
echo "所有入参:"$*
echo "第1、2、3个入参:"$1 $2 $3
echo "退出状态:"$?
运行test.sh
chmod u+x test.sh
bash test.sh 1 2 3
基本运算
1.加法 `expr $a + $b`
2.减法 `expr $a - $b`
3.乘法 `expr $a \* $b`
4.除法 `expr $b / $a`
5.取余 `expr $a % $b`
6.赋值 a=$b
7.相等 [ $a == $b ]
8.不相等 [ $a != $b ]
bash与目录命令
创建目录并生成文件
mkdir test
cd test
echo "hello" > test.txt
ls
bash与内存
统计内存使用
for i in `ps aux | awk '{print $6}' | grep -v 'RSS'`
do
echo `expr $i / 1024`
done
06 | Nginx日志分析
shell命令中单引号和双引号的区别:单引号里内容不转义,双引号里的内容会转义,举例说明:
a=123
echo '$a' 输出$a,$a未转换
echo "$a" 输出123,$a转换为变量值
grep只支持基本正则,不支持扩展正则,要使用“|”需用egrep,举例说明:
egrep "ab[c|cc]" test.sh
输出abc abcc
- 出现次数最多的ip个数
awk '{print $1}' nginx.log | sort | uniq -c | sort -nr | head -3
grep -o '^[0-9]*.[0-9]*.[0-9]*.[0-9]*' nginx.log | sort | uniq -c | sort -nr | head -3
- 替换
grep "/topics/" nginx.log | sed 's#/topics/[0-9]*#/topics/number#g'
- 将ip地址横向打印
awk '{print $1}' nginx.log | sed ':1;N;s/\n/|/g;t1'
N 将下一行读取到模式空间
:1 标记
t1 t1前的命令执行成功,就跳转到标记1
反复执行":1"和"t1"之间的命令
07 | Linux性能统计分析
命令说明
命令 | 全称 | 说明 |
---|---|---|
mpstat | Multiprocessor Statistics | 多处理器状态 |
vmstat | virtual memory statistics | 虚拟内存状态 |
iostat | input output statistics | 输入输出状态 |
uptime
15:52:31 up 4 days, 21:33, 1 user, load average: 0.00, 0.01, 0.05
当前时间 总开机时间 当前用户 负载(1分,5分,15分)
负载
特定时间间隔内运行队列中的平均进程数。进程满足以下条件则位于运行队列中:
1.未等待I/O操作的结果
2.未主动进入等待状态(未调用wait)
3.未被停止(等待终止)
一般来说,每个CPU内核当前活动进程数不大于3,则表示系统运行表现良好。若是多核则需要累加,即4核cpu<12
dmesg | tail -20
打印系统日志
vmstat
- 虚拟内存:磁盘的部分空间被当做内存使用
- cache:CPU和内存之间的高速缓冲存储器
- buffer:内存和磁盘之间的缓冲器
- 分页:将磁盘空间转换为虚拟内存的技术
- 字段说明
procs(进程):
1.r:运行队列中进程数量,可判断是否需要增加CPU(长期大于1)
2.b:等待IO的进程数量
memory(内存):
1.swpd:使用虚拟内存大小,此值越大说明物理内存已不够用
2.free:空闲物理内存大小
3.buff:用作缓冲的内存大小
4.cache:用作缓存的内存大小
CPU:
1.us:用户进程执行时间
2.sy:系统进程执行时间
3.id:空闲时间(包括IO等待时间),中央处理器的空闲时间
4.wa:等待IO时间
mpstat
语法
mpstat [-P ] [internal [count]]
1.-P 指定CPU
2.internal:相邻两次采样的间隔时间
3.count:采样次数-
参数
参数 | 说明 |
---|---|
%usr | 用户级(应用程序)执行时发生的CPU利用率百分比 |
%nice | 优先级较高的用户级别执行时发生的CPU利用率百分比 |
%sys | 系统级(内核)执行时发生的CPU利用率百分比 |
%iowait | 系统有未完成的磁盘I / O请求时一个或多个CPU空闲的时间百分比 |
%irq | 一个或多个CPU服务硬件中断所花费的时间百分比 |
%soft | 一个或多个CPU服务软件中断所花费的时间百分比 |
%idle | 一个或多个CPU空闲且系统没有未完成的磁盘I / O请求的时间百分比 |
- 理解iowait
CPU空闲时间处理io请求的占比
CPU可以并行处理io请求
其他命令
- pidstat
- iostat
- free -m
- top
1.%CPU是CPU每个核占比的累加
08 | 三剑客实战抽奖程序脚本
- 抽奖实现1:有空白
#!/bin/bash
rand() {
seeds=`while read line; do echo ${line// /..}; done < wx.txt`
while [[ $count != 1 ]];do
seeds=`for seed in $seeds;do (($RANDOM%2==0)) && echo $seed; done` # seeds只有1个元素时,$RANDOM%==1,此时会输出空白
count=`echo "$seeds" | wc -l`
done
echo $seeds
}
rand
- 抽奖实现2:无空白
#!/bin/bash
rand() {
local count
local seeds
count=0
seeds=`while read line; do echo ${line// /..}; done < wx.txt`
while [[ $count != 1 ]];do
seeds=`for seed in $seeds;do (($RANDOM%2==0)) && echo $seed; done`
count=`echo "$seeds" | wc -l`
done
if [[ $seeds == "" ]];then
rand # 这里用到了递归
fi
if [[ $seeds != "" ]];then
echo $seeds
fi
}
while true;do
rand
sleep 1s
done
- 抽奖实现3:去重
rand() {
local seeds
local count
count=0
seeds=`while read line;do echo ${line// /..}; done<test.txt`
while [[ $count != 1 ]];do
seeds=`for seed in $seeds;do (($RANDOM%2==0)) && echo $seed;done`
count=`echo "$seeds" | wc -l`
done
if [[ $seeds == "" ]];then
rand
fi
if [[ $seeds != "" ]];then
echo $seeds
fi
}
res() {
for i in `eval echo {1..$1}`;do
tmp=`rand`
while [[ `is_repeat $tmp` == 0 ]];do
tmp=`rand`
done
arrs[$i]=$tmp
done
echo ${arrs[@]}
}
is_repeat() {
for arr in ${arrs[@]};do
if [[ $arr == $1 ]];then
#此处需要有echo,因为子进程只能捕获echo的输出,不能捕获return的值
echo 0
return 0
fi
done
#输出1的逻辑在这里,因为需要遍历完整的数组后,才能输出1
echo 1
}
res $1
其他
1.echo $var
把所有行合并成1行输出
2.echo "$var"
按原格式输出设置vim编辑器一直显示行号
vim ~/.vimrc
set nu