shell下定时监测程序的死锁

这几天在处理微博爬虫。由于各种原因,爬虫经常为会出现网络错误断开连接,有时莫名其妙的程序锁死(程序在运行,但其实没有任何输出结果显示在运行)。因此就产生了一个定时检查所运行脚本的脚本,或者就在脚本中定时检查。但又不能将检测程序放入cron中,因为程序kill掉后还要继续向前运行。

处理方法如下:
1. 爬虫脚本将结果输出到某log文件中
2. 若log文件在一定时间内未发生变化,而且爬虫脚本还在运行,那可以认定此时程序锁死。
3. 处理锁死程序,直接kill掉,然后继续时间循环。

脚本运用了pgrep(获取某运行程序的pid)、pkill(杀死某程序)。

#!/bin/bash

#only works in Linux shell
startdate='2016-07-03'
for i in {0..7};do
echo "Running time:"`date`
tododate=`date -d "${startdate} $i days" +%Y-%m-%d`
logfile="weibo-${tododate}.log"
python -u weibo-num.py $tododate >$logfile 2>&1 &
while sleep 120;do
cmd=`pgrep -f "weibo-num.py ${tododate}"`
delta=$((`date +%s`-`date -r $logfile +%s`))
if [ ! -z $cmd ] && [ $delta -ge 900 ];then
pkill -f "weibo-num.py ${tododate}"
break
elif [ -z $cmd ]; then
break
fi
done
done

数据巧处理:重复数据的合并处理

要处理一批数据,形式为:
lat,lon,num
每个文件有一个timestamp,文件数量巨大,开始我感觉lat、lat应该唯一,但后来检查数据后发现,这批数据存在大量重复的点(可能之前高精度数据是唯一的,但精度降低后导致有重复数据出现),因此需要专门处理。
开始是想在bash里直接处理,但点位相同的数据,其后的num感觉应该sum后替换,因此还没有想到较好的方法。
后来一想数据不是要入库么,入库后先放松唯一性检查,然后通过group操作,可以简单获取到对应的结果。
SQL:
create table sum_point as
select ts,lat,lon,sum(num) from point group by ts,lat,lon

linux shell下处理web log

现在要将服务器的web log经过分析后将对应的分析结果保存到数据库里,因此需要在服务器后台自动运行,采用shell脚本进行处理,处理过程中遇到两个问题,将解决方法记录如下。

1. 合并昨日对应网站的web log

三个网站(中文版、英文版、专题版)的log记录要合并,而且现在为了保存更多的log,是将每个log按照日期的方式进行命令的,即:

website-access-20141225.log

但也有可能是.log.1的形式(之前是两个形式并存)。
因此需要在shell中获取昨日日期然后进行合并。在shell获取日期可以使用date命令,搜索后发现获取昨日日期的命令如下;

date –date=”yesterday” +%Y%m%d

或者:

date –date=”1 day ago” +%Y%m%d

然后就可以使用mergelog命令将所有的log合并。

2. 运行psql命令
需要使用管理员账号对数据库变更(用到copy命令),因此需要使用su切换到postgres账号并运行对应的sql。发现这个解决方法也比较简单:

su -c “psql db_name -f log.sql” postgres

其中-c就是运行指定的命令。

linux shell的代码执行问题

之前通过incron触发执行的一个wsn文件生成代码,据用户反馈,有很多情况下文件并未生成,因此思考是不是之前的触发脚本是不是存在不能的问题,因此就考虑重新修改代码。

之前的代码如下:

#!/bin/sh
cp /www/wsndata.sh /root/wsndata.sh
chmod +x /root/wsndata.sh
/root/wsndata.sh

怀疑就是执行/root/wsndata.sh未能并行执行多个实例,因此考虑引入临时变量。

#!/bin/bash
tmp=$RANDOM
cp /var/www/ftp2.westgis.ac.cn/wsndata.sh /root/wsndata-${tmp}.sh
chmod +x /root/wsndata-${tmp}.sh
/root/wsndata-${tmp}.sh &

后来发现第一行的sh和bash还有影响。

用shell脚本导入landuse数据到postgis

全国的土地利用数据,80年代末,1995和2000年3期数据,ARCINFO COVERAGE格式,打算直接转入POSTGIS库中。
写了一个shell文件,花费了2天时间。主要是shell的东西是边看边写的,特别是变量处理,还真是麻烦。
运行shell文件要先进入到landuse目录,postgis里应该已经有westdc库,并且已经
进行了POSTGIS初始化,导入过landuse表,并且已经增加了areacode和year字段,不能为NULL,且默认为空值。
从avcbin格式到postgis库,因为数据表的关系,作了两次转换。提出了ARCINFO中的cov#和cov-id字段。

#!/bin/sh
# cd /opt/to_reback/data/landuse
tmpdata=./tmpdata
YEAR=”80年代末 1995年 2000年”
for a in $YEAR; do
for b in $a/*; do #province, 目录判断
if [ -d $b ]; then
rm -fdr $tmpdata
for c in $b/ld*; do # areacode, 县级区域
bb=`echo $b | sed “s/\///g”` # 去除/特殊字符,否则sed罢工
areacode=`echo $c | sed “s/\///g” | sed “s/$bb//g” | sed “s/ld//g”` #主要时间都花费在这儿了
ogr2ogr $tmpdata $c
ogr2ogr $tmpdata/poly.shp $tmpdata/PAL.shp -select area,perimeter,r_area,ln71,ln72,ln73,ln74,aftln,tm20,tm30,tm40,tm50,tm60,afttm,ph41,ph52,ph53,net
shp2pgsql -a -g the_geom -i $tmpdata/poly.shp landuse | psql -d westdc
psql -d westdc -c “update landuse set areacode=’$areacode’ where areacode=””
psql -d westdc -c “update landuse set year=’$a’ where year=””
# exit
done
fi
done
done

bash中&&和||

一直没有搞清楚在bash中这两个符号的意义。最近在学习BASH编程一书才有所了解。

使用& &的一般形式为:
命令1 && 命令2
这种命令执行方式相当地直接。& &左边的命令(命令1)返回真(即返回0,成功被执行)
后,& &右边的命令(命令2)才能够被执行;换句话说,“如果这个命令执行成功& &那么执
行这个命令”

使用| |的一般形式为:
命令1 || 命令2
| |的作用有一些不同。如果| |左边的命令(命令1)未执行成功,那么就执行| |右边的命令
(命令2);或者换句话说,“如果这个命令执行失败了|| 那么就执行这个命令”。