Living a Simple Life is a Happy Life

有饭吃,自由自在,就非常开心

装服务器偶得

| Comments

最近工作需要,连续装了不少服务器。虽然做系统真是没什么技术含量的事,但做多了还是有些想法,记录下。

硬件tips

Dell

  • Dell PowerEdge 2950 2U

  • Dell PowerEdge R610 2U

  • Dell PowerEdge R630 1U

  • Dell PowerEdge R710 1U

  • Dell PowerEdge R720xd 1U

对Dell 系列的服务器印象一直很好,皮实耐折腾, R系列的兼容性也很好,开机启动速度也算是凑合。

但是最近发现一个问题,就是R630 系列的做了Raid5之后,分XFS分区,用clonezilla做镜像的时候非常慢。如果要调大xfs的blocksize,又需要重新编译内核,比较麻烦。

HP

  • HP ProLiant DL380 Gen6 2U

  • HP ProLiant DL360 Gen9 1U

网上对惠普 DL360系列的机器评价很好,但我对它印象不佳。

首先说设计,前面板只有一个usb接口,一般做系统的时候,条件简陋点,需要一个USB光驱,一套键鼠,光驱可以插后面,但是键鼠插后面太麻烦了,所以我比较喜欢前面板有两个USB接口的机器。

然后HP 的BIOS 自检极其缓慢,是Dell的1.5倍。很扯。

然后DL360系列,如果安装centos系,自编译内核的话,需要自己编译Raid驱动,这个极其不爽,而且惠普的官网找驱动,真是费力,而且kernel编出来总有种种小毛病。

比较值得赞扬的是 Gen9以后的机器,做Raid的界面做的挺漂亮的。但是极其坑爹的是,BIOS自检过了以后,没有明确提示按F8进Raid,一定要到网上查。而且我觉得HP的BIOS管理引导做的很啰嗦,要进三层才能看到功能。

Lenovo

  • Lenovo System x3550 M5

公司里说进了IBM的服务器,开机一看,打的Lenovo的LOGO,好吧,原来联想已经做到这个程度了。

机器的配置不错,说说吐槽点:

  • 首先自检的速度又慢了一个档次,重启一遍可以买个包子吃了。

  • BIOS 工具又是层层深入,做Raid估计要进入5级菜单才能搞定。

  • 不支持centos5系了,同事打电话问客服,号称没测过centos6.4以下的,真是理直气壮

吐槽

  • 所有的机器做Raid的那套东西大同小异,控制器都是一家的。但是界面包装有好有坏,按靠谱程度排序 HP>DELL>Lenovo

  • 做好机器后,总是需要在前面贴个标签,现在机器越做越小,最直观的感觉就是前面贴个标签都找不到地方了。看人家管理,有把标签挂在上面的,有在LED屏上编号的,都不方便。为什么没有厂商在前面设计一个小卡片槽,专门放标签纸呢,我估计这个小功能肯定会讨得很多人欢心。

  • 我装服务器,到现在为止一个最大的吐槽点,没有见过一家厂商解决过。就是机器自检的时候,很多显示器兼容性不好,会把左边屏幕的输出吃掉一截。最坑爹的是,每家的BIOS输出都是紧靠左边打出来的,往往会有 F2=Setup 前面的 F2被吃掉的情况,他们就不知道把输出居中一点,我只能说这些公司真是僵化了,下一个诺基亚,说不定就是惠普。

  • 最后就是所有的所谓大公司,官网做的都和微软帮助一个style,就是我按照提示一步步点下去,又回到开始了,它还问我”有帮助吗?”,已经吐槽无力了。在我看来,这些所谓的高科技大公司,其实已经比很多传统行业还恐龙了,看看他们数十年如一日的BIOS就知道了。只不过积累在那里,让他们产生自我感觉良好的错觉。这些公司死是早晚的事。

软件tips

centos5 -> centos6 -> centos7

