404频道

学习笔记

最近公司需要首先登录跳板机relay,然后通过跳板机才能登录服务器,操作上略显麻烦。为了节省登录服务器的时间,我编写了一个简单的脚本来简化登录操作。

实现效果为在本地terminal下,执行wrelay $host,即可自动登录到相应的主机。

在relay服务器上增加对其他服务器的免登录命令

在relay服务器上ssh到其他主机时需要输入密码,使用expect命令来登录到其他主机时通过expect脚本来实现自动输入密码并登录的功能。

在/home/$user目录下新建mybin文件夹,并将mybin文件夹添加到$PATH环境变量中,具体修改方法不展开。

在mybin目录下增加gw脚本,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/expect

if {$argc < 1} {
puts "Usage:cmd <host>"
exit 1
}

set host [lindex $argv 0]
# 在这里填写要登录的用户
set username "worker"
# 在这里填写要登录的密码
set password "worker"

spawn ssh $username@$host
set timeout 2
expect {
"*password:" {
send "$password\n"
}
"Are you sure you want to continue connecting (yes/no)?" {
send "yes\r"
exp_continue
}
}
expect "*#"
interact

执行gw 10.1.1.8,即可登录到对应的主机上。

本地主机免登录relay服务器,并自动登录到对应的服务器

在本地自动登录relay主机同样使用expect的方式,脚本名称为wrelay,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/expect

if {$argc < 1} {
puts "Usage:cmd <remote_host>"
exit 1
}

# 下面指定relay主机
set host "relay.name"
# 这里输入relay的用户名
set username ""
# 这里输入relay的密码
set password ""
set remote_host [lindex $argv 0]

spawn ssh $username@$host
set timeout 2
expect {
"*password:" {
send "$password\n"
}
"Are you sure you want to continue connecting (yes/no)?" {
send "yes\r"
exp_continue
}
}
expect "*#"

sleep 0.1
# 在relay上自动登录到其他服务器主机
send "gw $remote_host\n"
interact

清明节假期突然想起了我好久不更的blog,看到Farbox官网上的《2016,终结了几个产品》,说明Farbox已经停止更新了。虽然我挺喜欢Farbox这个项目,也见证了Farbox的成长及作者做产品的思考,在这里也向作者致敬。

我当时开始准备启用Farbox之前试用过jekyll,翻遍了整个github,也没找到个合我心意的theme。幸好是Farbox的出现,让我眼前一亮,这就是我想好的blog系统了。Farbox的停更使我不得不考虑重新换个blog,虽然2016的文章数量仅为罕见的个位数,但有可能今年有时间会多写一些。

近几年hexo特别的火,在试看了官方文档了解功能及考虑了blog的迁移成本后,心想,这就是我想要的blog系统了。hexo该有的功能全都有,甚至比Farbox要强大很多。Farbox的很多设计思想跟hexo相仿,但hexo显的更加自由,blog需要自己一手搭建完成。

当然hexo要想使用的好,做一些全面的了解及折腾是必不可少的,毕竟最终利用的Github pages是个静态的系统。早已没有了想当年翻遍整个github上jekyll theme的精力了,我这次的基调是能少折腾就少折腾,毕竟blog我也不是经常写,访问量也更是少的可怜,就当全面了解下当前最火的hexo就好了。

theme

本着不折腾原则,直接启用了很火的hexo-theme-next,文档比较全,维护比较及时。基本上按照文档走一遍,该配置的就都可以配置上了。

代码同步

代码通过git同步是必备技能。

hexo项目代码同步

hexo采用的是node.js环境,而Github pages是静态的,因此Github pages上仅能存储的是hexo编译后的静态文件,这些静态文件直接通过hexo d部署到kuring.github.com仓库中就可以了。

而对于项目中的_config.yml、md文件我直接用git同步到Github上另外一个项目hexo_bak中了。网上还有思路是同步到kuring.github.com上的另外一个分支,我感觉太啰嗦,容易出错,还不如直接分开来的简便。

theme项目的代码同步

theme项目中也包含了部分自己的配置及修改,我这里选择的同步策略为从github上fork对应的theme项目,然后clone fork下来的项目到本地,然后直接在theme的项目中通过git命令同步到github fork的项目中。

网上也有思路是通过git subtree的方式来解决,我仍然感觉太啰嗦,不采用。

但这样一个blog项目需要多个git仓库,git push起来会比较麻烦,好在theme一般不怎么修改。

评论系统

之前用多说的时候也没几个评论的,用起来还不错,至少比被墙了的disqus要好很多,可是多说这么好的项目要关闭了。我直接使用了国内的网易云跟帖来满足评论的需求。

站内搜索

站内搜索是必不可少的功能,next主题提供了多种选择,我直接使用了hexo-generator-searchdb通过本地搜索来完成,生成的xml文件目前还比较小,效果还可以。

常用命令

  • 启用本地server端:hexo clean && hexo g && hexo s
  • 部署到github:hexo d
  • 发布文章:hexo new 文章url

使用hexo new draft test会在source/_drafts目录下创建对应文件,此时文件不会生成页面,用于存放未写完的文章。hexo publish draft test命令可将_drafts下的文章移动到_posts目录下,并添加创建时间等信息。

收个尾

