批量ping IP
要点:
1. 定义trap 捕捉INT信号,以便退出。
2. 生成序列的方式可以使用{} , 也可以使用seq 2 254
seq -w 还可以等位补齐,很好用
3.ping
-c 参数代表次数。不会像windows一样ping四次后停止,次数由用户指定.
-W 代表timeout,1表示的是超过三秒钟就定义为ping不通
4.ping -c1 -W1 $ip &>/dev/null 将ping的STDOUT个STDERR 输出到黑洞文件.
5. echo "$ip" | tee -a ip.txt 代表 输出控制台的同时也追加写到ip.txt
#!/bin/bash #批量 ping ip 是否可以ping 通 ping 同网段的ip # 2022年1月2日15:51:02 trap "echo trapped!;exit 1" SIGINT SIGTERM SIGQUIT SIGHUP > ip.txt for i in {2..254};do ip=8.142.104.$i ping -c1 -W1 $ip &>/dev/null if [ $? -eq 0 ];then echo "$ip" | tee -a ip.txt #sleep 1s fi done
ping操作比较省时间,如果是个复杂的事情,在一个bash进程中处理太慢了
如何使用多进程处理呢?
脚本稍加改造:
多进程很好实现,将for循环体用{} &放入后台执行即可。
#!/bin/bash #批量 ping ip 是否可以ping 通 ping 同网段的ip # 2022年1月2日15:51:02 trap "echo trapped!;exit 1" SIGINT SIGTERM SIGQUIT SIGHUP > ip.txt for i in {2..254};do { ip=8.142.104.$i ping -c1 -w1 $ip &>/dev/null if [ $? -eq 0 ];then echo "$ip" | tee -a ip.txt fi } & done echo "finish...."
这个结果好像不太对,finish...怎么先打印出来了呢?
主进程一下子就执行完了,都在等待子进程的执行,如何让主进程等待其他子进程做完之后再执行呢?
使用wait命令
如何限制并发呢?
多进程是实现了,但是没有限制并发,ping一个网段还好一点,如果要ping 100个网段呢?200个网段呢? 如果不限制并发,机器的性能总有被榨干的时候。
借助管道实现并发控制。
实现思路: 使用一个fd 打开管道,往管道中送一些空行(多少个空行就多少个进程)。
在bash中通过此方法模拟co-process(协程) 实现不同进程之间的异步通信。
代码实现
#!/bin/bash #批量 ping ip 是否可以ping 通 ping 同网段的ip # 2022年1月2日15:51:02 count=$1 #创建管道文件 filename=/tmp/$$.fifo # 当前bash的pid mkfifo $filename # 以可读可写方式 用fd8 指向fifo exec 8<> $filename #rm -rf $filename # exec 已经指向了这个fifo, 即使删除,这个管道并不会被删除,除非关闭fd8,管道才会消失 #向管道中注入空行,注入多少个取决于你希望的并发量 echo $count for line in `seq $count`;do echo >&8 done trap "echo trapped!;exit 1" SIGINT SIGTERM SIGQUIT SIGHUP > ip.txt for i in {2..254};do read -u 8 # 在fd8 中读取内容 read from file descriptor FD instead of the standard inpu { ip=8.142.104.$i ping -c1 -w1 $ip &>/dev/null if [ $? -eq 0 ];then echo "$ip" | tee -a ip.txt sleep 1s fi echo >&8 } & done wait exec 8>&- # 释放文件描述符 echo "finish...."
不一定是等三个执行完再执行另外三个,只要管道中能读取到空行就可以执行。可以将参数传2 看的更清楚
思考一个问题: