起步于系统工程师,迈进入测试工程师,从起初的C/S系统到互联网时代的B/S系统,从事过电信增值业务、软交换、烟草OA、公安技侦和电子商务等行业的软件测试开发和管理多年,愿与大家共同分享共同交流,关注软件项目管理、测试团队管理、软件流程控制和软件性能测试及自动化测试技术。互联网时代,技术推动进步,欢迎人才推荐:jonas.wangl@alibaba-inc.com

发布新日志

  • 【linux】page cache 和VM Perl 线程和C++性能优化

    2010-03-24 11:35:27

    调节 Page Cache

    Linux 的内核中,对文件的读写提供一个页面缓冲的机制(Page Cache)。Page Cache 存在于内存中,当要读取一个磁盘文件的内容时,内核首先在 Page Cache 中进行查找,如果要读取的内容已经存在 Page Cache 中,则无需在对磁盘发起实际的读操作。同样在需要写文件时,写操作也只是将内容存放于 Page Cache 中,而 Page Cache 中的更改内容由内核进程 pdflush 周期性的写回磁盘。在默认情况下,pdflush 进程每 5 秒钟醒来一次,进行数据写回操作。这个写回时间值定义在参数 /proc/sys/vm/dirty_writeback_centisecs中。如果在这 5 秒钟之间,发生电源故障或者系统崩溃,可能会引起数据丢失。如果用户的电源供应比较可靠,或者丢数据丢失的风险不是非常在意,可以适当的提高这个数据写回时间。使用如下命令查看系统当前的写回时间值:

    cat /proc/sys/vm/dirty_writeback_centisecs

     500

     

    此时间值的单位为 1/100 秒。使用如下命令可以更改此值:

     echo 2000 > /proc/sys/vm/dirty_writeback_centisecs

     

    这样,就可以使 pdflush 进程 20 秒才醒来一次,从而减少对磁盘的访问频率。

    还有一个参数 /proc/sys/vm/dirty_expire_centisecs控制一个更改过的页面经过多长时间后被认为是过期的、必须被写回的页面,其默认值是 3000(单位也是 1/100 秒)。用户也可以适当的增加此值,使页面更长时间的驻留在内存中。如下命令:

     echo 4000 > /proc/sys/vm/dirty_expire_centisecs

     

    pdflush 进程处理的另一种情况是当可用内存量降低的时候,会将一些缓冲页面写回磁盘,释放内存。这个行为是受 /proc/sys/vm/dirty_background_ratio参数控制的,此参数的默认值为 10,意思是当所有被更改页面总大小占工作内存超过 10% 时,pdflush 会开始写回工作。用户可以增加这个比例,以增加页面驻留在内存的时间。此参数的更改方法同上面两个参数。

    Swap 分区或文件

    在 默认情况下,Linux 内核并不是只有在物理内存不够用的时候才进行交换,而是为了保证尽量大的磁盘缓冲以及其他一些原因,会尽可能的将非活动的进程及内存页面交换出内存,放在磁盘上的交换分区中。这种默认行为使得在还有大量内存可用的情况下,就会发生交换操作,而释放出的物理内存并没有被利用起来,显然这些交换操作是不必要 的。为了减少因交换引起的磁盘读写,在用户内存足够大的时候,可以考虑禁用 swap 分区。

    显示作业和进程信息

                                  

    ian@attic4:~$ jobs -l

    [1]-  3878 Running                 xclock -d -update 1 &

    [2]+  4320 Running                 xclock -bg wheat -update 1 &

     

    线程概述

    线程与进程之间既有联系,又完全不同。简单地说,一个线程必然属于某一个进程,而一个进程包含至少一个或者多个线程。

     

     

    1. Perl 程序中,我们也可以通过使用 Config 模块来动态获取 Perl 线程模型的相关信息,例如


    Perl
    程序中动态获取当前 Perl 线程模型

                                  

     #!/usr/bin/perl

     #

     use Config;

     if( $Config{useithreads} ) {

     printf("Hello ithreads\n")

     }

     elsif( $Config{use5005threads} ) {

     printf("Hello 5005threads\n");

     }

     else {

     printf("Can not support thread in your perl environment\n");

        exit( 1 );

     }

     

     

    创建线程

    Perl 里创建一个新的线程非常简单,主要有两种方法,他们分别是:

    1. 使用 threads 包的 create() 方法,例如


    1)
    通过 create() 方法创建线程

                                  

     use threads;

     

     sub say_hello

     {

        printf("Hello thread! @_.\n");

     return( rand(10) );

     }

     

     my $t1 = threads->create( \&say_hello, "param1", "param2" );

     my $t2 = threads->create( "say_hello", "param3", "param4" );

     my $t3 = threads->create(

     sub {

     printf("Hello thread! @_\n");

                     return( rand(10) );

     },

     "param5",

                 "param6" );

     

    1. 使用 async{} 块创建线程,例如


    2)
    通过 async{} 块创建线程

                                  

     #!/usr/bin/perl

     #

     use threads;

     

     my $t4 = async{

     printf("Hello thread!\n");

             };

     

     

    析构函数与构造函数

     

    析构函数的调用与构造函数的调用一样,也是类似的递归操作。

    但有两点不同,一是析构函数没有与构造函数相对应的初始化操作部分,这样析构函数的主要工作就是执行析构函数的函数体;

    二是析构函数执行的递归与构造函数刚好相反,而且在每一层的递归中,成员变量对象的析构顺序也与构造时刚好相反。

     

    C++程序汇总消耗性能

    C++程序中,创建/销毁对象是影响性能的一个非常突出的操作。

    首先,如果是从全局堆中生成对象,则需要首先进行动态内存分配操作。众所周知,动态内存 分配/回收在C/C++程序中一直都是非常费时的。因为牵涉到寻找匹配大小的内存块,找到后可能还需要截断处理,然后还需要修改维护全局堆内存使用情况信 息的链表等。因为意识到频繁的内存操作会严重影响性能的下降,所以已经发展出很多技术用来缓解和降低这种影响,比如内存池技术。其中一个主要目标就是为了减少从动态堆中申请内存的次数,从而提高程序的总体性能。当取得内存后,如果需要生成的目标对象属于一个复杂继承体系中末端的类,那么 该构造函数的调用就会引起一长串的递归构造操作。在大型复杂系统中,大量此类对象的创建很快就会成为消耗CPU操作的主要部分。因为注意和意识到对象的创 /销毁会降低程序的性能,所以开发人员往往对那些会创建对象的代码非常敏感。在尽量减少自己所写代码生成的对象同时,开发人员也开始留意编译器在编译 "悄悄"生成的一些临时对象。开发人员有责任尽量避免编译器为其程序生成临时对象,下面会有一节专门讨论这个问题。语义保持完全一致。

  • apache的动态和静态编译区别[转]

    2009-11-11 09:37:12

    apache的动态和静态编译区别
    一、含义:
    动态意味着不用此模块的时候就不需要Load进来,使用的时候需要显示的Load进来;
    静态意味着先把模块Load进来,想用的时候直接使用.

    二、编译:
    1、静态编译:
    当只需要静态编译module的时候,语法应写成–enable-ssl或–enable-ssl=static。
    例如:

    #./configure --prefix=/usr/local/apache2 --enable-ssl[=static]

    查看哪些modules被静态编译进apache里:

    #/usr/local/apache2/bin/httpd -l
    Compiled in modules:
      core.c
      mod_ssl.c

    2、动态编译:

    当只需要动态编译module的时候,语法写成–enable-ssl=shared即可。

    #./configure --prefix=/usr/local/apache2 --enable-ssl=shared

    查看哪些modules被动态编译进apache里:

    #ls -l /usr/local/apache2/modules/
    
    -rw-r--r-- 1 root root   8504 Aug 25 14:49 httpd.exp
    -rwxr-xr-x 1 root root 806898 Aug  7 13:57 mod_ssl.so

    3、静动混合:

    当既需要动态又需要动态的时候,语法写成–enable-ssl=static[动态编译] –enable-rewrite=shared[静态编译]
    以下为示例:

    #./configure --prefix=/usr/local/apache2 --enable-ssl=static --enable-rewite=shared

    三、使用:

    1、动态编译使用:
    会生成相关的so文件,例如:

    1)、动态加载module,在配置文件里需要加上如下语句:

    LoadModule access_module /usr/local/apache2/modules/mod_ssl.so

    2)、使用:

    rewriteEngine on
    RewriteRule ^/(.*)    http://www.hao123.com  [L,P]

    2、静态编译使用:
    例如要使用rewrite模块的时候在配置文件里加下这句就可以了:

    RewriteEngine on
    RewriteRule ^/(.*)    http://www.hao123.com  [L,P]
  • 理解Linux 的处理器负载均值(翻译)

    2009-11-04 19:32:42

    Linux 负载均值到底是什么意思? 这个数值究竟如何说明服务器是忙是闲?依据这个数值来决定是否需要添加服务器,靠谱么?在网上google了一篇文章描述的非常形象,当然也通俗易懂喔。可以收藏喔

    你可能对于 Linux 的负载均值(load averages)已有了充分的了解。负载均值在 uptime 或者 top 命令中可以看到,它们可能会显示成这个样子:

    load average: 0.09, 0.05, 0.01

    很多人会这样理解负载均值:三个数分别代表不同时间段的系统平均负载(一分钟、五 分钟、以及十五分钟),它们的数字当然是越小越好。数字越高,说明服务器的负载越 大,这也可能是服务器出现某种问题的信号。

    而事实不完全如此,是什么因素构成了负载均值的大小,以及如何区分它们目前的状况是还是糟糕?什么时候应该注意哪些不正常的数值?

    回答这些问题之前,首先需要了解下这些数值背后的些知识。我们先用最简单的例子说明, 一台只配备一块单核处理器的服务器。

    行车过桥

    一只单核的处理器可以形象得比喻成一条单车道。设想下,你现在需要收取这条道路的过桥 -- 忙于处理那些将要过桥的车辆。你首先当然需要了解些信息,例如车辆的载重、以及 还有多少车辆正在等待过桥。如果前面没有车辆在等待,那么你可以告诉后面的司机通过。 如果车辆众多,那么需要告知他们可能需要稍等一会。

    因此,需要些特定的代号表示目前的车流情况,例如:

    • 0.00 表示目前桥面上没有任何的车流。 实际上这种情况与 0.00 1.00 之间是相同的,总而言之很通畅,过往的车辆可以丝毫不用等待的通过。
    • 1.00 表示刚好是在这座桥的承受范围内。 这种情况不算糟糕,只是车流会有些堵,不过这种情况可能会造成交通越来越慢。超过 1.00,那么说明这座桥已经超出负荷,交通严重的拥堵。 那么情况有多糟糕? 例如 2.00 的情况说明车流已经超出了桥所能承受的一倍,那么将有多余过桥一倍的车辆正在焦急的等待。3.00 的话情况就更不妙了,说明这座桥基本上已经快承受不了,还有超出桥负载两倍多的车辆正在等待。

    上面的情况和处理器的负载情况非常相似。一辆汽车的过桥时间就好比是处理器处理某线程 的实际时间。Unix 系统定义的进程运行时长为所有处理器内核的处理时间加上线程 在队列中等待的时间。

    和收过桥费的管理员一样,你当然希望你的汽车(操作)不会被焦急的等待。所以,理想状态 下,都希望负载平均值小于 1.00 。当然不排除部分峰值会超过 1.00,但长此以往保持这 个状态,就说明会有问题,这时候你应该会很焦急。

    所以你说的理想负荷为 1.00

    嗯,这种情况其实并不完全正确。负荷 1.00 说明系统已经没有剩余的资源了。在实际情况中 ,有经验的系统管理员都会将这条线划在 0.70

    • 需要进行调查法则 如果长期你的系统负载在 0.70 上下,那么你需要在事情变得更糟糕之前,花些时间了解其原因。
    • 现在就要修复法则1.00 如果你的服务器系统负载长期徘徊于 1.00,那么就应该马上解决这个问题。否则,你将半夜接到你上司的电话,这可不是件令人愉快的事情。
    • 凌晨三点半锻炼身体法则5.00 如果你的服务器负载超过了 5.00 这个数字,那么你将失去你的睡眠,还得在会议中说明这情况发生的原因,总之千万不要让它发生。

    那么多个处理器呢?我的均值是 3.00,但是系统运行正常!

        哇喔,你有四个处理器的主机?那么它的负载均值在 3.00 是很正常的。

    在多处理器系统中,负载均值是基于内核的数量决定的。以 100% 负载计算,1.00 表示单个处理器,而 2.00 则说明有两个双处理器,那么 4.00 就说明主机具有四个处理器。

    回到我们上面有关车辆过桥的比喻。1.00 我说过是一条单车道的道路。那么在单车道 1.00 情况中,说明这桥梁已经被车塞满了。而在双处理器系统中,这意味着多出了一倍的 负载,也就是说还有 50% 的剩余系统资源 -- 因为还有另外条车道可以通行。

    所以,单处理器已经在负载的情况下,双处理器的负载满额的情况是 2.00,它还有一倍的资源可以利用。

    多核与多处理器

    先脱离下主题,我们来讨论下多核心处理器与多处理器的区别。从性能的角度上理解,一台主 机拥有多核心的处理器与另台拥有同样数目的处理性能基本上可以认为是相差无几。当然实际 情况会复杂得多,不同数量的缓存、处理器的频率等因素都可能造成性能的差异。

    但即便这些因素造成的实际性能稍有不同,其实系统还是以处理器的核心数量计算负载均值 。这使我们有了两个新的法则:

    • 有多少核心即为有多少负荷法则: 在多核处理中,你的系统均值不应该高于处理器核心的总数量。
    • 核心的核心法则: 核心分布在分别几个单个物理处理中并不重要,其实两颗四核的处理器 等于 四个双核处理器 等于 八个单处理器。所以,它应该有八个处理器内核。

    审视我们自己

    让我们再来看看 uptime 的输出

    ~ $ uptime
    23:05 up 14 days, 6:08, 7 users, load averages: 0.65 0.42 0.36

    这是个双核处理器,从结果也说明有很多的空闲资源。实际情况是即便它的峰值会到 1.7,我也从来没有考虑过它的负载问题。

    那么,怎么会有三个数字的确让人困扰。我们知道,0.650.420.36 分别说明上一分钟、最后五分钟以及最后十五分钟的系统负载均值。那么这又带来了一个问题:

    我们以哪个数字为准?一分钟?五分钟?还是十五分钟?

    其实对于这些数字我们已经谈论了很多,我认为你应该着眼于五分钟或者十五分钟的平均数 值。坦白讲,如果前一分钟的负载情况是 1.00,那么仍可以说明认定服务器情况还是正常的。 但是如果十五分钟的数值仍然保持在 1.00,那么就值得注意了(根据我的经验,这时候你应 该增加的处理器数量了)。

    那么我如何得知我的系统装备了多少核心的处理器?

    Linux 下,可以使用

    cat /proc/cpuinfo

    获取你系统上的每个处理器的信息。如果你只想得到数字,那么就使用下面的命令:

    grep 'model name' /proc/cpuinfo | wc -l

     

  • crontab 命令内容解释

    2008-11-10 11:46:29

     * * * /home/testing/scrīpt/test.sh
    分钟 小时 日期 月份 星期

    顺序为 分钟 (0-59) 小時 (0-23) 日期 (1-31) 月份 (1-12) 星期 (0-6)//0代表星期天
    除了数字还有几个特殊的符号就是"*"、"/"和"-"、",",
    *代表所有的取值范围内的数字
    "/"代表每的意思
    "*/5"表示每5个单位,
    "-"代表从某个数字到某个数字
    ","分开几个离散的数字

    例如:
    每天早上6点 0 6 * * * echo "Good morning." >> /tmp/test.txt
    //注意单纯echo,从屏幕上看不到任何输 出, 因为cron把任何输出都email到root 的信箱了。

    每两个小时
    0 */2 * * * echo "Have a break now." >> /tmp/test.txt

    晚上11点到早上8点之间每两个小时,早上八点
    0 23-7/2,8 * * * echo "Have a good dream:)" >> /tmp/test.txt

    每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
    0 11 4 * 1-3 command line

    1月1日早上4点
    0 4 1 1 * command line

  • Linux系统信息查看命令整理

    2008-11-07 11:22:37

    【系统】

       # uname -a # 查看内核/操作系统/CPU信息

      # head -n 1 /etc/issue # 查看操作系统版本

      # cat /proc/cpuinfo # 查看CPU信息

      # hostname # 查看计算机名

      # lspci -tv # 列出所有PCI设备

      # lsusb -tv # 列出所有USB设备

      # lsmod # 列出加载的内核模块

      # env # 查看环境变量

    【资源】

      # free -m # 查看内存使用量和交换区使用量

      # df -h # 查看各分区使用情况

      # du -sh # 查看指定目录的大小

      # grep MemTotal /proc/meminfo # 查看内存总量

      # grep MemFree /proc/meminfo # 查看空闲内存量

      # uptime # 查看系统运行时间、用户数、负载

      # cat /proc/loadavg # 查看系统负载

    【磁盘和分区】

      # mount | column -t # 查看挂接的分区状态

      # fdisk -l # 查看所有分区

      # swapon -s # 查看所有交换分区

      # hdparm -i /dev/hda # 查看磁盘参数(仅适用于IDE设备)

      # dmesg | grep IDE # 查看启动时IDE设备检测状况

    【网络】

      # ifconfig # 查看所有网络接口的属性

      # iptables -L # 查看防火墙设置

      # route -n # 查看路由表

      # netstat -lntp # 查看所有监听端口

      # netstat -antp # 查看所有已经建立的连接

      # netstat -s # 查看网络统计信息

    【进程】

      # ps -ef # 查看所有进程

      # top # 实时显示进程状态

    【用户】

      # w # 查看活动用户

      # id # 查看指定用户信息

      # last # 查看用户登录日志

      # cut -d: -f1 /etc/passwd # 查看系统所有用户

      # cut -d: -f1 /etc/group # 查看系统所有组

      # crontab -l # 查看当前用户的计划任务

    【服务】

      # chkconfig --list # 列出所有系统服务

      # chkconfig --list | grep on # 列出所有启动的系统服务

    【程序】

      # rpm -qa # 查看所有安装的软件包

  • [论坛] UNIX/Linux系统的日志整理

    2008-11-05 18:06:18

    UNIX/Linux系统的日志整理

    我们在测试web应用时,测试环境往往都是搭建在unix/linux系统上的,有jboss、apache等一些应用,但环境异常时,我们如何去查去分析呢?是很多新同学碰壁。

    LOG日志的介绍.doc
    (2008-10-30 13:46:53, Size: 82 kB, Downloads: 18)

  • 【分享】LINUX常用技巧

    2008-11-04 13:08:33

    一次使用的常用技巧,分享下

    1.取消^M字符
    当你FTP一些DOS文件到unix下时,你经常会看见每行文件后面有个讨 厌的^M 字符,有两个简单的方法可以取消它。 用"vi"打开此文件,在Command mode下敲入: :%s/^V^M//g 或者,在UNIX SHELL下敲入: sed 's/^V^M//g' foo > foo.new


    2.使用nohup命令
    如果你想进程在你退出系统后还能执行,可以使用NOHUP命令 如: % nohup tar -cf /dev/tape /home & 你退出后再重新登录的话,使用'ps'命令可以看到进程还在执行

    3.查看文件的方法
    如果你只想看文件的前5行,可以使用head命令,如: head -5 /etc/passwd 如果你想查看文件的后10行,可以使用tail命令,如: tail -10 /etc/passwd 你知道怎么查看文件中间一段吗?你可以使用sed命令 如: sed -n '5,10p' /etc/passwd 这样你就可以只查看文件的第5行到第10行。

    4.计算文件数和目录数 下面的语句可以帮你计算有多少个文件和多少个目录..
    # ls -l * |grep "^-"|wc -l ---- to count files
    # ls -l * |grep "^d"|wc -l ----- to count dir
    还可以将以上的语句变成scrīpt或做个alias

    5.只列子目录的方法:
    ls -F | grep /$ 或者
    alias sub = "ls -F | grep /$"(linux)
    ls -l | grep "^d" 或者
    ls -lL | grep "^d" (Solaris)

    6.利用Find命令改变所有权
    想要改变当前目录下所有文件的所有权,可以这样:
    find . -exec chown OWNER.[GROUP] {} \; (Solaris)
    find . -exec chown -R OWNER.[GROUP] {} \; (Linux)

    7.列出除了某些类型文件的当前目录所有文件
    使用Ksh,用ls !(*.Z)可以显示所有文件,除了*.Z文件。 这个命令在一个目录里有许多种类型的文件的时候很有用

  • 一次建立大量用户的方法

    2008-11-04 13:04:26

    在linux系统中,我们可以一次建立很多用户:

    1. 假设用excel 完成数据域的建立,另存成 文字文件,ftp 到server 上,面资料文件的内容有三个字段,分别是帐号($1)、密码($2)、姓名($3),存到server 上的檔名是 data.txt
    2.编辑一个 awk 的程序 ,文件名:mkusers.awk,内容如下:
    { print "adduser -g users -d /home/st/" $1 " -s /bin/bash -c " $3 " " $1 }
    { print "echo " $1 ":" $2 " | chpasswd "}
    请注意,蓝色部份是字符串,前后用"号,$1 $2 $3 是字段变量。
    3. 执行
    awk -f mkusers.awk ./data.txt | more
    说明:先看看输出的结果对不对,正确无误后,把 more 改成 sh 就 可以了

    如果希望同时删除这些用户,只需要使用userdel -r username代替上面的程序就可以了

  • Unix中限制root远程登录的方法

    2008-11-04 09:35:31

       UNIX系统中,计算机安全系统建立在身份验证机制上。如果root口令失密,系统将会受到侵害,尤其在网络环境中,后果更不堪设想。因此限制用户 root 远程登录,对保证计算机系统的安全,具有实际意义。本文向大家介绍一些方法,能达到限制 root 远程登录的目的。

      方法一:在/etc/default/login 文件,增加一行设置命令:

      CONSOLE = /dev/tty01

      设置后立即生效,无需重新引导。以后,用户只能在控制台(/dev/tty01)root登录,从而达到限制root远程登录,不过,同时也限制了局域网用户root登录,给管理员的日常维护工作带来诸多不便。

      方法二:1.为了达到限制root远程登录,首先要分清哪些用户是远程用户(即是否通过另一台 Windows 系统或 UNIX 系统进行 telnet 登录),哪些用户是局域网用户。通过以下shell程序能达到此目的。

      TY=`tty | cut -b 9-12`

      WH=`finger | cut -b 32-79 | grep "$TY " | cut -b 29-39`

      KK=` tty | cut -b 6-9`

      If [ "$KK" = "ttyp" ]

      Then

       WH=$WH

      Else

       WH="local"

      Fi

      以上Shell命令程序中,WH为登录用户的主机IP地址,但如果在 /etc/hosts 文件中,定义了IP 地址和机器名之间的对应关系,则 WH 为用户登录的主机名。假设连接到局域网中的终端服务器的IP 地址为:99.57.32.18, 那么应在 /etc/hosts 文件中加入一行:

      99.57.32.18 terminal_server

      所有通过99.57.32.18终端服务器登录到主机的终端中,WH 是同一个值,即为终端服务器名terminal_server。

      2.在root的.profile文件中,根据 WH 值进行不同的处理,从而实现限制root远程登录。

      Trap 1 2 3 9 15

      If [ "$WH" = "local" -o "$WH" = "terminal_server" ]

      Then

       Echo "Welcome......"

      Else

       Exit

      Fi

      方法三:有时为了工作的方便,允许局域网中部分电脑root登录,例如,允许局域网中IP 地址为 99.57.32.58 的电脑root登录,要实现这一点,需要在前述方法中,作两点补充:

      1.在 /etc/hosts 文件中,加入一行:99.57.32.58 xmh。

      2.在上述 Shell 程序段中,将下述内容:

      If [ "$WH" = "local" -o "$WH" = "terminal_server" ]

      修改为:

      If [ "$WH" = "local" -o "$WH" = "terminal_server" -o "$WH"= "xmh" ]

      方法四:经过以上处理后,仍存在普通用户登录后用su命令变成 root 用户的可能,从而达到 root 远程登录的目的。为了防止用这种方法实现 root 远程登录,需要限制普通用户不能执行 su 命令:

      1.将su命令属主改为 root;

      2.将su命令的权限改为 700。

      方法五:在上述方法中,虽限制了普通用户执行su 命令,但“精明”的用户可以用 ftp 命令上载一个用户可以执行的 su命令,从而实现 root 远程登录。为了防止这一点,需要在路由器上设立防火墙,限制用户执行ftp协议,这里不再赘述。
     

  • 介绍几种查看日志的方式

    2008-11-03 17:35:56

    在测试web应用程序时,配置测试环境是unix下的,如何查看应用的日志,以下介绍几个方式:

    1. 应用日志存放的路径一般为: /home/{unix_user}/output/logs/sys/webx.log

    2. 一般有很多个webx.log的文件,一个webx.log主文件,其他都加日期的,譬如webx.log.200x-xx-xx 结束的。这些都是之前的log。当日的应用日志应该是webx.log

    3. 建议删除所有日志  rm –rf *  然后再重启应用,这时,你的日志文件会变得很清晰,一目了然。

    4. 也可以不重启应用,直接清log 比如: > webx.log  这样你的日志文件就被清空了。

    5. 查看日志方式: vi webx.log   

                       more webx.log  

                       cat webx.log    

                       tail –f webx.log (查看后面10log)都可以。

    6. 查看日志并查找某关键字:

    a. vi webx.log   然后 /ERROR  就是查找有含有ERROR的日志,按键盘n 为 查找下一个

    b. cat webx.log |grep ERROR  列出webx.log 中所有 ERROR的行

    c. ERROR的个数 cat webx.log |grep ERROR | wc –l  计算出webx.log 中所有 ERROR的个数

      d. 查找除了ERROR 以外关键字的日志: cat webx.log |grep -v ERROR

         e. 在某个文件夹下,查找该文件夹下,所有文件含有某个关键字:  grep -e ERROR -r *

         ……

         要适当用 管道符 来缩小查找的范围.

    7. 对于webx.log ,存在 ERROR 或者 Exception ,我们都是要关注和跟进的.

    8. Log信息问几种级别:OFFFATALERRORWARNINFODEBUGALL;但是平时一般只用四种:DEBUGINFOWARNERROR;前三个级别的信息一般是在程序员用来调试的信息,而第四种(error)级别是日志信息里级别最高的,ERROR级别信息的产生分两种;一种是程序出错,一种只是程序员用来调试输出;一般在日志文件中,ERROR级别的信息是需要特别关注的

    9. 一般我们都把log 的级别调成 error . 在unix测试环境的home下面的antx.properties 中的  应用.loggingLevel     = error  比如: exodus2.loggingLevel     = error

     

  • web测试环(UNIX)Log日志整理

    2008-11-02 21:37:36

    LOG日志的介绍

     

     

    1、  在看log之前,首先需要了解每个log文件要记录什么信息:比如, performance.log是一个查看性能的log日志,而search-velocity.log则是一个查看页面信息的日志;由于每个projectlog文件都有其特定性,所以在看log之前需要先清楚每个log文件代表什么信息;

     

    2、  Log信息问几种级别:OFFFATALERRORWARNINFODEBUGALL;但是平时一般只用四种:DEBUGINFOWARNERROR;前三个级别的信息一般是在程序员用来调试的信息,而第四种(error)级别是日志信息里级别最高的,ERROR级别信息的产生分两种;一种是程序出错,一种只是程序员用来调试输出;一般在日志文件中,ERROR级别的信息是需要特别关注的;而在性能监控的日志文件里,则不需要特别去关注ERROR级别的信息,而是去关注操作带来的时间瓶颈

     

    3、  下面以一个应用工程为例讲讲;

     

    4、  如某个应用常用的日志文件分为两块:系统级(sys)和用户级(user),这一步是分成两个目录保存,/sys/user;我们主要关注系统级的日志信息,用户级的日志信息只是关注用户在系统中的行为,一般不需要去关注;而sys级的常用日志一般也分为两块:功能性的日志和关注性能方面的日志:

    功能性的日志一般为:

                             i.              dal.log:      用来记录数据层程序执行sql的信息,可以看到sql语句以及执行的情况,该日志不会产生error级别的信息;

                           ii.              velocity.log:  用来记录页面的信息;

                          iii.              webx.log:    该日志记录系统运行期间发生的信息,该日志记录的都是java类运行发生的信息,当程序出错后,首要查看的是该日志;

    性能方面的日志:

                         iv.              performance.log:记录aodao类运行时间,由什么请求发起,属于性能监控;

                           v.              webx-filter.log  用来记录每个ie请求的信息,以及该请求从开始到结束所经过的各个请求以及每个请求所开销的时间,属于性能监控;

                         vi.              hacking.log:      是记录用户修改登陆信息的日志;

     

      功能性的日志一般需要关注的是ERROR级别的日志信息,除dal.log外,因为dal.log是没有信息级别表识的,它只是打印sql执行的语句;但如果在webx.logvelocity.log日志中发现ERROR级别的信息,那肯定就是程序出错,需要返馈给程序员,由程序员去修改程序;下面对以上的日志举例进行讲解。

     

    4、一般每条日志信息包含了几大要素:

    a)         发生的时间;

    b)        信息级别;

    c)        执行什么操作,如果出错,则有出错的异常类型;

    d)        调试的输出信息,如出错,则有出错的提示;

    e)         如出错,相关出错的地方,在做什么动作的时候发生,具体出错在哪一行;

        操作步骤:

    确定要查看什么功能,打开相应的日志文件,先查看是否有ERROR级别的信息;

    然后确认该error信息的时间是否是要查询的操作时间,看是否是在该操作时间段内发生的;

    以上两点都符合的话,则进行下一步,举例分析ERROR发生的原因;

     

    5、举例说明:

           功能性的日志

    velocity.log:该日志是用来记录页面信息的;当页面运行时,页面的信息会被记录在该日志中,页面出错首先看这份文件,然后再看webx.log确定是页面出错还是环境或配置或程序出错;

           如:2007-08-06 15:02:20,335 ERROR VelocityService.aso - ResourceManager : unable to find resource 'macros.vm' in any resource loader.

           分析:

    发生的时间,2007-08-06 15:02:20

    信息级别,ERROR,表明是出错信息;

    出错的提示:unable to find resource 'macros.vm' in any resource loader

               根据出错提示可得出系统找不到macros.vm,该摸板没有被载入,据此就可以把这信息反馈给功能负责者或程序员,让他去改正这一bug

    但是页面的出错有时候并不能完全确定是页面或摸板出的错,也有可能是业务层或数据层出的错,比如页面出现505错误,这个时候就需要看Webx.log

     

    Webx.log: 一般环境、程序、配置出错,都看这份文件;

    2007-08-06 15:03:59,567 [] ERROR service.ServiceManager - Service BeanFactoryService failed to initialize

    com.alibaba.service.ServiceInitializationException: Failed to initialize BeanFactory

    at com.alibaba.service.spring.DefaultBeanFactoryService.init(DefaultBeanFactoryService.java:84)

           at com.alibaba.service.GenericService.init(GenericService.java:26)

           at com.alibaba.service.DefaultServiceManager.initService(DefaultServiceManager.java:458)

           at com.alibaba.service.DefaultServiceManager.getService(DefaultServiceManager.java:829)

           at com.alibaba.service.DefaultServiceManager.getService(DefaultServiceManager.java:801)

           at com.alibaba.service.DefaultServiceManager.initAll(DefaultServiceManager.java:186)

           at com.alibaba.service.context.SingletonServiceManagerLoader.getInstance(SingletonServiceManagerLoader.java:72)

                  ……………………

       分析:

    发生的时间,2007-08-06 15:03:59

    信息级别,ERROR,表明是出错信息;

    出错的异常类型:ServiceInitializationException

    出错的提示:Failed to initialize BeanFactory,初始化BeanFactory失败;

    相关类的出错的地方,在做什么动作的时候发生,具体出错在哪一行;

    如:at com.alibaba.service.GenericService.init(GenericService.java:26),表明是在执行GenericService.java的方法init时出错,在GenericService.java类的第26行;

     

     dal.log:从该日志信息,主要能打印出整个sql语句;该日志信息是没有显示信息级别的,目的只是为了打印出整个执行的sql语句;

           如:2007-08-02 17:40:40,573 DEBUG sql.Connection - {conn-100003} Preparing Statement:              select        sum(case when STATUS='published' and GMT_EXPIRE>sysdate then 1 else 0 end) total_count,     sum(case when STATUS='member expired' or (STATUS = 'published' AND GMT_EXPIRE < SYSDATE) then 1 else 0 end) expired_count    from offer     where member_id=?       

    从这条信息中能看到,发生的时间,执行的完整的sql

     

    性能监控的日志

    performance.log:从该日志信息能看到AODAOjava类在发生请求时,执行的时间;

    如:2007-08-02 17:40:40,581 INFO  - Call interface com.alibaba.exodus2.biz.dal.daointerface.OfferDAO.getOfferTotalAndExpiredCountByMemberId() take 8 ms. - [/ims/my_alitalk_info.htm?member_id=alipff]

    分析:

           发生的时间:2007-08-02 17:40:40

        信息级别:  INFO

          类:com.alibaba.exodus2.biz.dal.daointerface.OfferDAO

           该类执行的方法:getOfferTotalAndExpiredCountByMemberId()

           执行该方法花费的时间:8 ms

           执行该方法的请求:/ims/my_alitalk_info.htm?member_id=alipff

    根据以上的这些信息,就能够确定出这个请求在执行java类的方法时花了多少时间?在监控java类性能上可以查看该信息;

     

     

    webx-filter.log:该信息用来查看发起一次请求,所经过那些请求,以及每个请求所花费的时间,用来性能监控;

     

    如:2007-08-02 18:05:18,906 INFO  timer.TimerFilter - Started processing request: GET /offer/select_page.htm?needsignin=1

    2007-08-02 18:05:19,575 INFO  timer.TimerFilter - Response of GET /offer/select_page.htm?needsignin=1 returned in 657ms

    Detail: 0 [657ms, 100%] - process HTTP request

            +---0 [0ms] - Preparing request context: BufferedRequestContextImpl(14723050)

            +---0 [0ms] - Preparing request context: LazyCommitRequestContextImpl(19925149)

            +---0 [0ms] - Preparing request context: ParserRequestContextImpl(8754866)

            +---0 [1ms, 0%, 0%] - Preparing request context: SessionRequestContextImpl(6861740)

            +---1 [6ms, 1%, 1%] - Preparing request context: SetLocaleRequestContextImpl(32252426)

            |   `---1 [6ms (5ms), 100%, 1%] - Decoding cookie for session object

            |       `---1 [1ms, 17%, 0%] - Decrypting cookie for session object

            +---7 [1ms, 0%, 0%] - Preparing request context: RewriteRequestContextImpl(5203636)

            +---8 [0ms] - Preparing request context: RemoteAddrRequestContextImpl(14670479)

            +---8 [0ms] - Preparing request context: ChinaRunData(8789037)

            +---8 [16ms, 2%, 2%] - before request

            +---24 [625ms (84ms), 95%, 95%] - handle request

            |   +---94 [289ms (52ms), 46%, 44%] - load and execute screen module: SelectPage (template: screen/selectPage.vm)

            |   |   +---145 [94ms, 33%, 14%] - Dispatch and process command: offerBaseAO

            |   |   `---240 [143ms (119ms), 49%, 22%] - render velocity template: /screen/selectPage.vm

            |   |       +---327 [11ms (4ms), 8%, 2%] - load and execute control module: TemplateControl (template: control/post/style.vm)

            |   |       |   `---331 [7ms, 64%, 1%] - render velocity template: /control/post/style.vm

            |   |       `---363 [13ms, 9%, 2%] - load and execute control module: TemplateControl (template: control/excelpost/uploadExcelModule.vm)

            |   |           `---363 [13ms, 100%, 2%] - render velocity template: /control/excelpost/uploadExcelModule.vm

            |   `---397 [252ms, 40%, 38%] - load and execute layout module: TemplateLayout

            |       `---397 [252ms (128ms), 100%, 38%] - render velocity template: /layout/myalibaba.vm

            |           +---453 [21ms (9ms), 8%, 3%] - load and execute control module: home:TemplateControl (template: control/share/meta.vm)

            |           |   `---462 [12ms, 57%, 2%] - render velocity template: /control/share/meta.vm

            |           +---494 [5ms, 2%, 1%] - load and execute control module: home:TemplateControl (template: control/common/style/myalibaba.vm)

            |           |   `---494 [5ms, 100%, 1%] - render velocity template: /control/common/style/myalibaba.vm

            |           +---508 [2ms, 1%, 0%] - load and execute control module: TemplateControl (template: control/excelpost/uploadExcelDiv.vm)

            |           |   `---508 [2ms, 100%, 0%] - render velocity template: /control/excelpost/uploadExcelDiv.vm

            |           +---524 [3ms, 1%, 0%] - load and execute control module: home:TemplateControl (template: control/common/top/top.vm)

            |           |   `---524 [3ms, 100%, 0%] - render velocity template: /control/common/top/top.vm

            |           +---542 [83ms, 33%, 13%] - load and execute control module: home:TemplateControl (template: control/common/menu/myalibabaLeftMenu.vm)

            |           |   `---542 [83ms (30ms), 100%, 13%] - render velocity template: /control/common/menu/myalibabaLeftMenu.vm

            |           |       `---572 [53ms, 64%, 8%] - load and execute control module: home:TemplateControl (template: control/common/style/menuArray.vm)

            |           |           `---572 [53ms, 100%, 8%] - render velocity template: /control/common/style/menuArray.vm

            |           `---639 [10ms (1ms), 4%, 2%] - load and execute control module: home:TemplateControl (template: control/common/bottom/bottom.vm)

            |               `---640 [9ms, 90%, 1%] - render velocity template: /control/common/bottom/bottom.vm

            +---649 [2ms, 0%, 0%] - after request

            +---651 [0ms] - Committing request context: ChinaRunData(8789037)

            +---651 [0ms] - Committing request context: RemoteAddrRequestContextImpl(14670479)

            +---651 [0ms] - Committing request context: RewriteRequestContextImpl(5203636)

            +---651 [0ms] - Committing request context: SetLocaleRequestContextImpl(32252426)

            +---651 [5ms (2ms), 1%, 1%] - Committing request context: SessionRequestContextImpl(6861740)

            |   `---652 [3ms, 60%, 0%] - Encoding cookie for session object

            |       `---655 [0ms] - Encrypting cookie for session object

  • Mobile Linux组织融合背后的故事

    2008-11-02 21:34:18

    有近半年没有写关于mobile linux方面的博文了,主要原因就是LiPS Forum和LiMo Foundation的融合过程中作为内部人员的言论限制。亲历了LiPS Forum的创立、发展和结束,以及与LiMo Foundation的谈判,直到最近全面参与LiMo Foundation的工作,其中有很多东西与大家分享,以弥补这长期静默的“罪过”。    法国电信Orange作为LiPS Forum的发起公司其实一直没有放弃加入LiMo Foundation的努力,刚开始的时候LiMo Foundation的创始成员(NTT DoCoMo,Vodafone,Motorola,NEC/Panasonic等)中有人明确不希望Orange成为一员,这当然是出于竞争的考虑。然而,在发展了一段时间以后,发现不但是不能够击垮LiPS Forum,而且在时间表上还有落后的危险。这时候,实用主义的精神发挥了作用,由Foundation办公室出面提出了让法国电信Orange加入LiMo Foundation 并追认为创始会员,这离LiMo成立已经相隔1年半之久了。当然这不是没有条件的,法国电信Orange必须离开LiPS Forum,这个结果也就相当于直接解体了LiPS Forum。在那个时候我个人是极力反对的,原因就是LiMo Foundation的组织和工作进展都与我们的认识相左,存在极大风险。然而,随着法国电信内部的争论的升级,最后集团决策层会议上决定加入LiMo,但是没有人提及相应的附加条件。我们并没有放弃为LiPS Forum其它成员争取更多的利益,经过几轮谈判,终于所有的LiPS Forum成员都争取到了LiMo Foundation的会员资格,要知道LiMo的会员费比LiPS Forum贵6倍。
        这一个过程尽管作为LiPS Forum的创始人,我个人会有一些失落感,但是看看结果,还是一个双赢的局面。首先,法国电信Orange从Mobile Linux的门外汉,到世界上主要支持的Mobile Linux的运营商,仅仅耗时4年,费用相对其它公司来说也就1/10,然而先后成为LiPS Forum和LiMo Foundation的创始成员、董事会成员,成功的推动Linux在手机上的标准化,并有可能在欧洲首推运营商定制Linux手机。其次,LiPS Forum的成员他们往往没有机会被那些所谓的巨头认可,但是由于他们的重要作用和已经取得的成果(LiPS的标准及其实现),成为LiMo Foundation的成员,尤其得到关注。最后, LiMo Foundation尽管巨头云集,但是还是前途未卜,只有消灭潜在威胁、广聚人气才能为成功争取时间,而且,LiPS的融合使得成员数量增加近一倍,成为独一无二的Mobile Linux组织。
        从这个融合之中,我们也发现了行业中的普遍问题。首先是缺乏反垄断意识,尽管每个大公司都有一流律师,但是在这个融合过程中,还是有人犯了低级的错误,并且有可能将LiMo Foundation陷入法律纠纷中去。简单说来,在美国和欧洲的法律下,一个组织通过给与某些条件给另一个组织的主要成员,以达到消灭那个组织减少竞争为目的的行为,就有可能触犯了反垄断法。读者可以想像,在两个组织的讨论中,那么多的邮件交互,是不是漏洞也很多呀。其次是趋炎附势、人云亦云,我惊人的发现,很多大公司在加入LiMo这个投资巨大的组织前,并没有什么仔细研究,就是老板们见个面就定下来了,加入以后为了面子和位子的问题,又要处处硬上,为的就是自圆其说。我们还是要引以为鉴,希望不要再犯同样的错误。