blog总算迁移完成了,期望今年能多写上几篇。

目前php-fpm的服务部署在了docker中,对php-fpm的log和php error log可以通过syslog协议的形式发送出去,而php-fpm的slow log却不能配置为syslog协议,只能输出到文件中,因为一条slow log的是有多行组成的。

在docker中使用时发现fpm-slowlog不能正常输出,后经发现是docker默认没有ptrace系统调用的权限,而slow log的产生需要该系统调用。通过在docker启动的时候增加”–cap-add SYS_PTRACE”启动项可修正该问题。

为了收集slow log,可以通过logstash、flume等工具进行收集,本文采用logstash对slow log进行收集,并将收集的log写入到kafka中,便于后续的处理。logstash的input采用读取文件的方式,即跟tail -f的原理类似。为了能够将多行日志作为一行,采用了filter中的multiline来对多行日志进行合并操作。logstash的配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
input {
file {
path => [“/var/log/php-fpm/fpm-slow.log"]
}
}

filter {
multiline {
pattern => "^$"
negate => true
what => "previous"
}
}

output {
stdout{codec => rubydebug}
kafka {
codec => plain {
format => “tag|%{host}%{message}"
}
topic_id => "fpm-slowlog"
bootstrap_servers => “kafka1.hostname:8082,kafka2.hostname:8082"
}
}

ELK解析nginx日志

最近使用ELK搭建了一个nginx的日志解析环境,中间遇到一些挫折,好不容易搭建完毕,有必要记录一下。

nginx

nginx配置文件中的日志配置如下:

1
2
3
4
5
6
error_log /var/log/nginx/error.log;
log_format main '$remote_addr [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

logstash

由于是测试环境,我这里使用logstash读取nginx日志文件的方式来获取nginx的日志,并且仅读取了nginx的access log,对于error log没有关心。

使用的logstash版本为2.2.0,在log stash程序目录下创建conf文件夹,用于存放解析日志的配置文件,并在其中创建文件test.conf,文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
input {
file {
path => ["/var/log/nginx/access.log"]
}
}
filter {
grok {
match => {
"message" => "%{IPORHOST:clientip} \[%{HTTPDATE:time}\] \"%{WORD:verb} %{URIPATHPARAM:request} HTTP/%{NUMBER:httpversion}\" %{NUMBER:http_status_code} %{NUMBER:bytes} \"(?<http_referer>\S+)\" \"(?<http_user_agent>\S+)\" \"(?<http_x_forwarded_for>\S+)\""
}
}
}
output {
elasticsearch {
hosts => ["10.103.17.4:9200"]
index => "logstash-nginx-test-%{+YYYY.MM.dd}"
workers => 1
flush_size => 1
idle_flush_time => 1
template_overwrite => true
}
stdout{codec => rubydebug}
}

需要说明的是,filter字段中的grok部分,由于nginx的日志是格式化的,logstash解析日志的思路为通过正则表达式来匹配日志,并将字段保存到相应的变量中。logstash中使用grok插件来解析日志,grok中message部分为对应的grok语法,并不完全等价于正则表达式的语法,在其中增加了变量信息。

具体grok语法不作过多介绍,可以通过logstash的官方文档中来了解。但grok语法中的变量类型如IPORHOST并未找到具体的文档,只能通过在logstash的安装目录下通过grep -nr "IPORHOST" .来搜索具体的含义。

配置文件中的stdout部分用于打印grok解析结果的信息,在调试阶段一定要打开。

可以通过这里来验证grok表达式的语法是否正确,编写grok表达式的时候可以在这里编写和测试。

对于elasticsearch部分不做过多介绍,网上容易找到资料。

kibana

kibana不做过多介绍,使用可以查看官方文档和自己摸索。

reference

logstash中的grok插件介绍

曾经使用过多种科学上网方式,​最近尝试了使用aws的免费试用一年的功能搭建shadowsocks,访问google的速度非常不错,比很多收费的服务要好用,amazon真是良心企业!

本文用于记录在aws上搭建服务的步骤及其中的一些注意事项,步骤不会太详细,aws上关于主机的功能需要读者自己在试验的过程中去自己探索。

注册aws账号

为了能够搭建搭建aws服务,拥有一个amazon账号是必须的,在aws免费套餐的页面点击『创建免费账号』按钮即可按照步骤创建aws账号。

值得一提的是,注册aws的账号需要一张信用卡。

开启EC2主机实例

该步骤的目的是开启aws上的主机实例。​

进入aws的控制面板,在左上角的服务中选择EC2,aws提供了多种类型的主机,这里选择EC2即可。

在EC2控制面板界面中需要选择右上角的区域,这个用于选择EC2主机所在的机房,不同机房之间主机是不可以共享的。我这里选择了『美国西部(俄勒冈)』,感觉速度还不错,没有试验过亚洲地区的,新加坡的速度是不是会更好些。后续经过验证,首尔的服务器确实速度更快一些。

下面即可创建EC2的实例了,点击界面上的『启动实例』按钮即可按照步骤创建EC2实例了,创建实例的时候一定要选择免费的EC2主机,否则就会悲剧了。我选择了ubuntu14.04的主机,redhat7.2的主机yum源不太全,没有选择使用。

最终会得到ssh登录用的pem文件,用于ssh远程登录主机。并在界面上启动刚刚创建的实例。

按照shadowsocks

接下来就是在EC2实例上安装sock5代理工具了。

登录刚刚启动的EC2,需要pem文件。可以通过ssh -i "key.pem" ubuntu@ec2-52-26-2-14.us-west-2.compute.amazonaws.com命令来登录到远程主机,其他工具请自行google。

使用命令pip install shadowsocks来安装shadowssocks,pip命令的安装自行解决。

在ubuntu的home目录下执行mkdir shadowsocks创建保存配置文件的文件夹,并创建配置文件config.json,内容如下:

1
2
3
4
5
6
7
8
{
"server":"0.0.0.0",
"server_port":10001,
"local_port":1080,
"password":"xxx",
"timeout":600,
"method":"bf-cfb"
}

需要说明的是最好配置一下server_port选项,更改shadowsocks的默认端口号。method选项用于控制加密方式,我这里更改为了bf-cfb。

执行nohup ssserver -c config.json &命令即可启动shadowsocks服务。

由于对外增加了10001端口号,aws的默认安全策略为仅对外提供22端口,需要在EC2主机的安全策略中增加外放访问tcp端口10001的权限。

脚本

为了安装方便,我简单写了个脚本如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
yum -y install epel-release
#yum update -y
yum install python2-pip -y
pip install shadowsocks
mkdir ~/shadowsocks
echo '{
"server":"0.0.0.0",
"server_port":10001,
"local_port":1080,
"password":"xxx",
"timeout":600,
"method":"aes-256-cfb"
}' > ~/shadowsocks/config.json
systemctl disable firewalld.service
systemctl stop firewalld.service
nohup ssserver -c ~/shadowsocks/config.json &

