February 2010

pmap : 理解linux的进程内存占用

看了几篇文章,对linux的进程的内存占用,又有了一点认识,记录一下。

首先 ps 看一下我的系统跑着哪些process

$ ps aux
 
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
...
czbug     1980  0.0  1.7 180472 34416 ?        Sl   Feb25   0:01 /usr/bin/yakuake
...

我拿 yakuake 这个小程序作例子。

其中,关于内存的是 VSZ 和 RSS 这两个

man ps 看看它们的含义:

rss       RSS    resident set size, the non-swapped physical memory that a task has used (in kiloBytes). (alias rssize, rsz).

vsz       VSZ    virtual memory size of the process in KiB (1024-byte units). Device mappings are currently excluded; this is subject to change. (alias vsize).

简单一点说,RSS 就是这个process 实际占用的物理内存,VSZ 就是process 的虚拟内存,就是process 现在没有使用但未来可能会分配的内存大小。

其实这里的ps 出来的结果,是有点不正确的,如果把所有程序的 RSS 加起来,恐怕比你的实际内存还要大呢。为什么呢??因为 ps 的结果,RSS 那部分,是包括共享内存的。这里我用 pmap 来看看。

$ pmap -d 1980
 
1980:   /usr/bin/yakuake
Address   Kbytes Mode  Offset           Device    Mapping
00110000    2524 r-x-- 0000000000000000 008:00002 libkio.so.5.3.0
00387000       4 ----- 0000000000277000 008:00002 libkio.so.5.3.0
00388000      32 r---- 0000000000277000 008:00002 libkio.so.5.3.0
00390000      16 rw--- 000000000027f000 008:00002 libkio.so.5.3.0
00394000     444 r-x-- 0000000000000000 008:00002 libQtDBus.so.4.5.2
00403000       4 ----- 000000000006f000 008:00002 libQtDBus.so.4.5.2
00404000       4 r---- 000000000006f000 008:00002 libQtDBus.so.4.5.2
00405000       4 rw--- 0000000000070000 008:00002 libQtDBus.so.4.5.2
00407000     228 r-x-- 0000000000000000 008:00002 libkparts.so.4.3.0
00440000       8 r---- 0000000000039000 008:00002 libkparts.so.4.3.0
00442000       4 rw--- 000000000003b000 008:00002 libkparts.so.4.3.0
00443000    3552 r-x-- 0000000000000000 008:00002 libkdeui.so.5.3.0
007bb000      76 r---- 0000000000377000 008:00002 libkdeui.so.5.3.0
007ce000      24 rw--- 000000000038a000 008:00002 libkdeui.so.5.3.0
007d4000       4 rw--- 0000000000000000 000:00000   [ anon ]
....
mapped: 180472K    writeable/private: 19208K    shared: 20544K

我略去了一部分输出,都是差不多的,重点在最后那行输出。

linux 会把一些shared libraries 载入到内存中,在pmap 的输出中,这些shared libraries 的名字通常是 lib*.so 。如 libX11.so.6.2.0 。这个 libX11.so.6.2.0 会被很多process load 到自己的运行环境中,同时,ps 输出的RSS 结果中,每个process 都包含了这个libX11.so.6.2.0 ,而事实上它只被load 了一次,如果单纯把ps 的结果相加,这样就重复计算了。

而 pmap 的输出中,writeable/private: 19208K ,这个就是yakuake 这个程序真正占用的物理内存,不包含shared libraries 。在这里,它只有19208K,而ps 的RSS 是34416K。

————————————————————–

我在看这方面的资料时,还看到一些关于virtual memory 的,再记录下。

以下两个命令均可查看 vmsize 。

$ cat /proc/<pid>/stat | awk '{print $23 / 1024}'
$ cat /proc/<pid>/status | grep -i vmsize

一般来说,得出来的值,是和 ps 的 VSZ 是一样的,但有一种情况例外,就是查看X server 的时候。

举个例:

$ ps aux|grep /usr/bin/X|grep -v grep | awk '{print $2}'   # 得出X server 的 pid   ...
1076
 
$ cat /proc/1076/stat | awk '{print $23 / 1024}'
139012
 
$ cat /proc/1076/status | grep -i vmsize
VmSize:      106516 kB

而 ps 的 VSZ 为 106516 ,与后者是一致的。

据说是因为

VmSize = memory + memory-mapped hardware (e.g. video card memory).

这句话我不是很理解。。。就不作解释了。。。

对OS 的理解还很肤浅,还需努力啊。。。

Guy Ritchie’s Sherlock Holmes 小影评

