为了减少Image的fs layout数目,Dockerfile中经常会把多个命令集中到一个 RUN
指令下。
多行之后可读性就很差了。
有个比较偏门的写注释的方法:
1 2 3 4 5 6 7 8 9 10 11 |
|
比较实用,推荐之。
为了减少Image的fs layout数目,Dockerfile中经常会把多个命令集中到一个 RUN
指令下。
多行之后可读性就很差了。
有个比较偏门的写注释的方法:
1 2 3 4 5 6 7 8 9 10 11 |
|
比较实用,推荐之。
事情的缘起是这样的…….
想要在Dockerfile中启动一个MongoDB,之后编译为Docker image。(不要问我问什么要在docker image中存一个mongodb数据库,真实世界的需求你永远想不到)
Docker build不支持 –privileged,所以默认的/etc/init.d/mongod 这个脚本中的
1
|
|
这种写法就死翘翘了。
github上有这个Issue:
https://github.com/docker/docker/issues/1916
大家讨论了1年多,对于怎么解决,还是没有个所以然。(话说要再吐槽一下github的issue了,一般大一点的项目,一个issue跨度以年来论,长篇大论读完也不容易呀)
最后只好在Dockerfile中这么搞:
1 2 3 4 |
|
这样build就顺利完成了。
可是启动这个image为container后,执行:
1
|
|
报错:
1
|
|
虾米,明明已经加了mongod的group了。而且errorno是1,不是 "errno:13 Permission denied"
,有点奇怪。
问题在这里:
https://jira.mongodb.org/browse/SERVER-7583
要再加一个指令:
1
|
|
就是这么折腾。
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游戏” 的问题。大家都是对这种问题不屑一顾的,但我从开始到完成恰好十来天,可以作为参考记录一下。
确立市场方向,要做个益智类游戏,啥好呢?啥好呢?我把所有的Android的华容道下载下来玩了一遍,嗯,都很粗糙,看来有的玩,就是它了。
这个时候,其实你已经完成一半工作了。没错,就是那句什么 决定出发的时候,旅行就完成了一半
。 这个时候就不要纠结于做什么了,关键是如何做。
开始搭建开发环境,先后折腾了Android Studio和Eclipse,家里翻墙实在慢呀,另外我用父亲打扑克的机器跑Android Studio是在跑不动啊,最后装了Eclipse。推荐个链接,有兄弟收集了开发环境套装国内下载,你值得拥有。
http://www.cnblogs.com/bjzhanghao/archive/2012/11/14/android-platform-sdk-download-mirror.html
开始学习Java,神马?你都不会Java还来搞Android。嗯,我也没想到,有一天我要搞Java!要搞Java啊,我对它的印象还是航空母舰啊~~~。没办法,找了本 Head First Java
电子书,照着书里面的例子一个个敲,没错,不论懂不懂,就一个个敲。,幸亏 Head First
系列专门照顾低智商读者的,像我这样的一天敲到了300多页的例子。
不知不觉就把600页的书敲完了。嗯,看来那种xx天精通xxx,也不是骗人的,现在我的状态,估计能出去忽悠一些HR了。
先不管Android,搞一个穷人版的华容道。就开始封装三个类,什么接口啊,多态啊,统统不用,就是简单继承。搞了个核心库,棋盘就用 0011 先画出来了。嗯,最后可以玩了。不过只有我一个人懂得怎么玩。 不过很有成就感啊,看来一天写个俄罗斯方块之类的不是难事啊。
这个核心库很关键啊,挂了直接影响后面的开发啊。但是我用 0011 看的很累啊。赶紧google之,看看Java怎么搞测试~~~,好,最后集成了JUnit,顺便学了学怎么在Eclipse里面跑测试,最后写了一堆测试用例,果然发现了BUG,某些棋子竟然能对角线走动,罪过罪过。
Android程序怎么搞,现在八字还没一撇呢。热情啊,就要消耗光了。
赶紧找了本网上号称最简单的Android开发教程 第一行代码
,再开始对着敲。没错,我就是只会这一招。
还在敲~~~,敲不完了。不是打字慢,而是电脑一开Android 手机模拟器就陷入昏睡模式,一气之下不敲了,直接接上手机开干。
游戏逻辑早写完了,我对Android App的开发印象就是:画View。没错,就是处理各种图像拉伸,各种尺寸适配,各种布局位置,各种奇葩的手机尺寸,各种API新老接口整合。
简单列举下中间遇到的坑:
怎么在各种尺寸下画出一个比较漂亮的棋盘布局
怎么用相对布局把几个菜单搞得整齐一点
怎么PS出一个不那么生硬的背景,没错,我还同时开了Photoshop做美工,这个时候电脑已经处在超脱状态
怎么在两个View直接传数据,怎么处理活动的生存周期
怎么加背景音乐,怎么搞成服务,怎么能让程序退出的时候结束服务,怎么搞得好听一点,没错,这个时候我又客串DJ,研究了MP3各码率下音质和文件大小的关系,最后以专业乐评人的视角选择了一首古筝曲
晕,现在为止还是只有一关呢,怎么办?我到 代码发芽
网上,写个Python脚本爬下来了所有关卡,同时邮件问作者申请授权
到底是拖动棋子效果好呢,还是点击移动棋子效果好呢?我又化身PM,反反复复走最简单的一关, 十八步
,最后确定还是点击效果好。没错,到目前为止,这个游戏我只玩通了三关,我的智商就是这样。最后我爸还解决了 横刀立马
,我怎么也不行。
发现一个重大问题,原来我一直以为只有五虎上将的,一共五横五竖十个长条棋子,突然发现有一关里面出现了魏延,我晕,再调吧
又发现个问题,Android的默认sqlite模块好像没说怎么把已有的数据库集成进去,怎么办,Google吧
到各个Android市场注册账号,提交APP,等审核,之间经历若干PS工作,这也是辛苦活啊。
~~~~~
就是这样,我在各种大坑小坑瞎搞之后,瞎搞出来了。。。
所谓零基础xx天搞APP是可以的,但是有条件,你只是Android零基础或者Java零基础,其它编程基础还是要有的,不然期间大坑小坑肯定要浪费很多时间
熟练工和初级工效率差距巨大,一天写个游戏APP不是开玩笑
这样写出的APP完成度低,要加入完整的体验流程,工作量还是很大的
javascript 里面的继承是个非常复杂的话题,一言蔽之,就是你要替解释器干点活。另外,javascript属于使用原型式继承的语言,这个比较少见,所以直觉上不好拐弯。
先回顾比较简单的办法
1 2 3 4 5 6 7 8 9 10 11 |
|
好,下面定义一个它的子类
1 2 3 4 5 6 7 8 |
|
容易费解的是这两行:
1 2 |
|
javascript中,每个对象都有一个原型对象,在创建一个对象时,javascript会自动将其原型对象设置为其构造函数的prototype属性所指的对象。 在访问对象的某个成员时,如果这个成员未见于当前对象,那么javascript会沿着原型链向上逐一访问每个原型对象(最顶端为Object.prototype对象),直到找到这个成员为止。 这意味着,为了让一个类继承另一个类,只需将子类的prototype设置为基类的一个实例即可。
第二行将prototype的constructor属性重新设置为Author。是因为: 定义一个构造函数时,其默认的prototype对象是一个Object类型的实例,其contructor属性会被设置为构造函数本身。如果手工将prototype设置为另一个对象,就要重新设置其constructor属性。
最后,为了简化类的声明,可以将这些工作封装在extend函数中:
1 2 3 4 5 6 |
|
作为改进,定义了一个新对象F,避免基类对象过大,创建实例浪费资源。
但是这样还有个小缺点,声明 Author的时候,还要显式的调用一下Person.call()
,下面这个版本进一步做了改进:
1 2 3 4 5 6 7 8 9 10 11 |
|
增加了一个superclass属性来直接访问基类,这样声明Author的时候可以这么写:
1 2 3 4 5 6 7 |
|
TODO
整理一下经常忘记的Git命令
1 2 3 4 |
|
1 2 3 4 5 6 |
|
假设这样一种情况:
1
|
|
在git中重命名远程分支,其实就是先删除远程分支,然后重命名本地分支,再重新提交一个远程分支
1 2 3 |
|
1
|
|
1
|
|
branches/A 上修改了一个文件A.h,新增了一个文件B.h,删除了一个文件C.h。
1 2 3 4 5 6 7 |
|
参考:http://git-scm.com/docs/git-rebase
只显示两个分支间的差异,如果你想找出‘master’,‘test’的共有 父分支和’test’分支之间的差异,你用3个‘.’来取代前面的两个’.’ 。
1
|
|
显示你当前的索引和上次提交间的差异;这些内容在不带”-a”参数运行 “git commit”命令时就会被提交。
1
|
|
显示你工作目录与上次提交时之间的所有差别,这条命令所显示的 内容都会在执行”git commit -a”命令时被提交。
1
|
|
如果你要查看当前的工作目录与另外一个分支的差别,你可以用下面的命令执行: 这会显示你当前工作目录与另外一个叫’test’分支的差别。你也以加上路径限定符,来只 比较某一个文件或目录。
1
|
|
显示你当前工作目录下的lib目录与上次提交之间的差别(或者更准确的 说是在当前分支)。
1
|
|
如果不是查看每个文件的详细差别,而是统计一下有哪些文件被改动,有多少行被改 动,就可以使用‘–stat’ 参数。
1
|
|
最简单的办法就是按传统方法创建一个类,用一个函数来做其构造器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
用setattr,getattr等赋值取值方法及命名规范区别私有成员
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 |
|
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 |
|
这里应用了js的闭包特性,isbn等属性不再通过this
来引用,而是放到函数的构造器里面。既要访问到私有成员,又要对外的方法放到函数的构造中,对私有成员没有依赖的函数用prototype。
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 |
|
这里和闭包实现私有成员
的区别就在于构造函数变成了一个内嵌函数,这样就创建了一个闭包,可以把静态的私有成员声明在最顶层。
常量就设置为一个私有静态属性,用大写区分即可。我认为没有必要实现一个取值器去限制,用CONST前缀从代码风格上约束即可。
javascript中有三种原始类型:布尔型、数值型(不区分浮点数和整数)和字符串型。
此外,还有对象类型和包含可执行代码的函数类型。前者是一种复合类型(数组是一种特殊的对象)。
最后,还有空类型(null)和未定义类型(undefined)。
原始数据类型按值传送,其他数据类型则按引用传送。
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 |
|
作用域、嵌套函数和闭包
js中,只有函数具有作用域:
在一个函数内部声明的变量,外部无法访问; 定义在一个函数中的变量在该函数的内嵌函数中是可以访问的
js中的作用域是词法性的:
函数运行在定义他们的作用域中,而不是调用他们的作用域中; 可以利用这个特性定义静态方法和属性;
接口也是一种对象,判断一个类是否是实现了某类接口,就是传入这个接口,而后比较。
java有专门的接口类,C++有虚基类,而C在linux kernel中的对象设计方法实际上也是一种接口实现,这都是接口在语言层面支持的体现
封装(encapsulation)和信息隐藏:信息隐藏是目的,而封装则是藉以达到这个目的的技术
java和C++有 private关键字作为支持,Python有’__‘的命名约定,js中一般用闭包来模拟
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 |
|
约定所有类明确声明实现了那些接口,和这些类打交道的对象可以针对这些声明做检查。
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 |
|
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 46 47 48 49 |
|
用macvtap模拟网卡时,用tcpdump抓包是抓不到的,后来发现3.14版本以上的内核修正了这一点。
参考这个提交:
https://github.com/torvalds/linux/commit/6acf54f1cf0a6747bac9fea26f34cfc5a9029523
折腾了半天,原始出处不知道了,转记一下。
比如如果一个linux服务器有三个口接三个不同的网络,假设对应的网络信息是如此
eth0是电信,ip地址为1.1.1.1/24,电信网关为1.1.1.254
eth1是网通,ip地址为2.2.2.2/24,网通网关为2.2.2.254
eth2是教育网,ip地址为3.3.3.3/24,教育网网关为3.3.3.254
传统情况下,如果是为了从内向外访问获得更好的速度,让访问电信走电信,访问网通走网通,那么配置是网关只能够配置一个。
比如以电信为主的,那么网关就只设置电信的1.1.1.254,而针对网通和教育网设置不同的路由,路由下一跳指向网通和教育网对应的 网关。
如果这样做的目的只是实现内部访问外面,那么是没问题了,但是如果是为了让外面的用户能够正常访问到服务器上的服务就会出问题。比如电信用户会无法访问网通和教育网的ip,网通用户会无法访问电信和教育网的ip。
要解决这个问题,思路就是由哪个网口进来的流量希望全部就由哪个回去。用lartc里面提到的方法就是来源的口不同,走不同的路由表。在默认的路由表基础上再建立三个路由表。
用 ip route show 可以看到默认有local,main,default三个路由表,这三个路由表的名称命名来自 /etc/iproute2/rt_tables ,这里先在这个配置文件里面添加三个不同的路由表表名,
1 2 3 |
|
之后建立这三个路由表的内容,因为这三个路由表的只是用来响应来自不同接口的,而不是用来相应从哪个接口出去的,所以只需要每个路由表里面建立默认网关即可。
1 2 3 |
|
之后再加上三条规则,使来自不同的口的走不同的路由表
1 2 3 |
|
至此无论是电信还是网通还是教育网用户,访问三个ip的任意一个地址都能够连通了。即便是服务器上本身的默认路由都没有设置,也能够让外面的用户正常访问。
命令汇总:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
libpcap为了提高效率,调用setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,(void *) &req, sizeof(req))
时采用kmalloc分配内存。
可以参考:
https://www.kernel.org/doc/Documentation/networking/packet_mmap.txt
kmalloc底层依赖linux的slab内存分配机制,在2.6.22内核之后,slub取代slab成为默认的内存分配器。空间和时间上都有所提升。值得升级。
另外,centos5.9默认采用的2.6.18内核,编译的时候默认的KMALLOC_MAX_SIZE 设置为size-131072,这对于有很大内存的机器,分配效率是不高的。
最简单的办法就是用rpm包升级到2.6.33.9-rt31.86.el5rt,这个内核编译的时候已经将KMALLOC_MAX_SIZE设置为size-4194304。
这个问题是追踪libpcap的抓包程序,内存分配频繁失败发现的。
只能说,内核升级频繁,很多编译开关影响很大,要想全面发挥linux的性能,只能紧跟潮流啊。