熟悉基本shell操做不只是运维的基本功,对于开发来讲也是多多益善,我在学习的过程当中,总结了十个练手的小demo,并附上涉及的知识点,仅供娱乐。html
& 表示任务在后台执行,如要在后台运行redis-server,则有 redis-server &
&& 表示前一条命令执行成功时,才执行后一条命令 ,如 echo '1‘ && echo '2'
| 表示管道,上一条命令的输出,做为下一条命令参数,如 echo 'yes' | wc -l
|| 表示上一条命令执行失败后,才执行下一条命令,如 cat nofile || echo "fail"redis
ping 命令语法shell
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
#!/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 "复制结束"
分析工具:pstree 进程树数组
文件描述符是一个非负整数,而内核须要经过这个文件描述符才能够访问文件。当咱们在系统中打开已有的文件或新建文件时,内核每次都会给特定的进程返回一个文件描述符,当进程须要对文件进行读或写操做时,都要依赖这个文件描述符进行。文件描述符就像一本书的目录页数(也叫索引),经过这个索引能够找到须要的内容。在 Linux 或类 UNIX系统中内核默认会为每一个进程建立三个标准的文件描述符,分别是 0(标准输入)、 1(标准输出)和 2(标准错误)。经过查看/proc/PID 号/fd/目录下的文件,就能够查看每一个进程拥有的全部文件描述符。bash
建立文件描述符:网络
exec 文件描述符 <> 文件名
调用文件描述符语法格式:多线程
&文件描述符
关闭文件描述符:并发
exec 文件描述符<&- exec 文件描述符>&-
管道是进程间通讯的一种方式,匿名管道,使用|符号就能够建立一个匿名管道,顾名思义,系统会自动建立一个能够读写数据的管道,可是这个管道并无名称。一个程序往管道中写数据,另外一个程序就能够从管道中读取数据。可是匿名管道仅能够实现父进程与子进程之间的数据交换,能不能实现任意两个无关的进程之间的通讯呢?答案是确定的,使用命名管道,也叫FIFO1文件。运维
命名管道的特征:curl
第一个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
下载思路:用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
这种知识最基本的爬虫,对于反爬虫的网站就嗝屁了,对于那种异步加载的也没办法,总之,就是比较弱。
作一个互联网大佬的随机点名器
#!/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 #恢复终端属性
[-F|-f|-v] 大参数,-F指定分隔符,-f调用脚本,-v定义变量 var=value
#!/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 "------------------------------------------------------"
参考