看罢 Guy Ritchie 的新片<Sherlock Holmes>,装B影评一下。

首先知道 Guy Ritchie 此人,来自于他的<Lock, Stock and Two Smoking Barrels> ,经典之作,令我回味无穷,他才是真正在玩电影。那种英式口音,摇滚乐,也是他风格的一部分。

然后就是 <Snatch.>,明显承继了两杆大烟枪的风格及手法,但后者毕竟是出山之作,演员成本较低,前者则有了Brad Pitt 的加盟,相当不错的。

但这次的<Sherlock Holmes> 就没有了当初的惊艳,但同样是极具风格之作。偏暗的主题色调,苏格兰场的配乐,同样重的英式口音,还有最重要的剪切,虽然颠覆了原著角色,但塑造了自己风格的一个福尔摩斯。虽然戏中仍然运用了科学去解释了罪案,但整部戏还是偏重于武戏,所以5分为满分的话,我给4分!

其中我最喜欢的,就是开场打倒混混守卫和拳击比赛那段,用画外音去描述下一步动作,并慢动作演示一遍,非常有趣,呵呵。期待第二集!

重新上路!

以前的.me 域名,实在太山寨了,呵呵。

今天心情特佳,换了个域名,顺便换了个wp的theme,重新上路!

Hello 是我用了多年的QQ昵称,本来想用个 hellosa.net 或 hellosa.org 的域名的,谁知道已经被 @wuzhez 同学注册去了。。。而且他本人也情有独钟,呵呵,那么我也就换一个咯。

用css实现点击链接时不显示虚线框

在html上一直是个小白,以前初上网的时候觉得挺好玩的,但年幼无知就没学下去,只知道一点皮毛。。。

一直觉得 twitter 的UI 做得好,举个例,点击链接时,周围的那个虚线框不显示!!哈哈,没错,我今天才知道如何实现,小白吧,哈哈!!

用 css 实现的话,挺简单的,加一个

a {
outline: none;
}

就可以了。

好,我就不负责任地改一下!把我的style.css 加了一段:

body a {
outline: none;
}

呵呵,好像成功了,美观了一点了,哈哈。

至于 ie,貌似是不同的,那我也不管了。。。反正我极少使用ie 的,今天也是第二次使用ie6 开我的 blog ,好像乱了。。。这个去掉虚线框的效果也不奏效。。。算了,我都不管 ie 的。。。

ntpdate(no server suitable for synchronization found)

今天维护一个集群系统时,被人报障说集群的机器时间不对。。。我去看了一下,crontab 里有对时的命令啊。再手动执行一下,才发现,原来被我设的防火墙给墙住了。。。机器只允许特定的外网ip访问,内网无限制。。。所以ntpdate 外面一些对时服务器的时候,根本不会收到返回了。

话说这个防火墙,也是其它部门的同事建议我设的,本部门的程序员对安全这些事情好不上心的,专心于系统功能的开发,甚至连我多次建议的系统管理经验也不采纳。算了,none of my business 。

而他们说这个系统对时,很急,要不集群间的机器heartbeat 时间不对,就会以为对方挂了的了。

那我就马上在另一台对外网无限制的机器上搭一个ntpd ,就作为一个对时服务器的代理吧。

安装ntpd,这个很简单,那台机器是 centos 5,那就用yum。

#yum install ntp

装好还不能用呢,最快速度使用上的话,那就只修改一行配置,因为默认是只允许本地对时而已,我们必须加上内网都可以对时

#vi /etc/ntp.conf

把下面这行,取消注释,并加上自己网段的相关信息即可

#restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap

如:

restrict 10.100.20.0 mask 255.255.255.0 nomodify notrap

然后重启ntp

/etc/init.d/ntpd restart

重启成功后,如果你立刻想对时的话,是会报错的,如:

#ntpdate 10.100.20.59 # 就是我刚配的ntpd server
11 Feb 00:37:36 ntpdate[22276]: no server suitable for synchronization found

这种错误,应该是没有ntpd server 才会报的啊,究竟为什么呢??

原来,如果ntpd server 没有进行过对时的话,也是会报这个错的。。。很汗,为什么不写得明白一点呢??

好了,既然知道原因,只需要等待数分钟,让我的ntpd server 10.100.20.59 自己去对了一次时后,我们再操作,就会成功的了。

# ntpdate 10.100.20.59
11 Feb 00:41:30 ntpdate[22323]: adjust time server 10.100.20.59 offset -0.005792 sec

svn update 时出错(Valid UTF-8 data)

今天svn up的时候,发现一个报错:

#svn up
svn: Valid UTF-8 data
(hex:)
followed by invalid UTF-8 sequence
(hex: a1 b0)

突然爆出的错误。。。google 了一下,这个比较靠谱

http://ryanerwin.com/2007/04/09/valid-utf-8-data-hex-followed-by-invalid-utf-8-sequence/

大意是说,你的svn工作目录,有了一个不能由当前系统的字符集识别的文件。
解决方式是:删了这些文件。

ok,那我去删咯,确实有一个目录下,有一个?????????????? 的文件,gbk 编码的文件。。。

怎么出现的呢??不会是被某位大哥黑进来的吧,哈哈。

不追查了,就当是跑脚本失败生成的。删去,问题解决了!

nginx proxy_pass 里的”/”

见配置,摘自nginx.conf 里的server 段:

server {
listen 80;
server_name abc.163.com ;
location / {
proxy_pass http://ent.163.com/ ;
}
location /star/ {
proxy_pass http://ent.163.com ;
}
}

里面有两个location,我先说第一个,/ 。其实这里有两种写法,分别是:

location / {
proxy_pass http://ent.163.com/ ;
}
location / {
proxy_pass http://ent.163.com ;
}

出来的效果都一样的。

第二个location,/star/。同样两种写法都有,都出来的结果,就不一样了。

location /star/ {
proxy_pass http://ent.163.com ;
}

当访问 http://abc.163.com/star/ 的时候,nginx 会代理访问到 http://ent.163.com/star/ ,并返回给我们。

location /star/ {
proxy_pass http://ent.163.com/ ;
}

当访问 http://abc.163.com/star/ 的时候,nginx 会代理访问到 http://ent.163.com/ ,并返回给我们。

这两段配置,分别在于, proxy_pass http://ent.163.com/ ; 这个”/”,令到出来的结果完全不同。

前者,相当于告诉nginx,我这个location,是代理访问到http://ent.163.com 这个server的,我的location是什么,nginx 就把location 加在proxy_pass 的 server 后面,这里是/star/,所以就相当于 http://ent.163.com/star/。如果是location /blog/ ,就是代理访问到 http://ent.163.com/blog/。

后者,相当于告诉nginx,我这个location,是代理访问到http://ent.163.com/的,http://abc.163.com/star/ == http://ent.163.com/ ,可以这样理解。改变location,并不能改变返回的内容,返回的内容始终是http://ent.163.com/ 。 如果是location /blog/ ,那就是 http://abc.163.com/blog/ == http://ent.163.com/ 。

这样,也可以解释了上面那个location / 的例子,/ 嘛,加在server 的后面,仍然是 / ,所以,两种写法出来的结果是一样的。

PS: 如果是 location ~* ^/start/(.*)\.html 这种正则的location,是不能写”/”上去的,nginx -t 也会报错的了。因为,路径都需要正则匹配了嘛,并不是一个相对固定的locatin了,必然要代理到一个server。

apache rewrite 与linux软链的一个小问题

一个项目是apache+resin的架构,有一条 rewrite 规则是这样的:

RewriteRule ^/flashinfo/vinfo/([a-z0-9A-Z_]+).xml$ /video/videolist.htm?sid=$1 [PT,L]

其中,\.htm 交给resin处理

<LocationMatch (.*)\.htm>
SetHandler caucho-request
</LocationMatch>

理论上,访问 /flashinfo/vinfo/V5OJEFN7C.xml 文件,是会代理访问到 /video/videolist.htm?sid=V5OJEFN7C 的。

但事实上,却403了,如下:

$curl -I -H host:so.v.test.com http://127.0.0.1/flashinfo/vinfo/V5OJEFN7C.xml
HTTP/1.1 403 Forbidden
Date: Tue, 09 Feb 2010 07:29:30 GMT
Server: Apache/2.2.11 (Unix) Resin/3.0.26
Content-Type: text/html; charset=iso-8859-1

让我看看rewrite后的访问是否正常:

$curl -I -H host:so.v.test.com http://127.0.0.1/video/videolist.htm?sid=V5OJEFN7C
HTTP/1.1 200 OK
Date: Tue, 09 Feb 2010 07:33:23 GMT
Server: Apache/2.2.11 (Unix) Resin/3.0.26
Cache-Control: max-age=600
Expires: Tue, 09 Feb 2010 07:43:23 GMT
Content-Type: text/html

究竟什么原因呢??我看了一下,应该是这样的:

原因在于,在DocumentRoot下,有一个错误的软链video.

$ls -alh| grep video
lrwxrwxrwx  1 root root   29 02-09 15:29 video -&gt; /data/videopage

