nighty

折腾的年华
posts - 37, comments - 143, trackbacks - 0, articles - 0

2011年10月13日

系统为ubuntu server,二台机器A和B,IP为A 192.168.1.111,B 192.168.1.222
A为rsync server,启动为守护进程,B为备份机,做为rsync client,最后用crontab做一个简单的作业,定时在B上执行同步文件的功能
A的安装和配置如下:
1.  apt-get install rsync   可能提示系统已经安装有了
2. 配置文件/etc/rsyncd.conf
    默认安装时是不会有这个配置文件的,但是可以 cp /usr/share/doc/rsync/examples/rsyncd.conf /etc  把它示例中的配置文件拷贝过来
    vi /etc/rsyncd.conf    这里参数有点多,但是有些可以先不管,关注重点的
    [ftp]  这里是模块,可以配置多个,这个是系统默认给出的一个配置,下面给一个本机上的配置示例:
--------------------------------------------------------------------------------------------------
# so omit the "pid file" line completely in that case.
pid file=/var/run/rsyncd.pid
#syslog facility=daemon
#socket options=
# MODULE OPTIONS
[share]
comment = public archive
path = /var/www/pub
use chroot = no
max connections=2
# lock file = /var/lock/rsyncd
# the default for read only is yes...
read only = no
list = yes
uid = nobody
gid = nogroup
# exclude = 
# exclude from = 
# include =
# include from =
auth users = rsync
secrets file = /etc/rsyncd.secrets
strict modes = yes
hosts allow = 192.168.1.222
# hosts deny =
ignore errors = yes
ignore nonreadable = yes
transfer logging = yes
log format = %t: host %h (%a) %o %f (%l bytes). Total %b bytes.
timeout = 600
refuse options = checksum dry-run
dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz
---------------------------------------------------------------------------------------------
这里,最上面的是pid文件位置。然后配置了一个模块名叫做share,最大连接数是2,read only = no,指定为非只读(不然同步时会有权限问题)
而后面的auth users = rsync 是指定一个同步的账户名叫做rsync,这个账户的认证文件是/etc/rsyncd.secrets,当然我们要创建这个文件

3.  创建 /etc/rsyncd.secrets文件,内容为: rsync:123  表示rsync这个用户的密码是123 然后修改文件的权限 chmod 600 /etc/rsyncd.secrets

4.  rsync server做为守护进程
     vi /etc/default/rsync
     可以看到开头处这样声明:
------------------------------------
# start rsync in daemon mode from init.d script?
#  only allowed values are "true", "false", and "inetd"
#  Use "inetd" if you want to start the rsyncd from inetd,
#  all this does is prevent the init.d script from printing a message
#  about not starting rsyncd (you still need to modify inetd's config yourself).
RSYNC_ENABLE=inetd
-------------------------------------------
   做为守护进程,可以设置为true或是xinetd方式来启动。于是我们安装inetd   sudo apt-get install xinetd
   安装好后配置inetd的配置文件  vi /etc/xinetd.d/rsync ,输入如下内容:
---------------------------------------------------
service rsync
{
    disable = no
    socket_type = stream
    wait = no
    user = root
    server = /usr/bin/rsync
    server_args = --daemon
    log_on_failure += USERID
}
-------------------------------------------------------
然后启动xinetd,/etc/init.d/xinetd restart,A服务器的rsyncd server就完成了!

5.  B服务器由于是client,不需要配置,也不需要安装xinetd,直接可以通过命令行执行
rsync --delete -azvv rsync@192.168.1.111::share /var/www/pub/
这个命令就可以直接连接到192.168.111的rsync账户,它会提示你输入密码,就是A中的secrets文件中的密码,然后同步share模块到本机的/var/www/pub目录,你可以事前在A机器上创建一个文件如test.txt,随便写点内容,然后执行些命令,看是不是B上多了这样一个文件?如果是,则表示已经连接成功。你接下来就可以做crontab了!

posted @ 2013-04-12 12:23 寒武纪 阅读(1323) | 评论 (0)编辑 收藏

