Shell从入门到精通
熟悉基本shell操作不仅是运维的基本功,对于开发来说也是多多益善,我在学习的过程中,总结了十个练手的小demo,并附上涉及的知识点,仅供娱乐。
1. 多线程ping监控,检查同一网段的IP是否连通
- Linux 系统中有一个特殊的设备/dev/null,这是一个黑洞。无论往该文件中写入多少数据,都会被系统吞噬、丢弃。如果有些输出信息是我们不再需要的, 则可以使用重定向将输出信息导入该设备文件中。注意:数据一旦导入黑洞将无法找回。
- 重定向: > 是覆盖重定向, >> 是累加重定向
- $0 这个程式的执行名字
$n 这个程式的第n个参数值,n=1..9
$* 这个程式的所有参数,此选项参数可超过9个。
$# 这个程式的参数个数
$$ 这个程式的PID(脚本运行的当前进程ID号)
$! 执行上一个背景指令的PID(后台运行的最后一个进程的进程ID号)
$? 执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误)
$- 显示shell使用的当前选项,与set命令功能相同
$@ 跟$*类似,但是可以当作数组用 & 表示任务在后台执行,如要在后台运行redis-server,则有 redis-server &
&& 表示前一条命令执行成功时,才执行后一条命令 ,如 echo '1‘ && echo '2'
| 表示管道,上一条命令的输出,作为下一条命令参数,如 echo 'yes' | wc -l
|| 表示上一条命令执行失败后,才执行下一条命令,如 cat nofile || echo "fail"ping 命令语法
ping [-dfnqrRv][-c<完成次数>][-i<间隔秒数>][-I<网络界面>][-l<前置载入>][-p<范本样式>][-s<数据包大小>][-t<存活数值>][主机名称或IP地址]
#!/bin/bash
#使用&开启后台进程
net="101.200.35"
mult_ping() {
ping -c2 -i0.2 -W1 $1 &>/dev/null
if [ $? -eq 0 ];then
echo "$1 is up"
else
echo "$1 is down"
fi
}
for i in {0..255}
do
mult_ping $net.$i &
done
wait
2.进度条功能显示
- 常见系统预设变量
#!/bin/bash
trap 'kill $!' INT
# 定义宽度为50的进度条
# 输出完成后将/r光标切换到行首,准备下一次进度条显示
bar () {
while :
pound=""
for ((i = 47; i>=1; i-- ))
do
pound += #
printf "|%s%${i}s|\r" "$pound"
sleep 0.2
done
}
# 调用函数,显示进度符号,直到复制结束kill进度函数
bar &
cp -r $1 $2
kill $!
echo "复制结束"
3. Linux创建进程的三种方式
- fork
通常情况下在系统中通过相对路径或绝对路径执行一个命令时,都会由父进程开启一个子进程,当子进程结束后再返回父进程,这种行为过程就叫作fork。当脚本中正常调用一个外部命令 1或其他脚本时,都会fork一个子Shell进程,我们的命令会运行在这个子Shell中。 - exec
使用 exec 方式调用其他命令或脚本时,系统不会开启子进程,而是使用新的程序替换当前的 Shell 环境,因为当前 Shell 环境被替换了,所以当 exec 调用的程序结束后,当前环境会被关闭。但是有一个特例,当 exec 后面的参数是文件重定向时,不会替换当前 Shell 环境,脚本后续的其他命令也不会受到任何影响。 - source或 . (点)
使用 source 命令或.(点)可以不开启子 Shell,而在当前 Shell 环境中将需要执行的命令加载进来,执行完加载的命令后,继续执行脚本中后续的指令。
分析工具:pstree 进程树
4. 控制进程数量——文件描述符和命名管道
文件描述符
文件描述符是一个非负整数,而内核需要通过这个文件描述符才可以访问文件。当我们在系统中打开已有的文件或新建文件时,内核每次都会给特定的进程返回一个文件描述符,当进程需要对文件进行读或写操作时,都要依赖这个文件描述符进行。文件描述符就像一本书的目录页数(也叫索引),通过这个索引可以找到需要的内容。在 Linux 或类 UNIX系统中内核默认会为每个进程创建三个标准的文件描述符,分别是 0(标准输入)、 1(标准输出)和 2(标准错误)。通过查看/proc/PID 号/fd/目录下的文件,就可以查看每个进程拥有的所有文件描述符。
创建文件描述符:
exec 文件描述符 <> 文件名
调用文件描述符语法格式:
&文件描述符
关闭文件描述符:
exec 文件描述符<&-
exec 文件描述符>&-
命名管道
管道是进程间通信的一种方式,匿名管道,使用|符号就可以创建一个匿名管道,顾名思义,系统会自动创建一个可以读写数据的管道,但是这个管道并没有名称。一个程序往管道中写数据,另一个程序就可以从管道中读取数据。但是匿名管道仅可以实现父进程与子进程之间的数据交换,能不能实现任意两个无关的进程之间的通信呢?答案是肯定的,使用命名管道,也叫FIFO1文件。
命名管道的特征:
- FIFO 文件由命令创建(mknod 或 mkfifo 命令),可以在文件系统中直接看到。
- 写入管道的数据一旦被读取后,就不可以再重复读取。
- 进程往命名管道中写数据时,如果没有其他进程读取数据,则写进程会被阻塞。
- 进程尝试从命名管道中读取数据时,如果管道中没有数据,则读进程会被阻塞。
- 命名管道中的数据常驻内存,并不实际写入磁盘,读写效率会更高。
5. 可任意控制进程数量的多线程ping
第一个demo中,通过 & 开启任意数量线程进行ping,但是这里的线程不可控。我们用上面的文件描述符和命名管道的知识,写一段可控的多线程ping。
#!/bin/bash
pipefile=/tmp/procs_$$.temp
num=10
net="101.200.35"
multi_ping() {
ping -c2 -i0.2 -W1 $1 &>/dev/null
if [ $? -eq 0 ];then
echo "$1 is up"
else
echo "$1 is down"
fi
}
# 创建命名管道文件,创建其文件描述符,通过重定向将数据导入管道文件
mkfifo $pipefile
exec 12<>$pipefile
for i in `seq $num`
do
echo "" >&12 &
done
# 成功读取命名管道中的数据后开启新的进程
# 所有内容读取完之后read被阻塞,无法再启动新的进程
# 等待前面启动的线程结束后,继续往管道文件中写入数据,释放阻塞,再次开启新的线程
for j in {1..254}
do
read -u12
{
multi_ping $net.$j
echo "" >&12
} &
done
wait
rm -rf $pipfile
6. sed爬虫批量下载美女图片
- sed命令汇总
- sed 是逐行处理软件,我们可能仅输入了一条 sed 指令,但系统会将该指令应用在所有匹配的数据行上,因此相同的指令会被反复执行 N 次,这取决于匹配到的数据有几行。
- 默认 sed 不支持扩展正则,如果希望使用扩展正则匹配数据,可以使用-r 参数。
- sed 程序使用=指令可以显示行号,结合条件匹配,可以显示特定数据行的行号。
- 在 sed 中支持使用感叹号(!)对匹配的条件进行取反操作。
下载思路:用curl获取网站源代码+sed数据清洗获取图片地址+wget下载保存
#!/bin/bash
# 爬取美女图片
# 定义要爬取的网站和保存的文件
page="https://tieba.baidu.com/p/4420470629"
URL="beau.txt"
# 将网站源代码保存到文件中
curl -s https://tieba.baidu.com/p/4420470629 > $URL
# 对源代码数据过滤清洗,获取种子的URL链接
echo -e "\033[32m 正在获取种子 URL,请稍后...\033[0m"
sed -i '/<img/!d' $URL #删除不包含<img 的行
sed -i 's/.*src="//' $URL #删除 src="及其前面的所有内容
sed -i 's/".*//' $URL #删除双引号及其后面的所有内容
echo
#利用循环批量下载所有图片数据
#wget 为下载工具,其参数选项描述如下:
# -P 指定将数据下载到特定目录(prefix)
# -c 支持断点续传(continue)
# -q 不显示下载过程(quiet)
echo -e "\033[32m 正在批量下载种子数据,请稍后...\033[0m"
for i in $(cat $URL)
do
wget -P tempPhoto/ -c $i
done
这种知识最基本的爬虫,对于反爬虫的网站就嗝屁了,对于那种异步加载的也没办法,总之,就是比较弱。
7. sed随机点名器
做一个互联网大佬的随机点名器
#!/bin/bash
#按 Ctrl+C 组合键时:恢复光标,恢复终端属性,清屏,退出脚本
#防止程序意外中断导致的终端混乱
trap 'tput cnorm;stty $save_property;clear;exit' 2
#定义变量:人员列表文件名,文件的行数,屏幕的行数,屏幕的列数
name_file="name.txt"
line_file=$(sed -n '$=' $name_file)
line_screen=`tput lines`
column_screen=`tput cols`
#设置终端属性
save_property=$(stty -g) #保存当前终端所有属性
tput civis #关闭光标
#随机抽取一个人名(随机点名)
while :
do
tmp=$(sed -n "$[RANDOM%line_file+1]p" $name_file)
#随机获取文件的某一行人名
tput clear #清屏
tput cup $[line_screen/4] $[column_screen/4]
echo -e "\033[3;5H 随机点名器(按 P 停止): "
echo -e "\033[4;5H#############################"
echo -e "\033[5;5H# #"
echo -e "\033[6;5H#\t\t$tmp\t\t#"
echo -e "\033[7;5H# #"
echo -e "\033[8;5H#############################"
sleep 0.1
stty -echo
read -n1 -t0.1 input
if [[ $input == "p" || $input == "P" ]];then
break
fi
done
tput cnorm #恢复光标
stty $save_property #恢复终端属性
8.系统性能监控脚本
- awk语法格式
- awk变量
- awk条件匹配
- awk 可以通过-v(variable) 选项设置或者修改变量的值,我们可以使用-v 定义新的变量,也可以使用该选项修改内置变量的值。
- 使用[]定义分隔符集合,同时设置多个分隔符。比如使用[:,-]表示以冒号(:)、逗号(,)或者横线(-)为分隔符
[-F|-f|-v] 大参数,-F指定分隔符,-f调用脚本,-v定义变量 var=value
9.监控网络连接状态
- ss语法格式
#!/bin/bash
# 监控网络连接状态
#所有 TCP 连接的个数
TCP_Total=$(ss -s | awk '$1=="TCP"{print $2}')
#所有 UDP 连接的个数
UDP_Total=$(ss -s | awk '$1=="UDP"{print $2}')
#所有 UNIX sockets 连接个数
Unix_sockets_Total=$(ss -ax | awk 'BEGIN{count=0} {count++} END{print
count}')
#所有处于 Listen 监听状态的 TCP 端口个数
TCP_Listen_Total=$(ss -antlpH | awk 'BEGIN{count=0} {count++} END{print
count}')
#所有处于 ESTABLISHED 状态的 TCP 连接个数
TCP_Estab_Total=$(ss -antpH | awk 'BEGIN{count=0} /^ESTAB/{count++}
END{print count}')
#所有处于 SYN-RECV 状态的 TCP 连接个数
TCP_SYN_RECV_Total=$(ss -antpH | awk 'BEGIN{count=0} /^SYN-RECV/{count++}
END{print count}')
#所有处于 TIME-WAIT 状态的 TCP 连接个数
TCP_TIME_WAIT_Total=$(ss -antpH | awk 'BEGIN{count=0} /^TIME-WAIT/{count++}
END{print count}')
#所有处于 TIME-WAIT1 状态的 TCP 连接个数
TCP_TIME_WAIT1_Total=$(ss -antpH | awk 'BEGIN{count=0}
/^TIME-WAIT1/{count++} END{print count}')
#所有处于 TIME-WAIT2 状态的 TCP 连接个数
TCP_TIME_WAIT2_Total=$(ss -antpH | awk 'BEGIN{count=0}
/^TIME-WAIT2/{count++} END{print count}')
#所有远程主机的 TCP 连接次数
TCP_Remote_Count=$(ss -antH | awk '$1!~/LISTEN/{IP[$5]++} END{ for(i in
IP){print IP[i],i} }' | sort -nr)
#每个端口被访问的次数
TCP_Port_Count=$(ss -antH | sed -r 's/ +/ /g' | awk -F"[ :]"
'$1!~/LISTEN/{port[$5]++} END{for(i in port){print port[i],i}}' | sort -nr)
#定义输出颜色
SUCCESS="echo -en \\033[1;32m" #绿色
NORMAL="echo -en \\033[0;39m" #黑色
#显示 TCP 连接总数
tcp_total(){
echo -n "TCP 连接总数: "
$SUCCESS
echo "$TCP_Total"
$NORMAL
}
#显示处于 LISTEN 状态的 TCP 端口个数
tcp_listen(){
echo -n "处于 LISTEN 状态的 TCP 端口个数: "
$SUCCESS
echo "$TCP_Listen_Total"
$NORMAL
}
#显示处于 ESTABLISHED 状态的 TCP 连接个数
tcp_estab(){
echo -n "处于 ESTAB 状态的 TCP 连接个数: "
$SUCCESS
echo "$TCP_Estab_Total"
$NORMAL
}
#显示处于 SYN-RECV 状态的 TCP 连接个数
tcp_syn_recv(){
echo -n "处于 SYN-RECV 状态的 TCP 连接个数: "
$SUCCESS
echo "$TCP_SYN_RECV_Total"
$NORMAL
}
#显示处于 TIME-WAIT 状态的 TCP 连接个数
tcp_time_wait(){
echo -n "处于 TIME-WAIT1 状态的 TCP 连接个数: "
$SUCCESS
echo "$TCP_TIME_WAIT1_Total"
$NORMAL
}
#显示处于 TIME-WAIT2 状态的 TCP 连接个数
tcp_time_wait2(){
echo -n "处于 TIME-WAIT2 状态的 TCP 连接个数: "
$SUCCESS
echo "$TCP_TIME_WAIT2_Total"
$NORMAL
}
#显示 UDP 连接总数
udp_total(){
echo -n "UDP 连接总数: "
$SUCCESS
echo "$UDP_Total"
$NORMAL
}
#显示 UNIX sockets 连接总数
unix_total(){
echo -n "Unix sockets 连接总数: "
$SUCCESS
echo "$Unix_sockets_Total"
$NORMAL
}
#显示每个远程主机的访问次数
remote_count(){
echo "每个远程主机与本机的并发连接数: "
$SUCCESS
echo "$TCP_Remote_Count"
$NORMAL
}
#显示每个端口的并发连接数
port_count(){
echo "每个端口的并发连接数: "
$SUCCESS
echo "$TCP_Port_Count"
$NORMAL
}
print_info(){
echo -e "------------------------------------------------------"
$1
}
print_info tcp_total
print_info tcp_listen
print_info tcp_estab
print_info tcp_syn_recv
print_info tcp_time_wait
print_info tcp_time_wait1
print_info tcp_time_wait2
print_info udp_total
print_info unix_total
print_info remote_count
print_info port_count
echo -e "------------------------------------------------------"
参考
Shell从入门到精通的更多相关文章
- Shell从入门到精通进阶之四:流程控制
流程控制是改变程序运行顺序的指令. 4.1 if语句 4.1.1 单分支 if 条件表达式; then 命令 fi 示例: #!/bin/bash N=10 if [ $N -gt 5 ]; then ...
- Shell从入门到精通进阶之三:表达式与运算符
3.1 条件表达式 表达式 示例 [ expression ] [ 1 -eq 1 ] ` expression ` ` 1 -eq 1 ` test expression test 1 -eq 1 ...
- shell从入门到精通进阶之一:Shell基础知识
1.1 简介 Shell是一个C语言编写的脚本语言,它是用户与Linux的桥梁,用户输入命令交给Shell处理,Shell将相应的操作传递给内核(Kernel),内核把处理的结果输出给用户. 下面是处 ...
- Shell从入门到精通进阶之二:Shell字符串处理之${}
上一章节讲解了为什么用${}引用变量,${}还有一个重要的功能,就是文本处理,单行文本基本上可以满足你所有需求. 2.1 获取字符串长度 # VAR='hello world!' # echo $VA ...
- shell脚本从入门到精通(中级)之提高篇
shell 脚本入门到精通(中级) 一.shell 脚本的执行 二.输出格式化 三.数据类型 四.重定向 五.变量 一.shell 脚本的执行 1. 脚本执行的4种方法 $ ls /tmp/test. ...
- shell脚本从入门到精通
阿里云大学 shell脚本从入门到精通 第1 章 : shell脚本编程-变量-算术表达式-判断语句-if分支语句 第2 章 : case-for-While-双括号-循环嵌套-break-conti ...
- shell脚本从入门到精通(初级)之入门篇
写在开头 本文是阅读<Linux命令行与shell脚本编程大全>时的一些笔记,主要是shell脚本的一些基本语法, 还有很多细节和高级内容没有写到. 笔者也是shell script菜鸟, ...
- ASP.NET MVC4入门到精通系列目录汇总
序言 最近公司在招.NET程序员,我发现好多来公司面试的.NET程序员居然都没有 ASP.NET MVC项目经验,其中包括一些工作4.5年了,甚至8年10年的,许多人给我的感觉是:工作了4.5年,We ...
- 大数据应用之:MongoDB从入门到精通你不得不知的21个为什么?
一.引言: 互联网的发展和电子商务平台的崛起,催生了大数据时代的来临,作为大数据典型开发框架的MongoDB成为了No-sql数据库的典型代表.MongoDB从入门到精通你不得不知的21个为什么专为大 ...
随机推荐
- Python的精髓居然是方括号、花括号和圆括号!
和其他编程语言相比,什么才是Python独一无二的特色呢?很多程序员会说,缩进.的确,缩进是Python语言的标志性特点,但这只是外在的.形式上的.从语言特性层面讲,Python的特点是什么呢?我尝试 ...
- 面向切面@Aspect
package com.imooc.demo.filter; import org.springframework.core.Ordered; import org.springframework.c ...
- MySQL - 数据查询 - 简单查询
1. 简述 查询数据是指从数据库中获取所需要的数据.如Jack 要达到验证用户名和密码的目的,就需要从数据库已保存的用户表中读取当前用户的密码进行验证,以验明正身!保存查询数据是数据库操作中常用且重要 ...
- MPEG2TS文件格式概述
总结TS文件格式,早在几个月前就有了这个想法,但一直拖到今天才真正准备写一篇博文来介绍. 再不介绍的话,估计几月后又要去故纸堆里翻东西了,毕竟个人笔记中总结记录的东西太多,搞不好哪天给意外弄丢了. 1 ...
- [LeetCode]147. Insertion Sort List链表排序
插入排序的基本思想 把排好的放在一个新的变量中,每次拿出新的,排进去 这个新的变量要有超前节点,因为第一个节点可能会有变动 public ListNode insertionSortList(List ...
- 学习 Gin 总结(2020.12.30-31)
2020.12.30 问题总结 中间件 context.Next() 源码注释: // Next should be used only inside middleware. // It execut ...
- 第十九章节 BJROBOT 安卓手机 APP 导航【ROS全开源阿克曼转向智能网联无人驾驶车】
导航前说明:一定要确保你小车在构建好地图的基础上进行! 1.把小车平放在你想要构建地图区域的地板上,打开资料里的虚拟机,打开一个终端, ssh 过去主控端启动roslaunch znjrobot br ...
- css3 知识点积累
-moz- 兼容火狐浏览器-webkit- 兼容chrome 和safari1.角度 transform:rotate(30dge) 水平线与div 第四象限30度 transform: ...
- BCC和libbpf的转换
BCC和libbpf的转换 本文讲述如何将基于BCC的BPF应用转换为libbpf + BPF CO-RE.BPF CO-RE可以参见上一篇博文. 为什么是libbpf和BPF CO-RE? 历史上, ...
- thinkphp3.2框架运行原理
thinkphp3.2是使用率非常普遍的国产php框架,以简单易于上手闻名,那么它框架结构是怎样的? tp3.2设计简单来说就是CBD,core(框架核心文件),bebavior(行为,tp3.2一大 ...