redhat系的的安装界面 一代比一代漂亮,也一代比一代依赖鼠标。

  • centos5不支持鼠标,熟练后完全依赖键盘一路打下去,很方便
  • centos6 界面很朴素,但比较好用,键盘鼠标都能不是很痛苦的搞定
  • centos7 界面比较花哨了,都做到一个安装界面里,鼠标操作很方便,键盘操作很痛苦,我曾经在没有鼠标的环境下,硬是花了半个小时装了个centos7.1U

孰是孰非,让后来人评说。

xfs resize blocksize

  • xfs做文件系统的时候,试图mkfs.xfs -b –size=xxx ,不生效,默认redhat系的page_size设置的就是4K,xfs的blocksize必须不大于这个size,如果要设大,只能重新编译kernel

Linux Profile and Debug Tools of Performance

| Comments

用perf工具统计系统调用

1
perf top

或者统计一段时间内的调用

1
2
perf record -a -g -F 1000 sleep 30
perf report -g

用strace 追踪某个进程的调用

1
strace -c ls

或者attach一个进程

1
strace -c -p pid

查看磁盘调用

1
lsof -p pid

磁盘负载

1
iostat -x 5 -m

整体负载统计

1
vmstat 5 

Linux Cheat Sheet

| Comments

收集linux下需要多次google的命令

编码问题

  • utf16 > utf8
1
iconv -f UTF-16 -t UTF-8 file_name

web开发命令

  • curl post 一个json文件
1
curl -H "Content-Type: application/json"--data @body.json http://localhost:8080/ui/webapp/conf
  • curl post 一个json字符串
1
curl -H "Content-Type: application/json"-d '{"username":"xyz","password":"xyz"}' http://localhost:3000/api/login

系统时间

  • centos6系列修改时区
1
2
3
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
vim /etc/sysconfig/clock
ZONE="Asia/Shanghai"
  • centos7系列修改时区
1
2
timedatectl list-timezones | grep Asia
timedatectl set-timezone Asia/Shanghai
  • 设置系统时间
1
date +"%Y%m%d%H%M%S"

系统状态

  • 查看系统占用句柄数
1
lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr|more

程序

  • mongo导出
1
mongoexport  -u crossflow -p '0701!1523#SH' -authenticationDatabase admin -d bpc -c main_app_datapath -o main_app_datapath.json

shell 处理

  • 获取当前路径
1
export CURRENT_PATH=$(cd "$(dirname "$0")"; pwd)
  • 检查CPU load
1
2
CURRENT_LOAD=`top -b -n 1|grep 'load average'|awk '{print $12}'|sed 's/,//'`
declare -i current_load=${CURRENT_LOAD%.*}
  • find 匹配多个pattern
1
find /usr/lib64 -name '*.so' -o -name '*.so.1'

文本处理

  • 根据某个字段做uniq
1
sort -u -t, -k1 file

Debug Kernel Panic in Centos

| Comments

当你面对一台新机器,出于某些原因(不是闲的慌)不得不自己编译一个内核时,会碰上kernel panic。

kernel panic很让人心烦,启动时的panic更让人烦,没有挂上硬盘,没有任何log的panic尤其让人烦。

提供几个解决问题的瞎搞方法: (以下内容针对于redhat系,但大部分方法是通用的)

判断引起panic的环节

简单描述下启动流程:

1 Power On                                 Maybe Err:Worlds Collides
2 BIOS                                     Maybe Err:Worlds Collides
3 Load Grub From MBR                       Maybe Err:See nothing
4 load Grub and show it                    Maybe Err:Grub loads failed
5 Grub reads menu.list                     Maybe Err:Grub loads failed
6 Grub loads kernel image                  Maybe Err:Grub loads failed
7 kernel mounts root filesystem            Maybe Err:PANIC
8 kernel runs init                         Maybe Err:PANIC
9 init runs scripts to start               Maybe Err:PANIC