在某些云主机的CentOS7系统发现无法使用yum install python2-pip进行安装,原因是有些源被禁用了,可以使用yum repolist disabled来查看被禁用的源,其中会包含epel源。可以使用yum install python2-pip -y --enablerepo=epel的方式来安装。

安装shadowsocks客户端

这里是支持的客户端列表,​我这里仅使用的mac客户端ShadowsocksX,支持Auto Proxy Mode和Global Mode两种方式,其中Auto方式会自动下载使用sock5代理的列表,非常方便。

kcptun

为了加快访问速度,推荐使用kcp + shadowsocks

kcp的服务端配置如下,即启用20001端口,该端口会将流量导入到127.0.0.1:10001端口,即本机的shadowsocks端口

1
2
3
4
cd ~ && mkdir kcptun && cd kcptun
wget https://github.com/xtaci/kcptun/releases/download/v20190109/kcptun-linux-amd64-20190109.tar.gz
tar zvxf kcptun-linux-amd64-20190109.tar.gz
nohup ./server_linux_amd64 -l :20001 -t 127.0.0.1:10001 -key xxx -mode fast2 --log ~/kcptun/20001.log &

配置了kcptun的shadowsocks客户端仅需要配置代理为远程的kcpdun端口即可,不再需要指定shadowsocks的端口,相当于shadowsocks是透明的。

监控

为了避免aws产生额外的费用,一定要设置一下费用报警,否则被扣费了就麻烦了。

另外,可定期查看下aws的费用。试用期为一年,一年后一定要记得停掉aws服务。

最后,祝你玩的愉快!

按照惯例,年终总结依旧是按照农历算,农历乙未年的年终总结。

2015年的夏天对我而言是个转折点,终于实现了我工作以来一直想北漂的梦想,受够了各种束缚,受够了带同事的各种无奈,受够了跟同事没有话题的工作,受够了天天雾霾比北京不知严重多少倍却没有一点声音,受够了满城市找不到一家互联网公司,受够了满城市找不到一个技术会议,受够了于为了工作而工作的同事们共事,受够了天天受到官本位思想的侵蚀。

上半年在济南工作生活,下半年在北京工作生活。

似乎一直以来我的一些人生大事都是在夏天发生的。

工作

在济南的工作没什么好总结的,我已经在济南工作多年,似乎也没有太大的变化。

由于互联网公司和传统行业软件公司存在较大的差异,来到一点资讯后大约适应了两个月才完全适应。到现在,让我回想之前的工作状态,感觉好陌生,好遥远。

我的岗位为运维开发,叫做基础平台的研发更合适些。由于之前没有运维方面的工作经验,对运维开发这样的职位没有清晰的认识。对运维的需求也是在工作中逐步去摸索的。

之前在济南工作的时候,由于从事的是传统软件行业,对技术的使用比较保守,公司中很少会采用很新的技术,比如storm、kafka等。很多行业我个人利用业余时间倒是学习了很多互联网中会用到的技术,但是由于缺乏实践机会,时间一长就忘记了。

另外由于处理业务类型不同,使用的技术往往也不一样。比如haproxy这种反向代理软件在非互联网行业中其实用到比较少,因为非互联网行业面向的群体往往是政府和企业类的,不是使用互联网的广大用户群体,因此反向代理软件很少有永无之地。我之前待过的几家有些技术背景的非互联网公司往往会自己开发一些适合公司自己业务的类库或者技术架构,很多技术含量也是蛮高的,只是不为外界所知,组件无法公用,更没有开源的。

