Category Archives: Linux

Mac 安装cscope编译问题解决办法

今天晚上在Mac上安装cscope插件时,碰到一个编译问题。虽然最近在编译一个C++工程时也碰到不少编译的问题,但是对于今天碰到的这个问题,还是第一次碰到。具体情况如下:

在编译cscope-15.7a版本的代码,make这一步时抛出如下错误

In file included from build.c:50:
/usr/include/ncurses.h:539:40: error: macro “cbreak” passed 1 arguments, but takes just 0
/usr/include/ncurses.h:564:44: error: macro “erasechar” passed 1 arguments, but takes just 0
/usr/include/ncurses.h:600:43: error: macro “killchar” passed 1 arguments, but takes just 0
make[2]: *** [build.o] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2

于是grep一下cscope的源码,找到constants.h中含有这几个方法。代码如下:

#if (BSD || V9) && !__NetBSD__ && !__FreeBSD__
# define TERMINFO 0 /* no terminfo curses */
#else
# define TERMINFO 1
#endif

#undef TERMINFO 0
#define TERMINFO 1

#if !TERMINFO
# ifndef KEY_BREAK
# define KEY_BREAK 0400 /* easier to define than to add #if around the use */
# endif
# ifndef KEY_ENTER
# define KEY_ENTER 0401
# endif
# ifndef KEY_BACKSPACE
# define KEY_BACKSPACE 0402
# endif

# if !sun
# define cbreak() crmode() /* name change */
# endif

# if UNIXPC
# define erasechar() (_tty.c_cc[VERASE]) /* equivalent */
# define killchar() (_tty.c_cc[VKILL]) /* equivalent */
# else
# define erasechar() (_tty.sg_erase) /* equivalent */
# define killchar() (_tty.sg_kill) /* equivalent */
# endif /* if UNIXPC */
#endif /* if !TERMINFO */

看这段代码,只要让TERMINFO为1,即可不使用这几个函数。于是加上上面蓝色的两行,即可通过编译。

gdb初试小结

最近在搞一个C++的工程,终于有机会使用神往已久的gcc gdb make等套件了。今天在让老大帮忙解决一个问题时,被手把手地教着怎么用gdb。作为命令行下的debug工具,真是让我大开眼界了。 下面总结一下今天调试过程中使用gdb的一些基础命令:

== gdb ==

* 启动:
gdb ./bin/nginx

* 设置参数
set args -s reload

* 运行程序
r (run)

* 设置断点
** 在代码行上设置断点
b xxx.cpp:117 (break)

** 在代码方法上设置断点
b star::PManager::load
star 表示使用PManager时申明的namespace名称,PManager表示被调用的类,load 指调用的方法, 保证可以找到代码执行唯一的地方
如果某个函数被重载,也可以直接使用上述方法,gdb会自动关联到程序实际执行的那个函数。

* 查看断点信息
info break

* 单条执行
n (next)

* 执行到下一断点
c (continue)

* 打印出程序中变量的值
p (print)

* 自动显示变量
display  field
该功能类似于Intellij IDEA中的watch,每一步执行都会将这个指定变量打出,在debug 观察for循环中的某个值时,非常有用。

* 删除显示的变量
delete display

* 查看函数棧
bt

* 退出函数
finish

* 退出GDB
q

Ubuntu访问Windows共享目录

今天碰到一个需求,需要在Linux命令行下访问Windows共享目录,简单Google了一下,解决问题。记录一下,备查。

1、安装Ubuntu支持smbfs的包

sudo apt-get install smbfs

2、创建一个目录,用于挂载Windows共享目录

sudo mkdir /mnt/smb

3、将Windows共享目录mount到/mnt/smb目录

sudo mount -t smbfs -o username=guest //192.168.10.34/tools /mnt/smb
其中username 为windows共享目录的访问用户
4、卸载Windows共享目录

sudo umount /mnt/smb

top命令显示的VIRT列详解

在Linux下使用top命令查看进程时,经常可以发现Java应用的虚拟内存(即VIRT这一列)占用很高,如下:

PID   USER   PR   NI   VIRT     RES     SHR    S   %CPU  %MEM TIME+    COMMAND
5626  admin  20   0     9009m  496m   7072   S     1.8        6.3        355:00.79     java

这个VIRT代表啥意思呢?昨天看过StackOverFlow一条问题的解释后,这块算是彻底弄明白了。
上面的几列中,RES表示进程实际使用的内存,如果这个值很大则表示使用了大量实际内存,需要引起注意。
而VIRT的具体解释如下:
The total amount of virtual memory used by the task. It includes all code,data and shared libraries plus pages that have been swapped out.
这段解释的意思是VIRT表示进程所有使用过的代码,数据,共享库等等,这其中的许多数据或许已经从内存交换到硬盘上面,很少使用了。
使用pmap pid 可以显示出这个进程曾经使用过的虚拟内存映射。rwx–表示一般的数据空间,r-x–表示常驻磁盘的数据。
具体pmap的详细解释还是得翻看一下man文档。

Vim替换小技巧

