有统计访问用户地理位置的需求,故通过对用户访问信息中ip地址的处理,来整理出用户ip地址和地理位置
文件格式如下:
1555315829.907 ad170ef2-35bf-11e9-906b-286ed488c99f [2019-04-15T16:10:29+08:00] elb 49.69.197.165:64361
1555315830.429 ad170ef2-35bf-11e9-906b-286ed488c99f [2019-04-15T16:10:30+08:00] elb 14.30.43.217:12104
由于可从ip地址查找出地理位置信息,所以先对ip地址数据进行整理,主要的操作有去重和排序。
#!/bin/bash
path=$1;
gzip -d $path/*;
files=$(ls $path);
source_file="filename";
ans_file="filename";
for filename in $files
do
cat $filename >> $source_file;
done
cat $source_file |awk '{print $5}'|awk -F ':' '{print $1}'|sort -g|uniq > $save_file;
得到整理好的ip地址数据后,就需要查找到它们一一对应的地理位置。
我了解到的有以下几种方法:
(1)whois 命令工具
whois 119.26.15.14
输出信息比较多,我们可以提取自己想要的,如 grep 'country'。
但在实际使用过程中,发现其提供的部分ip地址的地理位置信息不完整,故放弃。
(2) 使用网上提供的接口
https://www.ipip.net/support/api.html
https://ip.sb/api/
...
由于是使用shell,推荐第一个接口,速度快但免费的限制次数为1000
temp=$(curl cip.cc/$ip|grep '地址'|awk '{print $3,$4}');
生成文件格式如下
为更好的查看地理位置,再使用一次sort排序整理
sort -k 2 oversea_ip_addr.txt > oversea.txt;
在实际运行脚本的过程中,发现接口返回的速度实在太慢,12000+ip实际运行了6,7个小时(ps 百兆宽带,肯定不是网速的问题)。基于目前水平,深层的原因暂时没有找到,故为了提高速度,使用shell多进程。
在shell脚本里面,直接使用 & 即可让程序在后台运行,实现方式较为简单。
唯一要注意的是,由于是多进程同时写同一个文件,有可能会出现不同进程同时写入导致乱序或者其他意外情况,所以在这里,我们要使用文件锁,shell脚本对应的命令为 flock 。详细使用方法可以使用man 来查询
(
flock -n 9 || exit 1
# ... commands executed under lock ...
) 9>/var/lock/mylockfile
The form is convenient inside shell scripts. The mode used to open the file
doesn't matter to flock; using > or >> allows the lockfile to be created if it does
not already exist, however, write permission is required. Using < requires that
the file already exists but only read permission is required.
在这里()后面的内容是先与()里面的内容执行的,“9>/var/lock/mylockfile” 代表的是 文件描述符 与 mylockfile文件写关联,若mylockfile不存在则新建。()里面的数字9即代表文件描述符。
编写完成多进程执行脚本的时候,开启10个进程理论上来说速度应该能达到原来的10倍,实际上只有2倍左右,具体原因待查找。
batch=$1;
process=$2;
path="/mnt/hgfs/共享文件夹/";
source_file=$path"ans.txt";
CN_save_file=$path"CN_ip_addr.txt";
HK_MO_TW_save_file=$path"HK_MO_TW_ip_addr.txt";
oversea_save_file=$path"oversea_ip_addr.txt";
CNlock="/tmp/cn.lock";
HMTlock="/tmp/hmt.lock";
oslock="/tmp/os.lock";
line=$(wc -l $source_file|awk '{print $1}');
startline=$((1+(batch-1)*line/process));
if [ "$batch" == "$process" ];then
endline=$line;
else
endline=$((batch*line/process));
fi
ip_total=$(sed -n ${startline},${endline}p $source_file);
for ip in $ip_total
do
temp=$(curl --max-time 5 cip.cc/$ip|grep '地址'|awk '{print $3,$4}');
while [ "$temp" == "" ]
do
temp=$(curl --max-time 15 cip.cc/$ip|grep '地址'|awk '{print $3,$4}');
done
country=$(echo $temp|awk '{print $1}');
province=$(echo $temp|awk '{print $2}');
if [ "$country" == "中国" ];then
case $province in
"香港")
(
flock -w 10 101
echo $ip $province >> $HK_MO_TW_save_file
)101<>/tmp/hmt.lock
;;
"台湾")
(
flock -w 10 101
echo $ip $province >> $HK_MO_TW_save_file
)101<>/tmp/hmt.lock
;;
"澳门")
(
flock -w 10 101
echo $ip $province >> $HK_MO_TW_save_file
)101<>/tmp/hmt.lock
;;
*)
(
flock -w 10 100
echo $ip $province >> $CN_save_file
)100<>/tmp/cn.lock
;;
esac
else
(
flock -w 10 102
echo $ip $country >> $oversea_save_file
)102<>/tmp/os.lock
fi
done