qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

用python做测试实现高性能测试工具(1)—序

 做过几年开发或者测试开发的人员,时常会觉得很迷茫,新功能的开发或者老功能的维护,基本是在堆代码了, 做过几年测试的朋友也会有类似的想法。性能调优或者性能测试的确很考验人分析问题、解决问题的能力,知识是否全面。本人也是第一次实现高性能的测试工具, 记录下这次diameter协议测试工具的优化过程,供大家一起学习。 有些内容涉及到具体产品,做了些改动或者单独写了测试代码演示。
  Python用来开发高性能的测试工具的确有天然的缺陷,性能差还有GIL,无法利用多线程。 但办法总比困难多,那么多大的互联网公司都使用python与实际产品中,总比我们测试的性能要求搞多了。 本文主要讲述在系统设计和架构方面的性能优化,具体算法和一些小细节的优化,请参考 http://blog.csdn.net/powerccna/article/details/8020289
  项目背景:
  实现个高性能的diameter 测试工具, 接受1000+发送1000,双向要支持到2000条消息每秒。 diameter 协议的源代码是从这里下载的 http://sourceforge.net/projects/pyprotosim/, 这个开源包还支持SMPP, RADIUS, DHCP, LDAP,  而且新增加的协议字段都可以在dictionary配置属性,不需要修改代码,实在是方便。 初始阶段我们为了实现功能,没有怎么考虑性能的问题,很多地方用的是单线程,初始性能只能支持到50 消息。硬件环境: SunFire 4170, 16 核,每核2.4 G
  Python性能优化的几个方向:
  1. 换python的解析器:常见的python解析器有pysco,pypy, cython, jython, pysco已经对python 2.7不支持了,就没有测试,据说跑的很C语言一样快。对pypy, jython做了简单测试,pypy在不同机器上可以提高到5-10倍的样子,Jython虽然可以避免python GIL的问题(因为jython是跑在java虚拟机上的),但测试看来,效率提升很少。
  2. 优化代码
  3. 改变系统架构,多线程,多进程或者协程
  方案1:  换Python解析器
  如果换Python解析器能达到性能需求是最廉价的方案了,不需要对代码做任何改动。下面代码只是为了说明pypy的效果,单独写的测试代码,在windows下运行的结果。在linux下机器上运行效果会更好些。
#!/usr/bin/env python
#coding=utf-8
import  time
def check(num):
a = list(str(num))
b = a[::-1]
if a == b:
return True
return False
def test():
all = xrange(1,10**7)
for i in all:
if check(i):
if check(i**2):
i**2
if __name__ == '__main__':
start=time.time()
test()
print time.time()-start
分别用python和pypy的运行结果
C:\Python27\python.exeD:/RCC/mp/src/test.py
14.4940001965
C:\pypy-2.1\pypy.exeD:/RCC/mp/src/test.py
4.37800002098
  可以看出来pypy的运行结果效果还是明显的,虽然能提高5倍(linux机器上),50*5, 离2000还差好远。 pypy对python 多线程的支持没有明显效果,这个在后面会提到。
  先告一段落,太长了大家看起来累,下一篇文章中将会介绍代码优化部分。

posted @ 2014-01-02 09:18 顺其自然EVO 阅读(434) | 评论 (0)编辑 收藏

Oracle SQL Loader切身实例

1.建立可执行文件:input.bat
  内容为:sqlldr userid= dsa_test/dsa_test@dsa_test bindsize=5120000  readsize=9999999 control=input.ctl errors=999999999 parallel=true
  2.建立控制文件:input.ctl
  yhq_session_120_13080704为同文件夹下的需要导入的文件,字段以逗号分开。也可以指向绝对路径,例如:infile 'I:\移动数据\yhq_session_120_13080704.txt'
  GET_CDR为要导入的表名。
  Date 'YYYYMMDD HH24:MI:SS' 是要和文件yhq_session_120_13080704里面的日期格式对应。
  PS:如果导入文件没有后缀,默认后缀为.dat,所以最好明确后缀名
  内容为:
Load data
infile 'yhq_session_120_13080704.txt'
Append into table GET_CDR
FIELDS TERMINATED BY ","  OPTIONALLY ENCLOSED BY '"'
(START_TIME Date 'YYYYMMDD HH24:MI:SS' ,
GTPXID ,
APN ,
MSISDN ,
IMEI ,
MOBILE_VENDOR ,
MOBILE_TYPE ,
MOBILE_SOFT  )
  3.如果上述文件在D盘的sqlldr目录,则需要输入CMD,打开命令窗口
  4.改变盘符,输入D:回车
  5.转到sqlldr目录,输入cd sqlldr回车
  6.输入input.bat
  然后就开始导入数据了!!!

posted @ 2014-01-02 09:17 顺其自然EVO 阅读(169) | 评论 (0)编辑 收藏

如何用Java将excel数据导入数据库

最近写了点关于将excel导入数据库的代码,当然也可以看做是对前面所介绍的小项目进行补充所做的准备。
  我一般都是先完成功能,然后将其封装成块,再添加到项目中,个人癖好不值得借鉴。项目中关于解析excel数据的方式请参考:http://blog.csdn.net/trsli/article/details/17392943
  这是已经成功插入数据化数据库中数据的记录,我新建的表为db.                            这是在控制台的数据输入
  很多时候拼接字符串是很多项目必须做的,该代码中我拼接了不少sql语句,也许有更简单的方式,但是我现在只能想到这一步。