当然了,随着互联网行业的发展,传统的软件企业所使用的技术也在更新,也在采用互联网企业使用的技术。

因此,来到了互联网行业对我而言最重要的就是掌握互联网行业中会用到的技术,除了工作过程中会使用一些新技术之外,晚上下班之后也会将时间充分利用上,学习一些工作中会用到的技术。由于要学的技术实在太多了,至于先学什么后学什么,我采取了“用到什么就学什么,广撒网,后深入”的原则,这样既能达到不太影响工作,又可以达到一定广度,等到广度够了再深入了解各个技术。

由于自己的各种问题,也造成过几次系统的线上的故障,靠谱程度还有待提高。

在济南的环境下从来没有见过@福波和@凯荣为了工作这般拼得的同事,虽然他们这种拼得方式我学不来,但至少要从精神上拼一下。

工作的原因,正在使用的编程也变得更多,工作中会用到C++、Java、Python、Golang、前端技术等,不同的语言使用于不同的场景下。

工作上并没有太大的成就,主要是因为需要学习的东西太多,需需要了解,各种技术需要学习,一些开源的大数据处理技术和存在的坑也需要学习。相信随着学习的不断深入,2016年工作能小有成就。

学习

由于我学习新知识很多时候还是看技术类的书籍,比较喜欢系统一点的学习,纸质书是我的最爱。今年买过不少的技术书籍,特别是下半年以来,至少有20本技术书的样子。之前都会系统的讲书籍看完,下半年买的技术书籍基本都是看上一半或找个技术重点就扔到一边去了。主要是因为没有了足够的时间来系统的学习整本书的内容,更多的时候是对症下药而已。

学习的方向上逐渐转为务实,为工作所用,解决工作之所需,不像之前学的很多东西都是纸上谈兵,缺少实践的机会。

生活

上半年生活在济南,下半年生活在北京。

在济南的生活相对惬意,加班相对少些,虽然是单双周轮休的生活,但周末仍然是有时间出去转转的。

来北京后,很多时候变成了工作在北京,周末回济南的生活,有时候两周回去一次,有时候一周回去一次,一般周一早上坐最早的高铁回北京。这样的生活相对单调,也确实非常辛苦,基本被工作和学习占去了绝大多数时间,剩下的时间非常有限。可以说工作就是我的生活,我的生活就是工作。

由于很多时间都是远离家的,自己为家庭付出的确实非常少,这点深表遗憾。

运动

之前上班的时候每天可以骑一个多小时的自行车来运动,而且坡度也比较大。后来,运动对我而言就相当匮乏了,没有活动的次数都非常有限,运动这一点做的相当不好。

今年从夏天开始学习游泳,终于将游泳学会了,而且游泳的次数也是很多的,虽然仅仅熟练的是蛙泳。公司每周三下午有个活动时间,有一段时间每周三下午都会去游泳的,正好此时学会了游泳。

偶然的一次机会,同学邀请打了一次台球,竟对台球感兴趣起来。

北京对我而言还是个陌生的地方,偶尔周末有时间,会去一些地方转转。

健康

今年下半年开始,职业症状逐渐明显,每天坐得时间一长,腰疼就来了,而且有愈演愈烈之势。后来尝试了站着办公,本来以为每天只要站着办公腰疼就不要紧了,试验后才发现站久了也是会腰疼的。目前每天基本都是站着办公了,只有站累了的情况下才会坐下来办公。

来到北京后睡的床垫不是太舒服,后来干脆更改为了睡硬板床,早上起来后确实能明显感觉到睡硬板床轻松的多。

颈椎也不是太好,虽然感觉到时候没有那么多,但至少没有那么健康了。

做按摩的时候才发现自己的腰肌劳损挺严重了,也许是按摩师故意说的严重,至少按摩时疼的我直叫,也能感觉到按摩时腰部的肌肉硬块。听到按摩师的一句话挺伤感的,『你为了工作也是够拼的,把腰伤成这样』。

汽车

一向比较排斥汽车的我也在今年的三月份拿到了驾照,并且一度产生了年底购买汽车的想法,曾经也是痴迷过一段时间的汽车节目,在做饭和骑着自行车去上班的路上听汽车广播,对常见的车型都有所了解,还去过春季车展,进过4S店,自己对车的了解也是与日俱增。曾经想过目标车型为标致2008,后来更换为马六,后来更换为昂科塞拉。曾经痴迷到在马路上见到不认识的车型就打开汽车之家的app来查看详情的地步。

但后来来北京工作后,之前做饭和骑自行车上班的时光都变成了在公司上班,也就没有了时间来听汽车广播,渐渐的对汽车的兴趣在逐渐下降,直到现在再也不关注任何和汽车相关的信息。

通过此来看,兴趣是可以培养的,但培养起来的兴趣,一旦放下了,兴趣就会逐渐淡掉,直到恢复到最初的状态。

旅游

说来惭愧,2015年没有任何的旅行计划。我唯一的一次旅行是公司校园招聘时在哈尔滨稍微转了下。曾多少次家人建议出去旅行,都被我否决了。理由要么是不愿跟团,要么时间不够,要么自己不愿去,要么考虑钱的问题。

游戏

