真心不想用Bash做这事。
获得HTTP状态
这么简单的功能,还是比新开一个curl要慢。
function get_http_status() {
# 去掉http://
local url=${1#http://}
# 获得端口
local port=80
if [[ $url =~ :([0-9]+) ]]; then
port=${BASH_REMATCH[1]}
fi
# 获得主机
if [[ $url =~ ([^:/]*) ]]; then
host=${BASH_REMATCH[1]}
fi
# 获得路径
local query=${url#*/}
if [[ $host = $query || $host:$port = $query ]]; then
query=""
fi
# 连接
exec 3<>/dev/tcp/$host/$port
#发HEAD请求
echo -e "HEAD /$query HTTP/1.1\r\nConnection: close\r\n\r\n" >&3
# 读状态
read status <&3
echo $1:${status:9:3}
}
顺便练了练正则表达式,好麻烦。
coproc多进程
只是把文件分割然后用多个进程处理,最后合并。
# 处理一个文件
loop_file() {
local input_file=$1
local output_file=$2
mapfile urls < $input_file
for url in ${urls[@]} ; do
get_http_status $url >> $output_file
done
}
# 用coproc在子shell异步处理各个文件
for f in input_file*; do
# 因为coproc不把第一个参数做变量展开,只好用eval展开,再传给coproc
eval "coproc $f { loop_file $f output-$f; }"
done
# 用wait等待全部的子shell完成
for f in $input_file*; do
pid=$f_PID
wait ${!pid}
done
# 合并结果,删除中间文件
for f in $ input_file* ; do
cat output-$f >> output.txt && rm output-$f
done
考虑过用管道实现生产者/消费者模式,实在太复杂,最后换成文件分割。