首先你要确认下是哪个环节引起的panic,如果你的log打得比较全,一般能根据蛛丝马迹判断是上面那个环节引起的问题。一般panic发生在step7,step8, step9环节当中。

  • step9: 走到这里已经无大碍,无非是/etc/rc.sysinit 之流挂载了不该有的设备,启动了不知道神马的服务,可以直接在启动脚本中打各种log调试

  • step8: 这个就比较棘手,一般是initramfs 解压后执行某些脚本报错,所幸是大部分都是init级别的,一般可以在grub的kernel后面加参数,挂载shell调,也可以直接用工具修改initramfs镜像中的文件,重新打包二分法定位

  • step7: 也比较棘手,一般panic总要怀疑磁盘驱动,我感觉这个是导致panic的大户,另外如果屏幕没有东东输出,估计视频驱动也要鼓捣一番。

下面针对 step7,step8级别的panic提供一些瞎搞手段

在kernel 参数中加入调试开关,关闭ACPI,selinux

1
2
3
4
  title CentOS (2.6.32-358.el6.x86_64)
          root (hd0,0)
          kernel /vmlinuz-2.6.32-358.el6.x86_64 ro root=/dev/mapper/vg_localhost-lv_root rd_NO_LUKS rd_NO_MD rd_LVM_LV=vg_localhost/lv_swap crashkernel=128M LANG=zh_CN.UTF-8 rd_LVM_LV=vg_localhost/lv_root  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM debug selinux=0 acpi=0
          initrd /initramfs-2.6.32-358.el6.x86_64.img

这是考验人品的时候,不管三七二十一,先把最有可能的问题点排除掉。另外redhat系的会在kernel后面加上 rhgb quiet 之类的参数,统统去掉,开机的时候好好盯着屏幕看看,有没有可疑的东东输出。 因为系统可能会在短时间内输出大量log而没有记录,你需要设置一下输出log的速率和暂停时机,更详细的参数可以在这里找到:

https://wiki.archlinux.org/index.php/Boot_debugging

在kernel 参数中加入dracut的调试开关

redhat系后期采用了dracut构建 initrd镜像,关于dracut的手册在这里:

http://people.redhat.com/harald/dracut-rhel6.html#lsinitrd

调试开关在这里:

https://fedoraproject.org/wiki/How_to_debug_Dracut_problems

你可以设定rdshell,在panic之后跳入dracut提供的shell,打dmesg看看log信息。

最后的最后,实在不知道为啥了,而且你很闲,可以考虑启动时加串口设备调试

一些tooltip

  • 编译kernel的时候,make menuconfig,3.10以后的内核支持搜索某个开关后按数字键直接跳到那个开关的设置项中,这个很有用

  • redhat系用dracut构建initrd,配置文件默认在 /usr/share/dracut/ ,如果你懒得改 initramfs,可以直接修改里面的配置文件,然后重新make install即可

  • 有时候你不好确认根文件系统挂载到哪里了,可以参考这里:

http://free-electrons.com/blog/find-root-device/

其它参考资料:

http://www.tuxradar.com/content/how-fix-linux-boot-problems

Tcpdump Commands

| Comments

tcpdump 的抓包保存到文件的命令参数是-w xxx.cap

  • 抓eth1的包
1
tcpdump -i eth1 -w /tmp/xxx.pcap
  • 抓eth1的包,用ip+port的形式显示通信对
1
tcpdump -i eth1 -nn -w /tmp/xxx.pcap
  • 抓 192.168.1.123的包
1
tcpdump -i eth1 host 192.168.1.123 -w /tmp/xxx.cap
  • 抓192.168.1.123的80端口的包
1
tcpdump -i eth1 host 192.168.1.123 and port 80 -w /tmp/xxx.cap
  • 抓192.168.1.123的icmp的包
1
tcpdump -i eth1 host 192.168.1.123 and icmp -w /tmp/xxx.cap
  • 抓192.168.1.123的80端口和110和25以外的其他端口的包
1
tcpdump -i eth1 host 192.168.1.123 and ! port 80 and ! port 25 and ! port 110 -w /tmp/xxx.cap
  • 抓vlan 1的包