最近几年每到周末是必然会晚上几盘dota的,主要是用来放松,另外也有点玩游戏的瘾。我之所以一直没有戒掉玩游戏,是因为我心里清楚到了一定的年龄段对dota自然不就感兴趣了。只是没想到来的这么快,近几个月对游戏玩的越来越少,有时候一周都不会晚上一次了,而且也没有特别想玩的冲动了。

也许是因为玩游戏需要久坐,而久坐容易腰痛,也许是因为我现在已经达到了特定的年龄段,总之,都在说明,我在变老,精力确实没有之前旺盛了。

展望

  • 深入学习各种技术,技术更上多层楼。
  • 至少要旅行一次,期望的目的地是日本或韩国,如果实在不行就国内。
  • 期望能学会自由泳,蝶泳估计没戏。
  • 多加强台球的练习。
  • 熟悉下北京,多转转北京,去过的地方还非常非常的少。
  • 如果有时间的话,多学一些锻炼智力的游戏,比如魔方。
  • 工作中提高些效率,多一些生活。
  • 多读英文技术文档。
  • 多参加一些技术交流活动或其他活动。

本文讲述的是我家狗的普通一生,我家的狗即没有名贵的种族,也没有喜人的外貌,就是农村家中最常见的看家狗。

image

狗的一生中连个正儿八经的名字都没有,父母平日里呼唤狗都是我们那方言中通用的『嗷(一声)嗷(三声)嗷(一声)』(我们那方言对家里的牲口都有一种特殊的呼唤方式),而我通常会通过舌头跟上颚发出的声音来呼唤。以至于在写本文时,我不知道该如何称呼了,只能约定俗成为『狗』。

『狗』在家中的作用为看家护院的作用,在村中养狗的目的大抵如此,狗的作用也仅仅是传统意义上的一条狗。村民们还没有清闲到靠养狗来娱乐的地步,何况邻里邻外的都认识,随便找个人都能聊上个把小时,靠拉呱聊天来娱乐比遛狗更丰富直接。

自打我记事起,家里共养过三只狗,第一只养了至少五年的样子,最终已经记不清楚为何而失去了,或是因为出去走丢了,亦或是因为误食了东西而死去。第三只狗是只有种族的狗,仅仅是中间的过客,确实家人的最爱,有个优雅的名字『点点』,仅此一点就能将此『狗』秒杀N条街,事实也是如此。

家中也养过一些其他的动物,猪、猫、鸡等。猪等到长肥了也就卖掉了,也就四五个月的样子。小时候家里养过母猪,估计也得有个五年以上,但母猪除了吃和睡之外,似乎也没啥了。猫养过多只,确实跟有些猫是有感情的,但大都比较短暂,猫经常跑出去就回不来了。有些鸡在家里也养过四五年,但鸡给我留下的印象中除了吃和下蛋之外,就剩下美味的鸡汤了。唯独『狗』在家中的时间最长,在家中的地位也最高,给家里的贡献也是最大的,给我留下的印象也是颇为深刻。

『狗』大概是我在刚上初中那会,父亲从集市上花了15或者30元钱抑或60元买的。刚买来的时候记得还不满月的样子,特别的可爱,白灰色毛居多,背上有个大大的灰黑色大圆点,不正不斜圆心就在脊梁骨的位置,而且圆是非常的标准的圆,头和尾巴是黄色的毛。由于小,不会造成什么破坏,就直接放在屋子总天天跑,我们吃饭时,它就在下面转啊转,等待着给点馒头或者菜来吃,一见到有东西吃,那尾巴就摇啊摇,摇啊摇。有时候在屋子里碍事了,我就用手揪住它背上的肉皮,扔到一边去,不一会又会回来,然后又让我给揪到一边去,这样揪来揪去的好好玩,听大人们说,这样狗是不疼的。

揪着揪着『狗』就这样被我揪大了,大了之后自然要发挥指责了,总不能天天让家里白白养着,凡事必然有其存在价值,它的价值就是看家护院。这样一干可就是一辈子,它的一辈子就在家里不大的院子里面绕着铁链转,转啊转,直到再也没有力气转下去。自从被拴上铁链的时刻开始,直到生命的最后一刻,再也没有进过曾经在饭桌底下绕啊绕找食物的屋子,饭桌下再也容不下它。

『狗』的看家还是非常尽职尽责,当然了,要不怎么是狗呢。只要是家里来的是陌生人,都会咬个不停,甚至是我爷爷来我家,都会咬个不停。要是觉得听起来太吵了,只要对它喊一声「狗」就会消停很多,跟家人的默契配合的相当不错。

『狗』的记性也是相当不错的,记得上高中时,一个月只能回一次家,每次回家狗都会认识,从来不会当成陌生人狂咬。后来,上了大学,成了半年回一次家了,刚进家门狗就开始叫,也就是脚踏进院子没多久,狗就不叫了,已经认出我也曾经是这里的主人。每次回家都会跟『狗』玩上半天,喂点吃的,挠挠肚子,看着它围着我转。

虽然对陌生人总是咬个不停,但是当人走到旁边时却不会上去咬人,对它凶点甚至还会吓得跑到狗窝里去,完全不是疯狗那样会咬人。但也确实咬过一次人,记得那是上高一那会,姨夫在我家喝多了,走到它旁边,它还在不停的咬,姨夫由于喝的多,对其踹了几脚,抑或身上酒味过重,这下『狗』可不干了,照着姨夫的脚脖子就咬了一口。这是已知的仅有的一次咬人经历。