二台服务器,A的内网IP为192.168.1.111,B的内网IP为192.168.1.222,A做为master,B做为Slave
1.  配置A的Mysql
     (1)  vim /etc/mysql/my.cnf
           去掉[mysqld]段中 server_id =1 和log_bin=/var/log/mysql/mysql-bin.log的#注释
           加上  binlog-do-db = s3     s3就是要同步的数据库的名称,如果没有这一行,表示同步所有的数据,另外 binlog_ignore_db = mysql。要表示忽略同步的数据库名称为mysql,如果有多个要指定同步或是忽略同步的数据,就配置多行,保存退出。
     (2) 创建一个复制用的账户(名称为repl,允许从远程连接,密码为123456):
          GRANT REPLICATION SLAVE, RELOAD,SUPER, NO *.* TO repl@'%' IDENTIFIED BY '123456';
        FLUSH PRIVILEGES;
     (3) 重启mysql服务,或是直接reboot机器也可以
     (4) 进入mysql,然后用 show master status\G  查看二进制日志的状态,看到类似以下的结果:
          +------------------+----------+--------------+------------------+
          | File                      | Position  | Binlog_Do_DB | Binlog_Ignore_DB |
          +------------------+----------+--------------+------------------+
          | mysql-bin.000003 |     1376  | s3                  |                           |
          +------------------+----------+--------------+------------------+
2.  配置B的Mysql
      (1) vim /etc/mysql/my.cnf
           去掉[mysqld]段中 server_id =1 和log_bin=/var/log/mysql/mysql-bin.log的#注释,把server_id改为2,要和master机器的不一样。并增加以下内容:
           binlog_do_db=s3
           log-slave-updates
          保存退出
     (2) 重启mysql服务
     (3) 进入mysql,执行
          CHANGE MASTER TO MASTER_HOST='192.168.1.111', MASTER_USER='repl',Master_Port=3306,MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=1376;
          SLAVE START;
          注意上面的CHANGE语句中,MASTER_LOG_FILE和MASTER_LOG_POS就是上面1.4中提到的show master status命令得到的结果,指定二进制文件的名称和开始同步的位置。
     (4) 查看SLAVE状态:    show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.111
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 1376
               Relay_Log_File: mysqld-relay-bin.000002
                Relay_Log_Pos: 1355
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 1376
              Relay_Log_Space: 1512
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
    上面的红色二行如果为YES则表示已经正常连接,可以进行复制了。

posted @ 2013-04-09 20:33 寒武纪 阅读(1708) | 评论 (0)编辑 收藏

    许久没用服务器上装的那个postgresql,其实是用来做redmine的数据库的,考虑到mysql可能经常升级,而rails的连接组件在安装上有点麻烦,所以当初就装成postgresql。
    今天准备备份一下,用的phppgadmin,刚开始是提示其中的pg_dump执行路径没有配置,重新配置好后,导出的结果却是空的损坏文件。于是想算了,还是转到pg的安装目录下执行pg_dump.
    服务器装的是centos 6.2,忘了当初是建了一个用户postgres.postgres进行安装的,用其它用户切换到pg的安装目录下bin/pg_dump是执行不了的,提示在指定目标下生成导出文件。故猜测应该是postgres这个用户的权限不足!
    cat /etc/passwd查看一下当前有多少用户,的确有postgres.postgres用户,密码多少?忘了!反正有root,直接passwd修改成新的密码吧,于是就立马修改了该用户的密码,可以正确切换到postgres用户了,还需要root为postgres指定一个目录有操作权限
    chown -R postgres.postgres /var/xxxx   
    然后再回到pg的bin目录下,执行pg_dump redmine > /var/xxx/redmine.bak
    这下终于正常了,别忘了还得去redmine安装目录下,备份下files文件夹。
    
    仅以此为笔记,以后可以查阅使用