1
tcpdump -i eth1 port 80 and vlan 1 -w /tmp/xxx.cap
  • 抓pppoe的密码
1
tcpdump -i eth1 pppoes -w /tmp/xxx.cap
  • 以100m大小分割保存文件, 超过100m另开一个文件
1
tcpdump -i eth1 -w /tmp/xxx.cap  -C 100m
  • 把后两个数据包并到一个数据包merge.pcap
1
mergecap -w merge.pcap 1.pcap 2.pcap
  • 按照radius条件过滤数据包
1
tshark -r 1.pcap radius -w radius.pcap
  • 按照数据包数分割一个大的数据
1
editcap -c 1000000 merge.pcap split01.pcap
  • split pcap
1
editcap -c 100000 in.pcap out.pcap

How to Xargs Separate Parameters

| Comments

做过很多遍了,每次还是得现查,记一下:

echo "'param 1' 'param 2'" | xargs -n1 | xargs -I@ echo \[@\] \[@\]

output:

1
2
[param 1] [param 1]
[param 2] [param 2]

xargs里面替换字符串

ls|xargs -I @  echo "mv @ @.pack"|sed 's/.json.pack.pack/.pack/g'|bash

Python编程实战 - 笔记1

| Comments

这本书讲的挺实在的,设计模式的部分又复习了一遍。另外又学了几个Python3的新decorator。

创建型设计模式

抽象工厂 (Abstract Factory)

  • 名字就用AbstractFactory好了,不要起什么BaseFactory之类的
  • 相关类都放到对应的Factory Class里面,不要暴露给外面了

建造者模式 (Build)

  • 和工厂的区别就是保存了创建对象时各个部分的细节

工厂模式

  • 根据情况实例化对象
  • 还是注意和抽象工厂的区别,抽象工厂是将创建对象的行为抽象出来,而工厂模式则是根据要创建的对象类型实例化

原型模式 (Prototype)

  • 这个模式其实在javascript的根本,不过Python的实现方法还真是五花八门,我说直接用copy就好了嘛

单例模式 (Singleton)

  • 我最中意的一种实现:
1
2
3
4
5
6
7
8
9
10
11
class Borg:
    _shared_state = {}
    def __init__(self):
        self.__dict__ = self._shared_state

class Singleton(Borg):
    def __init__(self, arg):
        Borg.__init__(self)
        self.val = arg
    def __str__(self):
        return self.val

结构型设计

  • 作用就是改装对象,或者把小对象合并为大对象

Adapter

  • 其实就是转接方法

Bridge

  • 把方法抽象出来

Composite

  • Python里面有一种省一点内存的写法,可以直接用CompositeItem和Item两个类来实现,不过我觉得不直观

decorator

  • 几个新的decorator:

    • @functools_wraps : 装饰器工厂

    • @statically_typed : 类型检查

  • 另外@ensure类修饰符可以用来简化设置property的代码

Facade

  • 这个模式其实是天天在做的,就是把接口聚合的好看一点
  • 其实思想可以推广到很多方面,比如Docker,就是LXC的一个Facader,而且做的比较好看,于是大家就都来用了

Flyweight

  • 管理许多小对象的时候用引用
  • Python用__slot__ Attribute来做最方便
  • 里面关于用shelve对象存储class attribute的思路挺实用的

Multiline Comments in Docker File

| Comments

为了减少Image的fs layout数目,Dockerfile中经常会把多个命令集中到一个 RUN 指令下。

多行之后可读性就很差了。

有个比较偏门的写注释的方法:

1
2
3
4
5
6
7
8
9
10
11
RUN mkdir -p /home/build/npm3 && \
    mkdir -p /home/build/smartprobe && \
    mkdir -p /home/build/bpc3 && \
    `#====================================================` \
    `#=============checkout and install rpms==============` \
    svn export xxx && \
    rpm -ivh --force --nodeps *.rpm && \
    `#====================================================` \
    `#=============checkout and install python==============` \
    ... && \

比较实用,推荐之。