『狗』是母狗,大概一岁多的时候生过三只狗,其中两只已经夭折了,另外一只目前在我爷爷家里养着。家里来陌生人时,狗都会从狗窝猛然间钻出来,仿佛早发现一会陌生人就能领到奖赏一般。两只小狗的死都是它猛然间出来时将正在吃奶的小狗用铁链给带出来摔死的,挺可怜的。不知是不是脑子缺根筋,看家的本领远比看护自己孩子来的高超,就好比在休产假的妈妈,却天天想着工作,自此之后再也没生过小狗。

『狗』的一声是用铁链禁锢的一生,成年后99%的时光都是用铁链拴着的,比互联网公司的服务可靠性都好的多。偶尔铁链会松掉,它仍然不知道自己的地盘之外仍然可以活动,直到偶然间走出了自己的活动范围,才发现原来自己的地盘外也可以肆意走动了,不过美好的时光不会太长,因为等着家人发现了,禁锢的铁链又跑到自己的脖子里了。有时家人发现的不及时,发现它又回到了原地了,也许它发现原来曾经向往的陌生地方也不过如此,远没有自己的地盘来的安全可靠和温馨。

image

记得有一次冬天大雾,能见度非常低,『狗』跑出了家门,一路向北,由于雾太大,迷失了方向。我跑出去在家附近找了半个小时未果,爷爷骑着自行车出去打听到别人看见过,父亲终于在离家二里地外的地方找到了,也是虚惊一场。

『狗』对吃得从来不挑,只要有吃的就行。记得之前家里还喂猪的时候,它就在旁边等着猪们吃完后再去吃猪剩下的,每次都会把猪槽舔的溜滑,比可以刷过的还干净。后来家里不喂猪了,就在喂鸡的时候一块喂一下。夏天吃完西瓜后,把西瓜皮扔过去,狗也可以啃得仅剩下一层薄薄的皮。偶尔忘记喂了,『狗』就会zhengzheng的叫,家人自然也能领悟『狗』的意图。

大约刚开始工作那会,姑家的狗『点点』由于没时间照顾在我家里养了半年,『点点』是姐姐给取的名字,长得一副小巧可爱样,在城市的笼子中靠吃狗粮长大。在我们那喂狗几乎是不用狗粮的,估计也买不到,因为没市场。『点点』自然是不能跟『狗』吃一样的,每天都会味一些狗粮,后来家人就买了些过期的方便面和馒头搀和着来喂,而『狗』的主食依旧是吃着跟鸡一样的凉水活玉米面。『点点』白天都在笼子里,只有放出来的时候才会找个地方拉屎撒尿,自然比随地大小便的『狗』更讨人喜欢。晚上『点点』是放在院子里的,院子里的任何角落都是『点点』的活动范围,这点也是『狗』可望不可及的。白天『点点』的笼子是放在大门下的,逢人从门口经过都能看到可人的样子,自然也会吸引很多人的目光。

image

也就是从『点点』刚来我家的时候,发现有时候从它身旁经过,它都没有任何反应了,因为『狗』的耳朵不好用了。人老了耳朵会聋,狗亦如此。有时候陌生人都进到家里了,发现『狗』仍然在狗窝里或外面太阳下睡觉,即使耳朵是贴在地面上的。狗天生骄傲的就是耳朵,试想一名工程师如果不能用双手敲代码,那怎么称之为码农。

自从『狗』聋了后,明显感觉到『狗』的情绪变得低沉了,也许是因为耳朵不好用了,也许是进入晚年了,也许是因为『点点』的缘故,虽贵为正室,却不再受宠幸。直到半年后的『点点』走后,也一直没有缓过来。

近几年,我每次回家都能感受到『狗』是一年不如一年,最后一次见到是在2015年的十一,那时它很多时候都是趴在窝里睡觉的,除了看家,也没啥本事,既然看家技能已失,那就只能睡觉了。

2016.1.22傍晚听到了『狗』去世的消息,脑海中自然也是联想关于『狗』的往事,历历在目,眼角泪花直流。没有任何仪式,『狗』悄悄的离开了奉献了自己一生的岗位,摆脱了束缚了自己一辈子的锁链,黯然离开了自己的主人。

当天天气极度寒冷,应该是一年中最冷的天气了,家中下起了大雪,也许是老天送给『狗』的葬礼,雪花仿佛跟『狗』的灵魂一般纯洁。

算下来从2000年左右到现在该有16岁的样子了,这16年是我人生中最年轻的时光,我从懵懂的少年已变成了社会中的青年,却是『狗』的一生。

下图是2016.1.22上午时的照片,已经生命垂危,生命在倒计时。

image


一个月前,父亲又弄了条小狗,凑巧的是,小狗的模样跟『狗』长的颇为相似,毛色也一致,甚至连背上也有一个灰黑色的圆点。虽没当面见过,但看小狗的照片不禁联想到『狗』的小时候仿佛是狗的小时候,这也许是『狗』的生命的延续。

image