/**将execl数据导入数据库
* @author trsli
* */
public class CreateDBTable {
private static Connection conn;
private static String sql="";
private static StringBuffer buf=new StringBuffer();
static{
conn=DBConnection.getConnection();
}
public static void main(String[] args) {
//数据.xls文件路径
System.out.println("输入文件路径:");
String filename=new Scanner(System.in).nextLine();
//获取需要插入数据库的数据内容
Object[][] contents=new PoiUtil().getmessage(filename);
//获取数据库创建表格的字段名
Object[] titles=new PoiUtil().gettitles(filename);
System.out.println("输入数表格名:");
String fname=new Scanner(System.in).nextLine();
try {
String ziduan="";
String blank="";
PreparedStatement stmt=conn.prepareStatement(sql);
buf.append("create table "+fname+"( id int primary key auto_increment");
//拼接字符串,主要是为了完全实现动态创建数据表格以及后期插入数据
<span style="color:#ff6666;">for(int i=0;i<titles.length;i++){
buf.append(","+titles[i]+"  varchar(20)");
if(i==titles.length-1){//字符串末尾没有“,”
ziduan+=titles[i]+"";
blank+="?";
}else{
ziduan+=titles[i]+",";
blank+="?,";
}
}
</span>         //sql数据拼装完成
sql="insert into "+fname+"("+ziduan+") values ("+ blank+")";
buf.append(" );");
stmt.executeUpdate(buf.toString());
System.out.println("预处理...");
try {
Thread.sleep(2000);//用于保证数据库建表操作完成
System.out.println("建表成功...");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
<span style="color:#ff6666;">for(int i=0;i<contents.length;i++){
Object[] content=contents[i];//获取一行数据
PreparedStatement insert=conn.prepareStatement(sql);
for(int j=0;j<content.length;j++){
insert.setString(j+1, content[j].toString());//预加载数据
}
insert.executeUpdate();//插入数据
System.out.println("第"+i+"行成功...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
</span>         }
System.out.println("插入数据完成");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

 整个代码很简单,可以从中提取出需要的方法,用于其它需要的地方,而这就是未来需要做的。个人感觉还有许多需要改进的地方,当然自从开始研究POI以来,我还没有对其进行更加深入的理解。比如红色代码块可以用批处理模式:addbatch方法。代码中的Thread.sleep()显得有点多余,主要原因是excel中德数据太少。
  这是数据库中数据的显示。  以下是原数据:
  最近公司安排的事情做得有点吃力,所以写点代码调节一下枯燥的心情。

posted @ 2014-01-02 09:04 顺其自然EVO 阅读(265) | 评论 (0)编辑 收藏

Magento数据库配置选项,以及mysql 读写分离

1.数据库配置
  [mysqld]
key_buffer = 512M
max_allowed_packet = 64M
table_cache = 512
sort_buffer_size = 4M
read_buffer_size = 4M
read_rnd_buffer_size = 2M
myisam_sort_buffer_size = 64M
tmp_table_size = 128M
query_cache_size = 96M
query_cache_type = 1
thread_cache_size = 8
max_connections = 400
wait_timeout = 300
  2.innodb
#innodb_data_home_dir = C:\mysql\data/
#innodb_data_file_path = ibdata1:10M:autoextend
#innodb_log_group_home_dir = C:\mysql\data/
#innodb_log_arch_dir = C:\mysql\data/
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
#innodb_buffer_pool_size = 16M
#innodb_additional_mem_pool_size = 2M
# Set .._log_file_size to 25 % of buffer pool size
#innodb_log_file_size = 5M
#innodb_log_buffer_size = 8M
#innodb_flush_log_at_trx_commit = 1
#innodb_lock_wait_timeout = 50
  example1:
innodb_additional_mem_pool_size = 16M
innodb_log_buffer_size = 8M
innodb_log_file_size = 512M
innodb_log_files_in_group = 2
innodb_buffer_pool_size = 3G
innodb_data_file_path = ibdata1:3G;ibdata2:1G:autoextend
innodb_autoextend_increment=512


  example2:
# Run a 64-bit operating system. Do not exceed 2GB memory for the following
# combination on 32-bit systems:
# innodb_buffer_pool_size + key_buffer_size + max_connections*(sort_buffer_size +
# read_buffer_size + binlog_cache_size) + max_connections*2MB
# On dedicated db server assign up to 80% of free memory to innodb buffer
# On combined web/db server take into account apache instances and php
innodb_buffer_pool_size         = 768M  #Data Page Memory Buffer
# Table metadata requires 2-16M, Magento only has abt 330 tables
innodb_additional_mem_pool_size = 2M    #Data Dictionary < 16M
# SHOW GLOBAL STATUS Innodb_log_waits should be 0 or the next setting
# innodb_log_file_size is too small. Holds changed data for lazy write to
# innodb database. To change size, database must be flushed to disk, database
# backed up, mysqld server must be downed, log files renamed, change
# my.cnf and mysqld brought back up. Log files will be recreated in
# proper number and size
innodb_log_file_size            = 100M  #Transaction Log up to 1/4 Buffer Pool
#innodb_log_files_in_group      = 2     #Default is 2
# Buffer for transactions to be written to log file
innodb_log_buffer_size          = 2M    #Transaction Memory Buffer 1-8M
#Recommended (2xcores)+disks, KEEP LOW < 16 More is not better tune for
#best performance
innodb_thread_concurrency       = 3
#Set this up before you install Magento. Create primary innodb table at 2GB
#and secondary autoextend table for growth
#Changing this after you've gone live requires eliminating the ibdata files and log files
innodb_data_file_path = ibdata1:2048M;ibdata2:50M:autoextend
#Amount to add on autoextend. Keep this large to keep blocks in file contiguous
innodb_autoextend_increment = 512M
  3.mysql读写分离配置
<resources>
<db>
<table_prefix><![CDATA[]]></table_prefix>
</db>
<default_setup>
<connection>
<host><![CDATA[localhost]]></host>
<username><![CDATA[root]]></username>
<password><![CDATA[]]></password>
<dbname><![CDATA[mg_wailian]]></dbname>
<initStatements><![CDATA[SET NAMES utf8]]></initStatements>
<model><![CDATA[mysql4]]></model>
<type><![CDATA[pdo_mysql]]></type>
<pdoType><![CDATA[]]></pdoType>
<active>1</active>
</connection>
</default_setup>
<default_read>
<connection>
<host><![CDATA[localhost]]></host>
<username><![CDATA[root]]></username>
<password><![CDATA[]]></password>
<dbname><![CDATA[mg_wailian]]></dbname>
<initStatements><![CDATA[SET NAMES utf8]]></initStatements>
<model><![CDATA[mysql4]]></model>
<type><![CDATA[pdo_mysql]]></type>
<pdoType><![CDATA[]]></pdoType>
<active>1</active>
</connection>
</default_read>
</resources>
  3.分离读写数据库,然后主从同步,是一个很好的选择。

posted @ 2014-01-02 09:02 顺其自然EVO 阅读(291) | 评论 (0)编辑 收藏

Windows下vmware虚拟Linux环境

 最近学习经常要在windows下进行,但是又离不开Linux环境,于是想到使用强大的虚拟机虚拟一套Linux工作环境,然后通过Xshell或者putty接入。于是立刻动手安装了Ubuntu Server 12,并进行了相应配置,最终实现了我的目的。以下是配置过程:
  1  vmware虚拟机设置中网络适配器选择桥接模式。通过查看资料貌似更多人使用的是NAT模式,本着实用原则就没有再深究这种模式的配置方式,如有需要再做补充。
  2  配置/etc/network/interfaces。以下是我的配置文件:
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
auto eth0
iface eth0 inet static
address 192.168.1.200// 与物理机在同一网段且不与其他IP冲突的IP即可
netmask 255.255.255.0
network 192.168.1.0// 暂不清楚这个是做什么用的
broadcast 192.168.1.255// 同样与物理机在同一网段的广播地址
gateway 192.168.1.1// 物理机所在局域网的真实网关地址
# dns-* options are implemented by the resolvconf package, if installed
dns-nameservers 218.108.248.245// 真实的DNS IP
  修改完配置文件后需要重启网络:sudo service networking restart。修改完Linux的配置后已经可以ping通外网了,但是虚拟机和物理机之间互通还有问题。虚拟机无法ping通物理机一般是由于windows防火墙的原因;物理机无法ping通虚拟机通过可以通过禁用vmware的VMware Network Adapter VMnet1和VMware Network Adapter VMnet8这两个连接解决,但是具体原因暂时不是十分清楚。这里务必要保证物理机可以ping通虚拟机的IP地址。
  3  安装openssl-server。执行命令sudo apt-get install openssl-server,apt-get工具会自动安装和配置好ssh服务。安装完成后通过sudo service ssh命令重启ssh服务。
  安装openssl-server如提示找不到该包,可以通过执行sudo apt-get  update解决。
  重启ssh服务如遇到Could not load host key: /etc/ssh/ssh_host_rsa_key这类错误可通过执行命令ssh-keygen -t rsa -b 2048 -f /etc/ssh/ssh_host_rsa_key解决。具体参考:http://blog.csdn.net/hyholine/article/details/7362073。
  通过上述配置,就可以通过putty或者Xshell正常连接到虚拟的Linux环境了。

posted @ 2014-01-02 08:59 顺其自然EVO 阅读(209) | 评论 (0)编辑 收藏

LoadRunner中的Web 函数列表

web_custom_request
允许您使用 HTTP 支持的任何方法来创建自定义 HTTP 请求。
web_image
在定义的图像上模拟鼠标单击。
web_link
在定义的文本链接上模拟鼠标单击。
web_submit_data
执行“无条件”或“无上下文”的表单提交。
web_submit_form
模拟表单的提交。
web_url
加载由“URL”属性指定的 URL。
  身份验证函数
web_set_certificate
使 Vuser 使用在 Internet Explorer 注册表中列出的特定证书。
web_set_certificate_ex
指定证书和密钥文件的位置和格式信息。
web_set_user
指定 Web 服务器的登录字符串和密码,用于 Web 服务器上已验证用户身份的区域。
缓存函数
web_cache_cleanup
清除缓存模拟程序的内容。
web_dump_cache
将资源转储到浏览器缓存中。
web_load_cache
加载缓存的内容。
  检查函数
web_find
在 HTML 页内搜索指定的文本字符串。
web_global_verification
在所有后面的 HTTP 请求中搜索文本字符串。
web_image_check
验证指定的图像是否存在于 HTML 页内。
web_reg_find
在后面的 HTTP 请求中注册对 HTML 源或原始缓冲区中文本字符串的搜索。
  连接定义函数
web_disable_keep_alive
禁用 Keep-Alive HTTP 连接。
web_enable_keep_alive
启用 Keep-Alive HTTP 连接。
web_set_connections_limit
设置 Vuser 在运行脚本时可以同时打开连接的最大数目。


 并发组函数
web_concurrent_end
标记并发组的结束。
web_concurrent_start
标记并发组的开始。
  Cookie 函数
web_add_cookie
添加新的 Cookie 或修改现有的 Cookie。
web_cleanup_cookies
删除当前由 Vuser 存储的所有 Cookie。
web_remove_cookie
删除指定的 Cookie。
  关联函数
web_create_html_param
将 HTML 页上的动态信息保存到参数中。(LR 6.5 及更低版本)
web_create_html_param_ex
基于包含在 HTML 页内的动态信息创建参数(使用嵌入边界)。(LR 6.5 及更低版本)
web_reg_save_param
基于包含在 HTML 页内的动态信息创建参数(不使用嵌入边界)。
web_set_max_html_param_len
设置已检索的动态 HTML 信息的最大长度。
  筛选器函数
web_add_filter
设置在下载时包括或排除 URL 的条件。
web_add_auto_filter
设置在下载时包括或排除 URL 的条件。
web_remove_auto_filter
禁用对下载内容的筛选。
  标头函数
web_add_auto_header
向所有后面的 HTTP 请求中添加自定义标头。
web_add_header
向下一个 HTTP 请求中添加自定义标头。
web_cleanup_auto_headers
停止向后面的 HTTP 请求中添加自定义标头。
web_remove_auto_header
停止向后面的 HTTP 请求中添加特定的标头。
web_revert_auto_header
停止向后面的 HTTP 请求中添加特定的标头,但是生成隐性标头。
web_save_header
将请求和响应标头保存到变量中。
  代理服务器函数
web_set_proxy
指定将所有后面的 HTTP 请求定向到指定的代理服务器。
web_set_proxy_bypass
指定 Vuser 直接访问(即不通过指定的代理服务器访问)的服务器列表。
web_set_proxy_bypass_local
指定 Vuser 对于本地 (Intranet) 地址是否应该避开代理服务器。
web_set_secure_proxy
指定将所有后面的 HTTP 请求定向到服务器。
  回放函数
web_set_max_retries
设置操作步骤的最大重试次数。
web_set_timeout
指定 Vuser 等待执行指定任务的最长时间。


其他函数
web_convert_param
将 HTML 参数转换成 URL 或纯文本。
web_get_int_property
返回有关上一个 HTTP 请求的特定信息。
web_report_data_point
指定数据点并将其添加到测试结果中。
web_set_option
在非 HTML 资源的编码、重定向和下载区域中设置 Web 选项。
web_set_sockets_option
设置套接字的选项。
  控制类型函数
除了 Web Vuser 函数以外,下列控制函数也可能会出现在 Vuser 脚本中:
lr_start_transaction
标记事务的开始以用于性能分析或优化。
lr_end_transaction
标记事务的结束以用于性能分析或优化。
lr_rendezvous
在 Vuser 脚本中设置集合点。
lr_think_time
暂停 Vuser 脚本中命令之间的执行。
版权声明:本文出自 wq19860122 的51Testing软件测试博客:http://www.51testing.com/?631118
原创作品,转载时请务必以超链接形式标明本文原始出处、作者信息和本声明,否则将追究法律责任。

posted @ 2013-12-27 11:09 顺其自然EVO 阅读(641) | 评论 (0)编辑 收藏

数据库与服务器安全选项拾遗

 之前总结过sql注入的一些特征。这里总结一下数据库的内部特征。和安全选项。
  MySQL
  权限划分
  mysql用户的权限,大体来说比较简单,分别存储于这几个表中
mysql.User,mysql.db,mysql.Host,mysql.table_priv,mysql.column_priv
  因为存取频繁,所以这几个表的数据存在内存中,更新数据后使用,语句来进行内存更新
  当然执行这个命令需要reload权限
FLUSH PRIVILEGES
  用户登录时需检查,mysql.user中的user host pass 三个字段,如果允许任何主机外部链接可以吧host设置成%
  用户登录通过后,mysql会自上而下的检查用户权限,首先在mysql.user中读取对应用户的权限。
  其中关于用户权限的字段大概有这些,除去一些常规的不表,比较重要的是
  file_priv 这个影响到了mysql读写文件的利用
  grant_priv 的用户可以吧自己拥有的权限付给其他用户
  process_priv 的用户可以通过SHOW PROCESSLIST查询所用用户的查询进程并kill,普通用户只可以查询自己的
  super_priv的用户允许改变set变量,修改用户查询
Select_priv
Insert_priv
Update_priv
Delete_priv
Create_priv
Drop_priv
Reload_priv
Shutdown_priv
Process_priv
File_priv
Grant_priv
References_priv
Index_priv
Alter_priv
Show_db_priv
Super_priv
Create_tmp_table_priv
Lock_tables_priv
Execute_priv
Repl_slave_priv
Repl_client_priv
Create_view_priv
Show_view_priv
Create_routine_priv
Alter_routine_priv
Create_user_priv
 另外 super file 等管理权限后面不能加数据库,只能以这种形式授权
  grant super on *.* to xxx@xxxxx;
  而select等增删改查的权限,可以指定数据库来添加
  grant select on pyt.* to ‘p1′@’localhost’;
  其中最低的权限是usage权限,相当于只有一个连接的权限。使用create user 建立的用户,默认为usage权限
  但是此权限貌似有information_schema表的select权限,其中host为允许连接的主机名
  CREATE USER 'username'@'host' IDENTIFIED BY 'password'
  查询一个用户的权限只需要
  CREATE USER 'username'@'host' IDENTIFIED BY 'password'
  安全选项
  mysql启动的时候,也有一些安全选项,可以起到提高mysql安全性的功能
  具体可以看官方文档
  http://dev.mysql.com/doc/refman/5.5/en/server-options.html#option_mysqld_allow-suspicious-udfs
  死四个安全选项
  http://database.51cto.com/art/201005/199939.htm
  提高安全设置
  http://www.mianwww.com/html/2009/02/2926.html
  六个安全选项
  http://news.zdnet.com.cn/zdnetnews/2008/0124/718026.shtml
  关于安全的文档
  http://dev.mysql.com/doc/refman/5.1/zh/database-administration.html
  PHP
  安全选项
  Safe Mode
  这个选项也是php常用的安全选项,开启他之后服务器会对文件读写,执行文件,改变php环境变量,文件包含等功能进行比较严格的限制。
  文件读写
  开启SafeMode之后,如果进行读写文件操作PHP检查当前用户是否是文件所有者,如果php被分配到一个比较低权限的账户,读写文件会比较困难。
  以下这些函数会受到影响
  chdir , move_uploaded_file, chgrp, parse_ini_file, chown, rmdir, copy, rename, fopen, require, highlight_file, show_source, include, symlink, link, touch, mkdir, unlink
  运行文件执行系统命令
  在执行系统命令的时候,只有safe_mode_exec_dir这个文件夹下的程序可以被执行。执行的指令会发送给escapeshellcmd进行过滤。
  受影响的函数
  exec, shell_exec, passthru, system, popen
  另外,重音符也会被禁止。
  环境变量
  改变环境变量的函数也会被禁止
  putenv,set_time_limit, set_include_path
  如果想设置安全模式下可以改变的环境变量,需要这样safe_mode_allowed_env_vars
  文件包含
  文件包含的话同样也是需要safe_mode_include_dir来设定目录
  expose_php
  这个安全选项,会防止response包中泄露PHP版本信息,比如包头信息中通常会包含
  Server: Apache/1.3.33 (Unix) PHP/5.0.3 mod_ssl/2.8.16
  OpenSSL/0.9.7c
  但如果expose_php开启的话,PHP的版本信息将不包含在上面的头信息里。
  AddType application/x-httpd
  有的时候你可能会觉得php的后缀不过瘾,那么可以在httpd.conf 中找到 AddTYpe这行,添加可供解析的后缀名。
  AddType application/x-httpd .html .htm .txt .asp
  这种方法也可以用来留后门。
  open_basedir
  这个选项可以规定用户只可以访问规定目录内的文件,这个选项并不和safe mode冲突
  disable_functions
  这个选项可以用来禁用一些函数
  disable_functions = eval
  当然,同样的你能够使用 disable_classes 选项来关闭对一些类的访问。
  magic_quotes_gpc
  大家常说的加引号的选项。
  display_errors
  大家常说的显错,如果被关闭的话,那就只能盲注啦~。也可以通过log_errors设置输出到文件。

posted @ 2013-12-27 11:04 顺其自然EVO 阅读(181) | 评论 (0)编辑 收藏

Linux操作系统启动过程详解

  如果你对Linux操作系统有一定的了解,想对其更深层次的东西做进一步探究。这当中就包括系统的启动流程、文件系统的组成结构、基于动态库和静态库的程序在执行时的异同、协议栈的架构和原理、驱动程序的机制等等。
  其中Linux操作系统启动过程肯定是大家最有兴趣了解的,这里在综合了现有网上大家智慧的基础上,基于2.6.32的内核的CentOS 6.0系统,对Linux的启动流程做了些分析,希望对大家有所帮助。
  OK,我们言归正传。对于一台安装了Linux系统的主机来说,当用户按下开机按钮时,一共要经历以下几个过程,如图:
  其中,每个过程都执行了自己该做的初始化部分的事情,有些过程又可分为好几个子过程。接下来,我们就对每个阶段做一个详细分析和讲解。
  一、BIOS自检
  稍有计算机基础的人都应该听过BIOS(Basic Input / Output System),又称基本输入输出系统,可以视为是一个永久地记录在ROM中的一个软件,是操作系统输入输出管理系统的一部分。早期的BIOS芯片确实是”只读”的,里面的内容是用一种烧录器写入的,一旦写入就不能更改,除非更换芯片。现在的主机板都使用一种叫Flash EPROM的芯片来存储系统BIOS,里面的内容可通过使用主板厂商提供的擦写程序擦除后重新写入,这样就给用户升级BIOS提供了极大的方便。
  BIOS的功能由两部分组成,分别是POST码和Runtime服务。POST阶段完成后它将从存储器中被清除,而Runtime服务会被一直保留,用于目标操作系统的启动。BIOS两个阶段所做的详细工作如下:
  步骤1:上电自检POST(Power-on self test),主要负责检测系统外围关键设备(如:CPU、内存、显卡、I/O、键盘鼠标等)是否正常。例如,最常见的是内存松动的情况,BIOS自检阶段会报错,系统就无法启动起来;
  步骤2:步骤1成功后,便会执行一段小程序用来枚举本地设备并对其初始化。这一步主要是根据我们在BIOS中设置的系统启动顺序来搜索用于启动系统的驱动器,如硬盘、光盘、U盘、软盘和网络等。我们以硬盘启动为例,BIOS此时去读取硬盘驱动器的第一个扇区(MBR,512字节),然后执行里面的代码。实际上这里BIOS并不关心启动设备第一个扇区中是什么内容,它只是负责读取该扇区内容、并执行。
  至此,BIOS的任务就完成了,此后将系统启动的控制权移交到MBR部分的代码。
  PS:在个人电脑中,Linux的启动是从0xFFFF0地址开始的。

  如果你对Linux操作系统有一定的了解,想对其更深层次的东西做进一步探究。这当中就包括系统的启动流程、文件系统的组成结构、基于动态库和静态库的程序在执行时的异同、协议栈的架构和原理、驱动程序的机制等等。
  其中Linux操作系统启动过程肯定是大家最有兴趣了解的,这里在综合了现有网上大家智慧的基础上,基于2.6.32的内核的CentOS 6.0系统,对Linux的启动流程做了些分析,希望对大家有所帮助。
  OK,我们言归正传。对于一台安装了Linux系统的主机来说,当用户按下开机按钮时,一共要经历以下几个过程,如图:
  其中,每个过程都执行了自己该做的初始化部分的事情,有些过程又可分为好几个子过程。接下来,我们就对每个阶段做一个详细分析和讲解。
  一、BIOS自检
  稍有计算机基础的人都应该听过BIOS(Basic Input / Output System),又称基本输入输出系统,可以视为是一个永久地记录在ROM中的一个软件,是操作系统输入输出管理系统的一部分。早期的BIOS芯片确实是”只读”的,里面的内容是用一种烧录器写入的,一旦写入就不能更改,除非更换芯片。现在的主机板都使用一种叫Flash EPROM的芯片来存储系统BIOS,里面的内容可通过使用主板厂商提供的擦写程序擦除后重新写入,这样就给用户升级BIOS提供了极大的方便。
  BIOS的功能由两部分组成,分别是POST码和Runtime服务。POST阶段完成后它将从存储器中被清除,而Runtime服务会被一直保留,用于目标操作系统的启动。BIOS两个阶段所做的详细工作如下:
  步骤1:上电自检POST(Power-on self test),主要负责检测系统外围关键设备(如:CPU、内存、显卡、I/O、键盘鼠标等)是否正常。例如,最常见的是内存松动的情况,BIOS自检阶段会报错,系统就无法启动起来;
  步骤2:步骤1成功后,便会执行一段小程序用来枚举本地设备并对其初始化。这一步主要是根据我们在BIOS中设置的系统启动顺序来搜索用于启动系统的驱动器,如硬盘、光盘、U盘、软盘和网络等。我们以硬盘启动为例,BIOS此时去读取硬盘驱动器的第一个扇区(MBR,512字节),然后执行里面的代码。实际上这里BIOS并不关心启动设备第一个扇区中是什么内容,它只是负责读取该扇区内容、并执行。
  至此,BIOS的任务就完成了,此后将系统启动的控制权移交到MBR部分的代码。
  PS:在个人电脑中,Linux的启动是从0xFFFF0地址开始的。

另外一个概念:initramfs
  initramfs 是在 kernel 2.5中引入的技术,实际上它的含义就是:在内核镜像中附加一个cpio包,这个cpio包中包含了一个小型的文件系统,当内核启动时,内核将这个 cpio包解开,并且将其中包含的文件系统释放到rootfs中,内核中的一部分初始化代码会放到这个文件系统中,作为用户层进程来执行。这样带来的明显的好处是精简了内核的初始化代码,而且使得内核的初始化过程更容易定制。
  疑惑的是:我的内核是2.6.32-71.el6.i686版本,但在我的/boot分区下面却存在的是/boot/initramfs-2.6.32-71.el6.i686.img类型的文件,没搞明白,还望高人解惑。我只知道在2.6内核中支持两种格式的initrd,一种是2.4内核的文件系统镜像image-initrd,一种是cpio格式。接下来我们就来探究一下initramfs-2.6.32-71.el6.i686.img里到底放了那些东西。
  在tmp文件夹中解压initrd.img里的内容:
  如果initrd.img文件的格式显示为“initrd.img:ISO 9660 CD-ROM filesystem data”,则可直接输入命令“mount -o loop initrd.img /mnt/test”进行挂载。
  通过上的分析和我们的验证,我们确实得到了这样的结论:
  grub的stage2将initrd加载到内存里,让后将其中的内容释放到内容中,内核便去执行initrd中的init脚本,这时内核将控制权交给了init文件处理。我们简单浏览一下init脚本的内容,发现它也主要是加载各种存储介质相关的设备驱动程序。当所需的驱动程序加载完后,会创建一个根设备,然后将根文件系统rootfs以只读的方式挂载。这一步结束后,释放未使用的内存,转换到真正的根文件系统上面去,同时运行/sbin/init程序,执行系统的1号进程。此后系统的控制权就全权交给/sbin/init进程了。
  四、初始化系统
  经过千辛万苦的跋涉,我们终于接近黎明的曙光了。接下来就是最后一步了:初始化系统。/sbin/init进程是系统其他所有进程的父进程,当它接管了系统的控制权先之后,它首先会去读取/etc/inittab文件来执行相应的脚本进行系统初始化,如设置键盘、字体,装载模块,设置网络等。主要包括以下工作:
  1. 执行系统初始化脚本(/etc/rc.d/rc.sysinit),对系统进行基本的配置,以读写方式挂载根文件系统及其它文件系统,到此系统算是基本运行起来了,后面需要进行运行级别的确定及相应服务的启动。rc.sysinit所做的事情(不同的Linux发行版,该文件可能有些差异)如下:
  (1)获取网络环境与主机类型。首先会读取网络环境设置文件”/etc/sysconfig/network”,获取主机名称与默认网关等网络环境。
  (2)测试与载入内存设备/proc及usb设备/sys。除了/proc外,系统会主动检测是否有usb设备,并主动加载usb驱动,尝试载入usb文件系统。
  (3)决定是否启动SELinux。
  (4)接口设备的检测与即插即用(pnp)参数的测试。
  (5)用户自定义模块的加载。用户可以再”/etc/sysconfig/modules/*.modules”加入自定义的模块,此时会加载到系统中。
  (6)加载核心的相关设置。按”/etc/sysctl.conf”这个文件的设置值配置功能。
  (7)设置系统时间(clock)。
  (8)设置终端的控制台的字形。
  (9)设置raid及LVM等硬盘功能。
  (10)以方式查看检验磁盘文件系统。
  (11)进行磁盘配额quota的转换。
  (12)重新以读取模式载入系统磁盘。
  (13)启动quota功能。
  (14)启动系统随机数设备(产生随机数功能)。
  (15)清楚启动过程中的临时文件。
  (16)将启动信息加载到”/var/log/dmesg”文件中。
  当/etc/rc.d/rc.sysinit执行完后,系统就可以顺利工作了,只是还需要启动系统所需要的各种服务,这样主机才可以提供相关的网络和主机功能,因此便会执行下面的脚本。
  2. 执行/etc/rc.d/rc脚本。该文件定义了服务启动的顺序是先K后S,而具体的每个运行级别的服务状态是放在/etc/rc.d/rc*.d(*=0~6)目录下,所有的文件均是指向/etc/init.d下相应文件的符号链接。rc.sysinit通过分析/etc/inittab文件来确定系统的启动级别,然后才去执行/etc/rc.d/rc*.d下的文件。
  /etc/init.d-> /etc/rc.d/init.d
  /etc/rc ->/etc/rc.d/rc
  /etc/rc*.d ->/etc/rc.d/rc*.d
  /etc/rc.local-> /etc/rc.d/rc.local
  /etc/rc.sysinit-> /etc/rc.d/rc.sysinit
  也就是说,/etc目录下的init.d、rc、rc*.d、rc.local和rc.sysinit均是指向/etc/rc.d目录下相应文件和文件夹的符号链接。我们以启动级别3为例来简要说明一下。
  /etc/rc.d/rc3.d目录,该目录下的内容全部都是以 S 或 K 开头的链接文件,都链接到”/etc/rc.d/init.d”目录下的各种shell脚本。S表示的是启动时需要start的服务内容,K表示关机时需要关闭的服务内容。/etc/rc.d/rc*.d中的系统服务会在系统后台启动,如果要对某个运行级别中的服务进行更具体的定制,通过chkconfig命令来操作,或者通过setup、ntsys、system-config-services来进行定制。如果我们需要自己增加启动的内容,可以在init.d目录中增加相关的shell脚本,然后在rc*.d目录中建立链接文件指向该shell脚本。这些shell脚本的启动或结束顺序是由S或K字母后面的数字决定,数字越小的脚本越先执行。例如,/etc/rc.d/rc3.d /S01sysstat就比/etc/rc.d/rc3.d /S99local先执行。  3. 执行用户自定义引导程序/etc/rc.d/rc.local。其实当执行/etc/rc.d/rc3.d/S99local时,它就是在执行/etc/rc.d/rc.local。S99local是指向rc.local的符号链接。就是一般来说,自定义的程序不需要执行上面所说的繁琐的建立shell增加链接文件的步骤,只需要将命令放在rc.local里面就可以了,这个shell脚本就是保留给用户自定义启动内容的。
  4. 完成了系统所有的启动任务后,linux会启动终端或X-Window来等待用户登录。tty1,tty2,tty3…这表示在运行等级1,2,3,4的时候,都会执行”/sbin/mingetty”,而且执行了6个,所以linux会有6个纯文本终端,mingetty就是启动终端的命令。
  除了这6个之外还会执行”/etc/X11/prefdm-nodaemon”这个主要启动X-Window
  至此,系统就启动完毕了。
  PS: 最后附上一张非常完整的系统启动流程图,适合各个水平阶段的读者。

posted @ 2013-12-27 11:02 顺其自然EVO 阅读(282) | 评论 (0)编辑 收藏

在Maven里使用TestNG的方法的单元测试实例

要在Maven里面使用TestNG很简单。去TestNG的网站上可以找到非常详细的一段代码,将下列代码加入<dependencies></dependencies>标签之间:
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.1.1</version>
<scope>test</scope>
</dependency>
  当然,这是对应的TestNG 6.1.1版本。其它版本的TestNG,应当只需要改动一下版本号即可。
  在src/main/java文件夹中书写Main.java文件如下:
package org.silentmusicbox.justanothermavenproject;
public class Main {
public String sayHello() {
return "Hallo Welt!";
}
public static void main(String [] args) {
Main objOfMain = new Main();
System.out.println(objOfMain.sayHello());
}
}
  在src/test/java文件夹中书写TestMain.java文件如下:
packageorg.silentmusicbox.justanothermavenproject;
importorg.testng.Assert;
importorg.testng.annotations.BeforeMethod;
importorg.testng.annotations.Test;
publicclassTestMain{
privateMainm;
@BeforeMethod
publicvoidinit(){
m=newMain();
}
@Test
publicvoidtestSayHello(){
Assert.assertEquals(m.sayHello(),"HalloWelt!");
}
}
  运行mvn test,一切正常。如果将sayHello()方法中的返回值改为"Hello World!"则报错。说明TestNG已经正常运行了。


posted @ 2013-12-26 11:06 顺其自然EVO 阅读(695) | 评论 (0)编辑 收藏

部署Selenium Grid + Selenium RC + Webdriver

 Grid Hub:Ubuntu12.10_x64(自动化脚本所在的机器,也是selenium server所在的机器)
  Selenium RC:Windows 7_x32(接收hub的命令并启动浏览器运行测试脚本的机器,称为节点)
  1、Hub需要安装的软件及包:Python2.7.3+Selenium2+Java1.7.0_25+selenium-server-2.39.0.jar+chromedriver_linux64.zip
  2、RC需要的软件及包:Java1.7.0_25+selenium-server-standalone-2.39.0.jar+Firefox+Chrome28+IEDriverServer_Win32_2.39.0.zip+chromedriver_win32_13.0.775.0
  3、Grid Hub安装步骤
  Python(Ubuntu自带了,无需额外安装)
  安装setuptools
  下载路径:http://pypi.python.org/pypi/setuptools
  安装:sudo python  easy_install.py install
  安装pip
  下载 pip-1.4.1.tar.gz
  安装:sudo python setup.py install
  在线安装selenium
  pip install selenium
  Java(Ubuntu自带了,无需额外安装)
  下载selenium-server-2.39.0.jar
  解压selenium-server-2.39.0.zip,在selenium-server-2.39.0目录下找到 selenium-server-standalone-2.39.0.jar
  下载chromedriver_linux64.zip。解压得到chromedriver,用root用户将chromedriver复制到/usr/bin目录
  进入selenium-server-standalone所在的目录
  在终端输入java -jar selenium-server-standalone-2.39.0.jar -role hub启动Grib Hub
  浏览器端可打开http://localhost:4444/grid/console页面
  终端显示如下:
irene@shuixian:~/Downloads/selenium-2.39.0$ java -jar selenium-server-standalone-2.39.0.jar -role hubDec 24, 2013 6:28:00 PM org.openqa.grid.selenium.GridLauncher main
INFO: Launching a selenium grid server
2013-12-24 18:28:01.513:INFO:osjs.Server:jetty-7.x.y-SNAPSHOT
2013-12-24 18:28:01.564:INFO:osjsh.ContextHandler:started o.s.j.s.ServletContextHandler{/,null}
2013-12-24 18:28:01.571:INFO:osjs.AbstractConnector:Started SocketConnector@0.0.0.0:4444
  4、Selenium RC安装步骤(Windows 7)
  下载安装JAVA
  下载selenium-server-standalone-2.39.0.jar,同上
  下载并安装Firefox
  下载并安装Chrome,版本33会有错,可下载28这个版本
  下载IEDriverServer.exe,解压包并将IEDriverServer.exe复制到IE的安装目录下如:C:\Program Files\internet Explorer
  把C:\Program Files\internet Explorer增加到机器的环境变量PATH中,即编辑PATH,在后面加上;C:\Program Files\internet Explorer
  下载chromedriver_win32_13.0.775.0.zip,解压得到chromedriver.exe,将chromedriver.exe放在chrome的安装目录如:C:\Users\irene\AppData\Local\Google\Chrome\Application。


把C:\Users\irene\AppData\Local\Google\Chrome\Application追加到机器的环境变量PATH中
  将Selenium RC注册到Grib Hub中,并指定浏览器为IE
java -jar selenium-server-standalone-2.39.0.jar -role node -hub http://192.168.88.183:4444/register -browser browserName="internet explorer" naxInstance=1,platform=WINDOWS
  将Selenium RC注册到Grib Hub中,并指定浏览器为Firefox
java -jar selenium-server-standalone-2.39.0.jar -role node -hub http://192.168.88.183:4444/register -browser browserName="firefox" naxInstance=1,platform=WINDOWS
  将Selenium RC注册到Grib Hub中,并指定浏览器为Chrome
java -jar selenium-server-standalone-2.39.0.jar -role node -hub http://192.168.88.183:4444/register -browser browserName="chrome" naxInstance=1,platform=WINDOWS
  5、Selenium RC的启动(与Grid Hub在同台机器)
  将Selenium RC注册到Grib Hub中,并指定浏览器为Firefox
java -jar selenium-server-standalone-2.39.0.jar -role node -hub http://localhost:4444/register -browser browserName="firefox" naxInstance=1,platform=LINUX
  将Selenium RC注册到Grib Hub中,并指定浏览器为Chrome
java -jar selenium-server-standalone-2.39.0.jar -role node -hub http://localhost:4444/register -browser browserName="chrome" naxInstance=1,platform=LINUX
  6、示例脚本
from selenium import webdriver
from selenium.webdriver.remote.command import Command
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
browser = webdriver.Remote('http://192.168.88.183:4444/wd/hub', DesiredCapabilities.FIREFOX)
browser.get("http://www.baidu.com")
browser.find_element_by_name("wd").send_keys("scutech")
browser.find_element_by_id("su").click()
browser.quit()
  7、注意:运行脚本前Selenium Grid 和Selenium RC都要启动。Hub只有一个,RC可以有多个。

posted @ 2013-12-26 11:04 顺其自然EVO 阅读(1316) | 评论 (0)编辑 收藏

仅列出标题
共394页: First 上一页 165 166 167 168 169 170 171 172 173 下一页 Last 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