而/data/videopage这个目录是不存在的,所以video是一个错误的软链,rewrite 后的地址是 /video/videolist.htm?sid=$1 ,这样就爆403了。

真奇怪,其实apache 根本不用管我有没有video 这个目录的,因为都是转发到resin 去处理的了。既然想不通,就先记下。。。

我还做了两个测试:

1,让 video 成为一个正确的软链,curl 测试结果,200 。

2,把 video 删去,不存在这个软链,curl 测试结果,200。

————————————

结论:apache rewrite 后的地址,如 /data/dopost.jsp?sid=$1 这种,如果data 是一个错误的软链,尽管动态程序/data/dopost.jsp?sid=$1是正确的,apache 的 rewrite 都会不成功,返回 403 。如果 data 是一个正确的软链或者压根不存在,apache 正确地rewrite 。

当squid遇上502 bad gateway

测试环境:

192.168.1.1 (squid) , 192.168.1.2 (nginx proxy) , 192.168.1.3 (nginx web)

squid 作为最外层的代理;nginx proxy 作为第二层代理,通过upstream访问后台;nginx web 真正的数据后台web server。

测试开始:

$curl -I -H host:blog.lazybug.me http://192.168.1.1/test.html
 
HTTP/1.0 200 OK
Server: nginx/0.8.32
Date: Mon, 08 Feb 2010 18:11:48 GMT
Content-Type: text/html; charset=GBK
Expires: Mon, 08 Feb 2010 18:12:58 GMT
Cache-Control: max-age=70
X-Cache: MISS from proxy.lazybug.me
X-Cache-Lookup: HIT from proxy.lazybug.me:80
Via: 192.168.1.3.nginx, 1.1 proxy.lazybug.me:80 (squid/2.7.STABLE7)
Connection: close

此时, user -> squid -> nginx proxy -> nginx web

此时,这个页面已经被缓存住,往后的访问都是TCP_MEM_HIT的了。等到页面过期后,我把nginx web 后台弄挂,我在这里是直接把nginx proxy的upstream给改了,改为 192.168.1.4。此时,访问nginx proxy

$curl -I -H host:blog.lazybug.me http://192.168.1.2/test.html
 
HTTP/1.1 502 Bad Gateway
Server: nginx/0.8.32
Date: Mon, 08 Feb 2010 18:28:06 GMT
Content-Type: text/html
Content-Length: 173
Connection: keep-alive

因为根本没有192.168.1.4这个ip,肯定bad gateway了。

但此时访问squid

$curl -I -H host:blog.lazybug.me http://192.168.1.1/test.html
 
HTTP/1.0 200 OK
Server: nginx/0.8.32
Date: Mon, 08 Feb 2010 18:11:48 GMT
Content-Type: text/html; charset=GBK
Expires: Mon, 08 Feb 2010 18:12:58 GMT
Cache-Control: max-age=70
Age: 1004
Content-Length: 0
X-Cache: HIT from proxy.lazybug.me
X-Cache-Lookup: HIT from proxy.lazybug.me:80
Via: 192.168.51.3.nginx, 1.1 proxy.lazybug.me:80 (squid/2.7.STABLE7)
Connection: close

squid 仍然返回200,不过并不是立刻返回,而是经过了几秒才返回,因为此时squid认为请求页面过期,正在尝试去后端取新数据,但此时,后端返回一个502 bad gateway,那它的工作机制就是,返回旧的缓存数据给用户。

看一下squid的access.log,写着TCP_REFRESH_FAIL_HIT。查一下手册,如下:

An expired copy of the requested object was in the cache. Squid attempted to make an If-Modified-Since request, but it failed. The old (stale) object was delivered to the client.

如果 squid 没有缓存到页面,而出现502,squid 会不会返回200呢??测试下

清缓存:
squidclient -p 80 -m purge http://blog.lazybug.me/test.html

然后再次访问:

$curl -I -H host:blog.lazybug.me http://192.168.1.1/test.html
 
HTTP/1.0 502 Bad Gateway
Server: nginx/0.8.32
Date: Tue, 09 Feb 2010 18:17:13 GMT
Content-Type: text/html
Content-Length: 173
X-Cache: MISS from proxy.lazybug.me
X-Cache-Lookup: HIT from proxy.lazybug.me:80
Via: 1.1 proxy.lazybug.me:80 (squid/2.7.STABLE7)
Connection: close

呵呵,不出所料。

———————————————————————

结论:squid 作为前端代理,而后端502的话,如果squid已经缓存住的页面,那squid就返回用户旧的数据,如果squid没有缓存住的话,很遗憾,还是会502的。