keepalived的作用为保持存活服务,服务启动后会在两台物理机器之间维护一个vip,但是仅有一台物理机器拥有该vip,这样就保证了两台机器之间是主备。

安装

在ubuntu下直接执行:sudo apt-get install keepalived.

使用

本例子两台机器的物理ip地址分别为10.101.185和10.101.1.186,要增加的虚拟ip地址为10.101.0.101、10.101.0.102、10.101.0.107和10.101.0.108,其中10.101.0.101和10.101.0.102在10.101.185上为主,10.101.0.107和10.101.0.108在10.101.1.186上为主。

keepalived的默认配置文件位于/etc/keepalived/keepalived.conf目录下,由于两台物理机器之间的主辅关系不同,配置文件也不相同。

10.101.185机器上的配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
! Configuration File for keepalived

global_defs {
# 报警邮箱配置
notification_email {
ops@yidian-inc.com
}
smtp_server 10.101.1.139
smtp_connect_timeout 30
router_id 101-1-185-lg-201-l10.yidian.com // 运行机器的唯一标识,每个机器应该都不一样,可以直接使用hostname代替,具体用在什么地方暂时不是很清楚
}

vrrp_instance ha-internal-1 {
state MASTER
interface eth0
virtual_router_id 1 // VRID标记,可以设置为0-255,对应VRRD协议中的Virtual Rtr Id
priority 100 // 对应VRRD协议中的priority选项
advert_int 1 // 检测间隔,默认为1s,对应VRRD协议中的adver int
authentication {
auth_type PASS // 认证方式,支持PASS和AH
auth_pass 1-internal-ha // 认证的密码,从抓取的包中看到
}
// 声明的虚拟ip地址,这些ip会在VRRP一些的一个包发送
// 另外VRRP协议中还有一个Count IP Addrs用来指明需要声明多少个VIP
virtual_ipaddress {
10.101.0.101/22 dev eth0
10.101.0.102/22 dev eth0
}
}

vrrp_instance ha-internal-2 {
state BACKUP
interface eth0
virtual_router_id 2
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 2-internal-ha
}
virtual_ipaddress {
10.101.0.107/22 dev eth0
10.101.0.108/22 dev eth0
}
}

10.101.1.186上的配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
! Configuration File for keepalived

global_defs {
notification_email {
ops@yidian-inc.com
}
smtp_server 10.101.1.139
smtp_connect_timeout 30
router_id 101-1-186-lg-201-l10.yidian.com
}

vrrp_instance ha-internal-1 {
state BACKUP
interface eth0
virtual_router_id 1
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 1-internal-ha
}
virtual_ipaddress {
10.101.0.101/22 dev eth0
10.101.0.102/22 dev eth0
}
}

vrrp_instance ha-internal-2 {
state MASTER
interface eth0
virtual_router_id 2
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 2-internal-ha
}
virtual_ipaddress {
10.101.0.107/22 dev eth0
10.101.0.108/22 dev eth0
}
}

配置文件搭建完毕后,通过sudo service keepalived start即可启动服务,执行ip addr命令即可看到vip。需要注意的是,通过ifconfig命令是看不到vip的。

有了vip,其他服务就可以利用该vip做一些绑定vip的端口来作为主辅热备模式了。

about vrrp

关于VRRP的详细说明可以查看RFC3768,我这里记录几点说明。

协议中的以太网Destination Address的值必须为多播地址224.0.0.18。

当前正在使用的VRRP版本为version 2,认证功能已经取消,但为了向下兼容,仍然可用。在抓取的包中,仍在使用认证信息

download

这里提供两个vrrp协议的pcap包

一直对堆排序算法用的不错,但是又是在排序中挺重要的算法,并且可以求解其他问题,比如top k问题。已经对堆排序学习过好多次了,无奈每次都记不太清楚具体的细节问题,本文对堆的问题进行整理。本文的排序例子来源于严蔚敏的《数据结构》,本文的知识点来自《算法导论》。

最大堆为堆中的最大元素位于根节点,顾名思义,最小堆的根节点为最小值。堆的性质决定了堆中节点一定大于等于其子节点。在堆排序算法中用到的是最大堆,最小堆用于构造优先队列,要是使用最小堆进行排序,得到的排序结果为倒序。

堆的结构为完全二叉树,因此可以用数组存储来代替树的链式存储结构。

建最大堆过程

我这里通过图表的形式对建大顶堆的过程进行了展示,不再对文字进行叙述。在堆排序的过程中会不断进行建最大堆过程的调用。

堆的初始化

堆排序的核心步骤

清楚了堆的初始化,再看一下下面的堆排序步骤就非常清楚了,不需要图片进行描述了。堆排序的步骤:

  1. 将待排序的数组初始化为大顶堆,该过程即建堆。
  2. 将堆顶元素与最后一个元素进行交换,除去最后一个元素外可以组建为一个新的大顶堆。
  3. 新建立的堆不是大顶堆,需要重新建立大顶堆。重复上面的处理流程,直到堆中仅剩下一个元素。

top k问题的堆解法

该问题最常规和通用的解决思路为使用快速排序,还可以在N的范围不大的情况下采用哈希(桶)的方式。

另外一种解法就是堆排序的思路来解决。这里用到的为最小堆,用最小堆来存储最大的k个数,其中堆顶元素为最大k个数种最小的数。这个解法初看有些别扭,求最大的k个数,居然会用到小顶堆。

