404频道

学习笔记

某些情况下需要搭建自己的yum源,比如维持特定的软件包版本等,只需要从网上下载合适的rpm包,即可构建yum源。

repodata数据

创建/data/yum.repo目录用来存放rpm包。

可以使用yumdownloader命令来下载rpm包到本地,并且不安装。这里以安装mesos为例,在/data/yum.repo目录下执行yumdownloader mesos即可下载mesos的rpm包到本地。

安装createrepo:yum install createrepo,用来根据rpm包产生对应的包信息。

每加入一个rpm包需要更新下repo的信息,执行createrepo --update /data/yum.repo。会自动产生repodata目录。

搭建web服务

需要对外提供web服务,通常会使用nginx或者apache来对外提供服务,这里使用python SimpleHTTPServer来对外提供服务,执行cd /data/yum.repo && python -m SimpleHTTPServer 1080

客户端的repo文件设置

安装yum优先级插件,用来设置yum源的优先级: yum install -y yum-plugin-priorities

每个需要使用该yum源的客户端需要在/etc/yum.repo.d/目录下增加devops.repo文件。

1
2
3
4
5
6
[devops]
name=dev-ops
baseurl=http://10.103.17.184:1080/
enabled=1
gpgcheck=0
priority=1

本次grafana的升级从版本3.1.1,变更为4.4.3,涉及到一个大的版本跨度。同时之前在使用的存储为sqlite,趁着这次升级更改为mysql。

grafana升级

直接从官网下载对应的4.4.3版本的二进制包,修改部分配置即可,该部分没任何难度。

sqlite to mysql

由于grafana使用的表结构在3.1.1到4.4.3之间有变更,不能直接将3.1.1版本的sqlite中的数据导入到4.4.3的mysql中。我的方法为先使用3.1.1版grafana将数据从sqlite导入到mysql中,然后再升级grafana的版本,grafana可以自动修改表结构。

在的mysql中创建grafana的数据库,并修改数据库的编码为utf-8.

修改grafana 3.1.1配置文件conf/defaults.ini如下:

1
2
3
4
5
6
7
8
9
10
11
[database]
# You can configure the database connection by specifying type, host, name, user and password
# as separate properties or as on string using the url property.

# Either "mysql", "postgres" or "sqlite3", it's your choice
type = mysql
host = xx.xx.xx.xx:3306
name = grafana
user = dev
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
password = dev

启动grafana后会自动在grafana数据库中创建相应的表结构,接下来就是将sqlite中的数据导入到mysql中。

在data目录下增加如下脚本sqlitedump.sh,并执行sh sqlitedump.sh grafana.db > grafana.sql

1
2
3
4
5
6
7
8
9
#!/bin/sh
DB=$1
TABLES=$(sqlite3 $DB .tables | grep -v migration_log)
for t in $TABLES; do
echo "TRUNCATE TABLE $t;"
done
for t in $TABLES; do
echo -e ".mode insert $t\nselect * from $t;"
done | sqlite3 $DB

然后将grafana.sql导入到新创建的mysql。

将grafana 3.1.1版本停掉,将grafana 4.4.3版本的配置指向到mysql数据库,启动grafana 4.4.3后,mysql中的表结构会自动变更。

至此,grafana的升级完成。

由于不允许通过ssh直接连接服务器,即服务器的22端口是不开放的,但是其他端口号可以访问。这就造成了往服务器上传输文件会特别麻烦,需要通过relay中转一下。

rsync命令有shell模式和daemon模式,为了解决该问题,可以通过rsync的daemon模式,rysnc的daemon模式会默认使用873端口,不使用ssh协议,以此来绕过ssh的22端口限制。

最终可以实现在本地通过rsync一条命令直接同步文件或文件夹到服务器的指定目录下。

首先在服务器上搭建rsync的服务端,rsync的安装不再介绍。

修改服务器的rsync配置文件/etc/rsyncd.conf如下:

1
2
3
4
5
6
[worker]
path = /home/worker
list = true
uid = worker
gid = worker
read only = false

这里为了简便,并未设置rsync的用户名和密码。

客户端同步文件的命令如下:

1
rsync -avz $SRC worker@$HOST::worker --exclude=target --exclude=.git --exclude=.idea --delete

命令中的第一个worker为HOST的登录用户名,第二个worker为rysncd配置文件中配置的组名。–exclude选项可以用来屏蔽需要同步的文件夹。–delete选项用来同步删除的文件或文件夹。

daemon模式跟ssh模式相比,无法指定服务器的具体某一个路径,使用不够灵活,但也基本可以满足需求。只能通过daemon配置文件中配置的组中的path参数,同步时仅能通过::组名的形式来指定。

最近公司需要首先登录跳板机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

0%