用Vim很长时间了,但是面对这个牛B的编辑器,始终不敢说熟悉Vim。最近就碰到几个靠Google才搞定的问题,特记录之。

  • Vim正则表达式匹配中文字符:[^\x00-\xfff],同理可以得出匹配非中文字符的正则表达式了:[\x00-\xfff],配置出来后就很容易做替换了。
  • 利用Vim替换文件中的英文的大小写
    • 将文件全部大写字符替换成小写字符: ggguG ,即可,开始的gg是将光标移动到文件开头,gu是预转换为小写,G是将光标移动到最后一行。
    • 将某行替换掉, nGgu<回车> n为行号,G表示跳转到该行号去,gu表示预转换,回车表示移动到下一行。

很好的awk教程

接触到awk已经有好几年了,但是一直只是了解一些皮毛,经常碰到一些情况挺抓狂。之前也尝试着系统学习一下,但是许多的教程要不太简单,要么写得不那么好理解。最近终于找到一个很好的awk教程,把awk主要的一些东西讲得非常清晰。提供了通过许多的例子,简洁明了。

Exercise #1: Learning awk Basics

Exercise #2: Learning awk with Operators

Exercise #3:Using awk with Print and Printf

Exercise #4: Starting with awk Scripts

Exercise #5: Managing the Structure of the awk file

Exercise #6: Set Variables in Scripts

Exercise #7: Multiple Field Separators

Exercise #8: Counting and Sums with awk

Exercise #9: Output/Input Redirection With awk

using-variables-with-awk

 

Nginx连接JBoss碰到的问题

最近在做Nginx+JBoss的性能测试,目标是通过性能测试的结果与Apache + JBoss进行比较,看看是不是有必要用Nginx替换Apache。目前Nginx+JBoss的方式采用的是pass_proxy的方式。从当前的测试结果来看,性能比Apache+JBoss有不小的提升。今天测试时碰到了一个有趣的问题,在Nginx专家叔度的协助下很快地解决了,也明白Nginx作为Proxy与后端服务交互的原理,是以为记。

今天试图配置JBoss nio(其实就是tomcat6.0中的nio)的模式进行性能测试,修改好Connecter的配置之后发现访问页面非常慢。于是测试通过8080端口直接访问JBoss,发现页面打开很快,因此可以得出问题出在Nginx与Jboss之间。于是找到我厂的Nginx专家帮忙排查,不一会专家就找出了问题的原因,打来电话给我解决。原来在修改Jboss nio配置时默认采用的是HTTP1.1协议,还默认开启了keepalive,而Nginx作为reverse proxy只支持HTTP1.0协议。Nginx在与后端Server交互时,采用HTTP1.0的模式,认为每个连接关闭才算请求完成,而后端server使用了keepalive,所以Nginx一直等到后端的这个keepalive连接关闭才返回给浏览器,所以访问页面非常慢。

问题根源找到了,修改起来就很快了,参照http://tomcat.apache.org/tomcat-6.0-doc/config/http.html文档,将maxKeepAliveRequest=1,关闭keepalive。重启jboss后,问题解决。

一点感想,学习Nginx还是得弄明白其内部处理原理,否则只能悲剧,无奈目前市面上的书多是讲述如何配置,对于这些原理机制所述甚少。

Nginx作为Jboss proxy的配置

最近开始深入了解一下Nginx的使用,因为未来工作中需要用到这个东西。在Mac下直接可以通过Macport进行安装,安装完之后在启动命令在/opt/local/sbin/下,配置文件在/opt/local/etc/nginx/目录下,nginx.conf里面配置的是相对路径,其的root路径是/opt/local。

作为java开发人员,以前熟悉了Apache + mod_jk + Jboss的模式,到了Nginx下自然也希望有类似mod_jk的工具来将请求转发给Jboss. 但是在找叔度要这个模块是,他告诉我可以自己将Nginx作为一个Proxy,以反向代理的方式将请求转给Jboss. 在http://wiki.nginx.org/JavaServers上面有教程,看了一下非常简单。 关键是下面这个配置:

server {
listen              8080;
server_name         10.232.22.174;
location / {
proxy_pass   http://127.0.0.1:8100/;
tcp_nodelay     on;
proxy_redirect  off;
proxy_set_header Host            $host;
proxy_set_header X-Real-IP       $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

server {

listen              8080;

server_name         127.0.0.1;

location / {

proxy_pass   http://127.0.0.1:8080/;

tcp_nodelay     on;

proxy_redirect  off;

proxy_set_header Host            $host;

proxy_set_header X-Real-IP       $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}

}

配置好后以-c filename的方式指定用新的配置文件启动nginx服务器,在启动jboss 就ok了。
这两天看了一些Nginx Wiki的文档,有一些心得。要熟练运用这东西最重要的是熟悉它的配置,以及支持的一些运用模式。这快只能通过看文档,做实验来熟悉。要达到高性能,并做一些调优则需要对于网络,Linux底层有很好的认识。
ps: 今天在配置过程中还发现,如果只是kill 掉 nginx master process,保留 worker process,进程仍然会占用80端口。但是这时候通过 lsof -i:80 查看时会发现没有进程占有80端口。后来twitter上的@chzealot给我解释了一下原因:lsof只能查看fd,端口处于time_wait状态时,fd已经close,但是还需要两个MSL time_wait状态才能消逝。