该算法必然是一个个遍历N个数一次就够了,这点很好理解。每读取一个新的数x,如果x比堆顶的元素y小,则抛弃;如果x比y大,则用x替换y,并重新更新堆。

十一回农村老家,有件小事有些感悟。

只要家里有人,家里的大门白天一直都是敞着的,外面的人都可以直接走进来,这在农村是很正常的一件事情,门敞着才说明家里是有人的,农村的人没有城里人这么多的隔阂。

正巧地里的活都干得差不多了,母亲在院子里晒着太阳,我在屋子里收拾东西。从门口走到院里一个人来,只见一身道姑打扮,还带一顶帽子,嘴里振振有辞,说是泰山娘娘庙里的保佑家里平安之类的。母亲见到来者第一反应就是骗子,立马上前说是地里有活要干,马上要出去了。来者压根不理会母亲的话,依旧是保佑平安之类的,像极了大街上迎上前去得乞讨者。来者说道,要捐款之类的,并有个小本子,上面写着捐款者的名字。母亲看了眼捐款者的名单,很多都是邻居家的,说明来者刚从家里过来,迟疑了一会便签上了名字,回屋里去取钱。

这时还在屋子里的我才看到并明白过来是这么一回事,我一看母亲名字都签上了,钱肯定是要给的了,想逃掉避免少不了一番纠结。我便回屋子去取钱,在城市待习惯了,知道乞讨者五毛一块就能打发的很高兴,我便从钱包里去了两张一块的,其中一张还是备用的,我先给一块,要是嫌少再给两块。我先于母亲出了屋子,给到了来者一块钱,岂知来者说道别人都是给三十五十的,这些太少了我不要。靠!这年头乞讨还嫌钱少啊,还是我太out了?我直接说那你走吧,我没钱,并转头回屋子,可最烦的是她也跟着往屋里走。

就在这时母亲从屋子里走出来并拿着10块钱,迎上前去给了她。又是嫌少之类的话,最后也不情愿的收下了,并留下了一根红丝带,说些全家平安之类的话就走了,当然了骗子的目的已经完成了,只需匆匆收场就行了。

此事的经过到此结束,但却有个问题挺令我深思的,这也是为什么写下本文的原因。

父母并不富裕,家里一直也是过得比较平淡的生活,在我看来勤奋和勤俭节约一直是我们老家那块的美德。平常家里买个菜什么的都要为了几毛钱掂量半天,但却在面对乞讨施舍这种事情上扔掉了10块钱的巨款,而且母亲对于骗钱这件事从始至终都是知情的。

事后,我的同样上当受骗的邻居也来到了我家,通过邻居和我母亲的谈话我大体理解了他们在经历此事时的心理活动。由于每年都会有多次来到家里进行骗钱的,骗钱的方式是多种多样的,无非是找不到孩子,回不了家之类的,母亲一开始见到骗子就知道是个骗子,这第一印象的判断是过关的。

母亲对骗子的第二个行为是阻拦,母亲用了要去地里干活的信息来阻拦,但是阻拦不彻底,见阻拦不成功就放弃了。这一点上就显现出了的缺点,不知道用合理的手段来保护自己,并完全从主动状态变为了被动状态。之所以意志这么不坚定,其中有一个很大的因素就是母亲知道强加阻拦的后果就是骗子可能会爆粗口,完全不想听骗子絮絮叨叨个没完没了,撵都撵不走,还不如给点钱省事。另外得罪的骗子的后果可能会更麻烦,毕竟骗子往往都是一个团伙,且知道家庭住址,怕有什么报复行为。所以之所有给钱的原因就是花钱买个安宁,免得带来一身的麻烦,当然从这个出发点上给钱是对的。骗子也正是利用了这一点才在农村屡试不爽。

但给钱的数目跟平时的生活水平是完全不相符的,要知道在农村买上10块钱的菜可以吃上好几顿。我觉得之所以出现这个问题,根源在于对自己的不够重视。在中国这种权力的社会中,母亲一直觉得处于权力的最底层,事实也确实如此。即使在自己的家中也很容易变主动为被动,让骗子得手。

可能有人会说农村的法律意识淡薄,不知道合理的维权,完全可以打110来解决。我曾经打110处理过店铺扰民这种鸡毛小事,110给的处理时间为5天,这还是在城市里。我估计换做农村的派出所,这种小事估计110是请不动的。

我在此次事件中并没有第一时间作出应有的反应,这点我需要反省。首先,我见到母亲签字后没有跟骗子要一下工作证明,这样子至少让骗子没这么容易得逞,给我的反驳增加大大的筹码。其次,没有阻拦母亲给骗子送钱,按照我的意思是跟骗子死缠到底的,毕竟是在我家,给不给钱也是我的自由。但我怕在家里生活时间不长,骗子的规矩我不懂,还是顺从了母亲的行为。

之所以写这篇文章是想梳理下农民身上的共同缺点及我身上的缺点。我不是歧视农民,我是农村出来的,我知道农村人的辛苦,忙起来的时候他们的辛苦程度是我等码农不能企及的。

在这里为广大奋斗在田地里的农民致敬!

0%