posted @ 2013-03-27 22:39 寒武纪 阅读(1374) | 评论 (0)编辑 收藏

      用Flex做企业应用将近有一年时间了,这个过程很累,在国内这方面的积累不多,真正有参考意义的资料的确非常少。经过一段长时间的摸索后,多少也积累了一点经验,就最近的关于单元测试的想法做一点总结,由于涉及的知识较多,这里也只是给出个人的一种思路。
     众所周知,Flex的缺点是开发调试效率较低,而且它只是表现层的一种解决方案。在企业应用中最需要解决的是编译生成的swf体积问题,我想任何客户都很难接受一个企业应用全部打包在一个swf里,几MB甚至几十MB的初始化过程谁都无法接受,所以都必不可少地采用Module的加载方式,把不同的业务功能编译成独立的swf,需要用的时候再去加载。把核心功能、通信机制、公共组件设计成库项目,编译成swc做为RSL让业务模块共享调用,达到尽量减少业务模块编译体积的目的。在这方面如果用心优化的话,基本上可以控制到每个swf体积大概在200KB以内,这样就算是互联网方式部署,客户访问仍是可以接受的。
    

     该结构图给出了一种整体的设计方案,Flex的启动肯定得有Application,这个是用户初登录后第一个加载的swf(登录就不要用flex了,用jsp或是模板实现吧)。所以它负责加载你设计的整个框架,包含模块加载机制、通信代理方式、基础库初始化等等,而和Java端的通信目前比较有效的仍然是blazeds,这个技术需要的介绍内容不在本文的范围之内。关于通信接口的实现有一种非常有用的方式就是借用Java的动态代理理念,Spring有一个flex的扩展子项目叫做springactionscript,而这个项目又引用了as3commons的库(类似于apache commons的一些公共组件)。为什么提及这个,因为flex本身的反射功能api非常难用,所以as3commons就做了扩展,它大大简化了反射的使用,而且提供了一个bytecode的工具用于操作字节码,它是实现动态代理的关键。至于为什么要动态代理?目的就是达到在写和Java对接的接口时,可以只声明接口,不需要实现类(得减少多少重复代码呀?),而和Java对接接口我们又可以开发一个工具让java code 自动转成 as code,如果懂得Eclipse插件开发的话还可以进一步做一个插件,达到Java只写一次就可以自动生成对应的flex接口,提高开发效率。
     转入正题,关于单元测试的概念,Flash Builder在4.5已经把flex unit作为内置库了,这点和Eclipse把junit内置类似,而flex unit的使用网上有大量的资料介绍,这里也不多说。flex unit在测试as代码还是不错的,和junit测试一样,提供了一些简单的Assert断言,但是你最痛苦的却不是as的测试。企业开发的特点就是数据量不大,但是需求坑爹,经常变来变去,而且结构复杂,往往一张表很多字段,关联子表,层级属性多。而你如果选择了Flex做了展示层的技术,那必定是看中它比HTML + CSS + JS更强的界面交互功能。的确,这点不容质疑,Flex Spark的皮肤机制的确提供了很多优秀的特点,不过如果你想纯熟掌握它的整个机制,恐怕得花很多时间阅读源代码才行,而皮肤的制作整对别想让美工独自实现,它同样是需要技术积累的,介绍它需要用几个篇幅才足够。任何技术方案都一样,BS、CS、AIR在实现复杂界面时,对于开发人员来说,最痛苦的莫过于界面的单元测试。
     痛苦在哪里?回看上面那幅架构图,业务功能界面实现在Flex,业务逻辑在后台Java,那么当二个团队同时进行工作的时候,沟通就是最大的成本。解决沟通的问题就必须在先前设计时约定好接口和数据结构,那是会影响双方团队协调的关键因素。当双方同时进行开发的时候,势必存在前台依赖后台的情况,因为它能到达界面的前提得在整个框架载入后(并且可以初始化一堆数据,发生了通信),Java后台还好说,依赖于spring和junit可以做到很好的单元测试。而flex就痛苦了,我没有通讯啥都做不了呀!
     如何设计单元测试?最大的出发点就是如何切掉和后台通信连接,看下面的简单结构图

     实现思路介绍:
     1.  简化Application加载过程   --   可以套用你主程序中的加载过程,但是不需要你的主界面其它多余的元素,达到减少到达测试界面的多余步骤(尽可能少地减少鼠标和键盘操作)
     2.  定义测试配置   --   测试哪个模块?哪个工作流程?你得通过配置的方式来定义,而不是每次都手写代码,才能方便你的成员使用你这个工具
     3.  模拟后台接口实现  --  记得上面说的动态代理吗?其实是为接口动态生成一个实现类,然后注入真正通信的实现代码,例如WebService、HTTP,既然可以注入这些通信渠道,当然就可以注入本地实现类啦
     4.  对象查看器    --   这个是神马?因为你都不要Java后台了,每次操作一个界面后得提交数据吧?没有后台了,提交到哪里?你得必须把你的提交对象用界面展示出来吧?好吧,这个可是个难点!

     我想这四个方面的原则无非就是:减少单元测试需要进行的步骤(最快到达测试界面),脱离后台依赖(自己简单模拟后台实现,可惜flex没有类似java的mock库,悲剧!),如何查看提交到后台的结果。 单元测试的目标:界面能正常加载、提交数据正常,如果二者都没问题,那么联调的时候就可以非常容易定位到是Flex的问题还是Java的问题!达到介分责任的目标,当然,如果你所在团队是按模块分的,也就是说flex和java都是同一个人做,那么就不存在责任问题。

     怎么实现上面的四个步骤呢?简要地介绍一下吧。
     第1简化application加载,其实你可以把第一张图中的application加载机制拷贝过来,只是主界面可以做得非常简单,比如不需要多余的控件(比如过长的菜单、当前登录人、时间、一陀设置按钮等),只留下最核心的能到达你测试界面的入口,至于怎么设计这个简化版的application,那得发挥你本人的创造力,另外还得看具体的业务。

    第2定义测试配置。模块如何加载?通信接口本地模拟实现类定义?通过配置显示在appliation做为触发控件,这些你都得自定义一套xml之类的文件来配置吧,这个就需要技巧了,不能设计得太复杂,因为你的开发人员需要沿用你定义的规范来定义它需要测试的模块,关于这方面的知识,可以参考spring加载配置文件方式、struts2加载定义文件等理念,有一个概念我比较推荐,就是struts2中的include配置文件,允许配置文件分散,让大家提供代码和文件时减少冲突,又可以套用你正常的加载机制。

    第3模拟后台接口实现。这个是比较烦的,模拟机制本身通过动态代理倒是不难实现,恶心的是你得自己动手用flex简单实现一次后台生成数据、处理数据的逻辑。这里我有个实践的总结经验分享,在前期你调试完的后台接口证明是没有问题的,那么可以混合使用,一部分调试过的接口可以直接用后台,而新接口才本地模拟。一个原则就是后台有的,已经证明稳定的就用后台,没有的或是后台还没有完成的你就自己模拟。

    第4对象查看器。想想flex不能操作数据库、由于安全限制不允许直接操作文件、无法读取本地文件目录。而你的测试数据也许会有关联(特别是在工作流方面),所以你得想一个方案来保存你的对象结果,而且得以一种人性化的方式查看对象内容。且抛开数据存储的问题,这个对象查看器如何设计就够你头疼的了,首先是对象得定义成一种格式,一种人可以看得懂的格式,比如xml,可以支持序列化和反序列化,你得去掉多余的无用属性和访问器。又得回到反射机制上了,序列化其实不难,难的是反序列化时如何正确地转成原来的对象。列一种本人设计的结构:
     <xxx   type="com.xx.oo.XXClass">
          <aa type="String">aaa</aa>
          <bb type="Boolean">true</bb>
          <list type="mx.collection.ArrayCollenction">
              ....
          </list>
     </xxx>
     对象分简单对象、复杂对象、动态对象等,如何表达这种结构和保证序列化时不丢失数据需要细心考虑。那么最后如何实现查看器呢?其实有一个参考的范例,就是Eclipse的“大纲”视图,经过实践的扩展,把树视图换成表格树(这种控件原生没有,有第三方的可以拿来修改),看个样图吧!
 
     因为你关注的对象内容无法就是这三个方面,属性名、值、和类型,又支持以树方式导航对象,已经足够你人眼分辩内容了。至于如何有效的保存测试数据,并且组织好结构,这个方面我目前也仍在思考中,未有较好的思路。
     以上内容仅是出于本人的一种方案,也许有更好的实现方案,只是水平不足以超过这种认识,希望后续能进一步思考能实现更加完美的单元测试框架。
     ST测试更关注的界面的自动化测试,这方面涉及的知识更多,一般公司是很难有财力和技术去支持做自动化测试,属于比较高端的范围,实现是很多回归都靠测试团队人肉在实现。