Different Users in Same Unix Group Can Not Run Mongod

| Comments

事情的缘起是这样的…….

想要在Dockerfile中启动一个MongoDB,之后编译为Docker image。(不要问我问什么要在docker image中存一个mongodb数据库,真实世界的需求你永远想不到)

Docker build不支持 –privileged,所以默认的/etc/init.d/mongod 这个脚本中的

1
runuser -s /bin/bash mongod -c 'ulimit -S -c 0 >/dev/null 2>&1 ; numactl --interleave=all /usr/bin/mongod -f /etc/mongod.conf'

这种写法就死翘翘了。

github上有这个Issue:

https://github.com/docker/docker/issues/1916

大家讨论了1年多,对于怎么解决,还是没有个所以然。(话说要再吐槽一下github的issue了,一般大一点的项目,一个issue跨度以年来论,长篇大论读完也不容易呀)

最后只好在Dockerfile中这么搞:

1
2
3
4
mongod --fork -f /etc/mongod.conf && \
mongod --shutdown -f /etc/mongod.conf && \
chown mongod:mongod /opt/lib/mongodbpath -R

这样build就顺利完成了。

可是启动这个image为container后,执行:

1
/etc/init.d/mongod start

报错:

1
 [initandlisten] warning couldn't write to / rename file /datadir/journal/prealloc.0: couldn't open file /datadir/journal/prealloc.0 for writing errno:1 Operation not permitted

虾米,明明已经加了mongod的group了。而且errorno是1,不是 "errno:13 Permission denied",有点奇怪。

问题在这里:

https://jira.mongodb.org/browse/SERVER-7583

要再加一个指令:

1
setcap cap_fowner+ep /usr/bin/mongod

就是这么折腾。

第一个AndroidApp-华容道

| Comments

第一个Android APP上线,很简单的一个小游戏:智取华容道

GooglePlay: https://play.google.com/store/apps/details?id=me.happy123.aklotski

百度应用下载地址: http://shouji.baidu.com/game/item?docid=7547918

小米商店下载地址: http://app.mi.com/detail/87656

老是对自己说,要不断学习,跟上时代浪潮。但是悲哀的发现,自己是跟的越来越吃力了。

早在大连搞电视机的时候,那时候Android刚出来,就对自己说,要好好看看。无奈之后各处辗转,这事就搁下了。

非不能也,实不为也!

过年空出来一个周,Python党也要写Android App了。

找了本 HeadFirst Java ,一天的时间扫了一遍Java的语法,写了几个小例子练练手。之后直接对着Android官方文档开干了。

流程就是 google -> 坑 -> 继续google ….,如此循环不已……

用父亲打扑克的机器,开个Eclipse基本上卡半天,本着一颗折腾的心,硬是PS出来几张背景图,小游戏<华容道>出炉啦。

图片和关卡都来自于代码发芽网,作者非常大度的授权我使用,非常感谢:

http://fayaa.com/

开发日志:

很巧的,我在知乎看到了类似”如何20天零基础开发Android游戏” 的问题。大家都是对这种问题不屑一顾的,但我从开始到完成恰好十来天,可以作为参考记录一下。

Day1

确立市场方向,要做个益智类游戏,啥好呢?啥好呢?我把所有的Android的华容道下载下来玩了一遍,嗯,都很粗糙,看来有的玩,就是它了。

这个时候,其实你已经完成一半工作了。没错,就是那句什么 决定出发的时候,旅行就完成了一半。 这个时候就不要纠结于做什么了,关键是如何做。

Day2

开始搭建开发环境,先后折腾了Android Studio和Eclipse,家里翻墙实在慢呀,另外我用父亲打扑克的机器跑Android Studio是在跑不动啊,最后装了Eclipse。推荐个链接,有兄弟收集了开发环境套装国内下载,你值得拥有。

http://www.cnblogs.com/bjzhanghao/archive/2012/11/14/android-platform-sdk-download-mirror.html

Day3

开始学习Java,神马?你都不会Java还来搞Android。嗯,我也没想到,有一天我要搞Java!要搞Java啊,我对它的印象还是航空母舰啊~~~。没办法,找了本 Head First Java 电子书,照着书里面的例子一个个敲,没错,不论懂不懂,就一个个敲。,幸亏 Head First 系列专门照顾低智商读者的,像我这样的一天敲到了300多页的例子。

Day4

不知不觉就把600页的书敲完了。嗯,看来那种xx天精通xxx,也不是骗人的,现在我的状态,估计能出去忽悠一些HR了。

Day5

先不管Android,搞一个穷人版的华容道。就开始封装三个类,什么接口啊,多态啊,统统不用,就是简单继承。搞了个核心库,棋盘就用 0011 先画出来了。嗯,最后可以玩了。不过只有我一个人懂得怎么玩。 不过很有成就感啊,看来一天写个俄罗斯方块之类的不是难事啊。

Day6

这个核心库很关键啊,挂了直接影响后面的开发啊。但是我用 0011 看的很累啊。赶紧google之,看看Java怎么搞测试~~~,好,最后集成了JUnit,顺便学了学怎么在Eclipse里面跑测试,最后写了一堆测试用例,果然发现了BUG,某些棋子竟然能对角线走动,罪过罪过。

Day7

Android程序怎么搞,现在八字还没一撇呢。热情啊,就要消耗光了。

赶紧找了本网上号称最简单的Android开发教程 第一行代码 ,再开始对着敲。没错,我就是只会这一招。

Day8

还在敲~~~,敲不完了。不是打字慢,而是电脑一开Android 手机模拟器就陷入昏睡模式,一气之下不敲了,直接接上手机开干。

Day9-Day13

游戏逻辑早写完了,我对Android App的开发印象就是:画View。没错,就是处理各种图像拉伸,各种尺寸适配,各种布局位置,各种奇葩的手机尺寸,各种API新老接口整合。

简单列举下中间遇到的坑:

  • 怎么在各种尺寸下画出一个比较漂亮的棋盘布局

  • 怎么用相对布局把几个菜单搞得整齐一点

  • 怎么PS出一个不那么生硬的背景,没错,我还同时开了Photoshop做美工,这个时候电脑已经处在超脱状态

  • 怎么在两个View直接传数据,怎么处理活动的生存周期

  • 怎么加背景音乐,怎么搞成服务,怎么能让程序退出的时候结束服务,怎么搞得好听一点,没错,这个时候我又客串DJ,研究了MP3各码率下音质和文件大小的关系,最后以专业乐评人的视角选择了一首古筝曲

  • 晕,现在为止还是只有一关呢,怎么办?我到 代码发芽 网上,写个Python脚本爬下来了所有关卡,同时邮件问作者申请授权

  • 到底是拖动棋子效果好呢,还是点击移动棋子效果好呢?我又化身PM,反反复复走最简单的一关, 十八步 ,最后确定还是点击效果好。没错,到目前为止,这个游戏我只玩通了三关,我的智商就是这样。最后我爸还解决了 横刀立马 ,我怎么也不行。

  • 发现一个重大问题,原来我一直以为只有五虎上将的,一共五横五竖十个长条棋子,突然发现有一关里面出现了魏延,我晕,再调吧

  • 又发现个问题,Android的默认sqlite模块好像没说怎么把已有的数据库集成进去,怎么办,Google吧

Day14

到各个Android市场注册账号,提交APP,等审核,之间经历若干PS工作,这也是辛苦活啊。

~~~~~

就是这样,我在各种大坑小坑瞎搞之后,瞎搞出来了。。。

结论

  • 所谓零基础xx天搞APP是可以的,但是有条件,你只是Android零基础或者Java零基础,其它编程基础还是要有的,不然期间大坑小坑肯定要浪费很多时间

  • 熟练工和初级工效率差距巨大,一天写个游戏APP不是开玩笑

  • 这样写出的APP完成度低,要加入完整的体验流程,工作量还是很大的