posted @ 2012-04-28 12:03 寒武纪 阅读(1511) | 评论 (1)编辑 收藏

      采用Spark进行Flex的Web应用开发的时候,往往会用一个固定栏,比如说类似Windows的任务栏,我们想把它固定在顶部或是底部,用于某些场景存放一些控件。<s:Application>组件中有一个<s:controlBarContent>属性和<s:controlBarLayout>,用于设置Application的一个组件区域(我猜官方起的这个名称大概用意在于此吧),下面这段话就是官方的中文注释:
Title包含在 Application 容器控件栏区域中的组件集。Application 容器控件栏区域的位置和外观由 spark.skins.spark.ApplicationSkin 类确定。默认情况下,ApplicationSkin 类定义以灰色背景显示在 Application 容器内容区域顶部的控件栏区域。创建自定义外观以更改控件栏的默认外观。
      于是可以简单的给<s:controlBarContent>区域添加各种控件,以及设置它内在的布局(controlBarLayout)。但是,发现它只能显示在Application的顶部!
      这是怎么回事,根据上面的注释,感觉应该原因在它的皮肤,得跟进代码,看一下究竟。
      首先找到<s:Application>控件的标准Skin,可以在Flash Builder中直接查看。
      
      双击打开ApplicationSkin,里面的代码包含了各种SVG图形学的实现api调用,flex管这些库叫FVG,大意就是SVG的Flex实现版本,该库实现得还算简洁!
      Application标准皮肤的就是先画一个矩形,然后用一个Group来包含不同的形状,最后一段<s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0" />,代表Application的内容区域,Flex从设计上区分了控件树和布局树,有些复杂,可以参考官方的文档。因为Application是属于容器,所以必须在皮肤中包含这一句,不然程序运行时就看不到它包含的子控件。
     而前面长长一串<s:Group id="topGroup">中是画了顶栏的外观,它用FVG库画了四层:
     <!-- layer 0: control bar highlight -->     底部高亮线(用画笔填充一个矩形)
     <!-- layer 1: control bar fill -->              背景填充线性渐变颜色
     <!-- layer 2: control bar divider line -->  分割线
     <!-- layer 3: control bar -->                  controlBar的具体内容容器
     当然这个controlBar不是自己会出现的,只有当你填充了内容控件的时候它才显示,所以有includeIn="normalWithControlBar, disabledWithControlBar",表示在这二个State下才显示,什么时候State才包含这二个呢?当然,就得去看Application.as的实现原理,具体篇幅就不描述。
     那么回到最初的问题:我想改变controlBar的位置在下方怎么处理?
     从上面的分析可知其实controlBar的摆放位置是在Skin中定义的,而它是什么布局,它显示不显示是通过Application.as本身的代码控制的,那么我们就只要自定义Application.as的皮肤就可以,新建一个外观mxml,直接复制官方的ApplicationSkin.mxml的代码,然后,把<s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0" />代码移到<s:Group id="topGroup">代码的上面,在你的Application中强制指定skinClass为你自定义的ApplicationSkin,或是通过css设定即可。
     再扩展思维一下,其实我们完全可以把controlBar放到左边或是右边,甚至任何位置,都取决你在Skin的定义和Application.as的逻辑控制(你可以继承Application扩展)。
     那么controlBar有什么作用?其实spark的Panel从及它的子类TitleWindow都有controlBar的概念,它能独立于你容器外的区域,对于你容器本身包含的组件和布局不会产生干扰,以及你设置了width、height为100%时也不产生影响。如果你不要controlBar,直接在Application中用布局添加一个Group也是可以实现,但是它从根本上是属于布局树中contentGroup的内容,会受限于布局。
     Spark Skin的设计的确有高明的地方,对比Flex3的外观,它提供给设计人员的空间实在大得多,你可以组合图片和FVG库的功能自定义各种外观,当然,我就建议你多熟悉一下FVG库的应用,毕竟从外加载图片对flex来说是一个消耗,你的程序也会增肥。

posted @ 2011-10-13 18:14 寒武纪 阅读(2455) | 评论 (0)编辑 收藏