posts - 168,  comments - 30,  trackbacks - 0
blogjava网站与博客园合并了,对blogjava还是有感情的。
并且blogjava网站发布的文章是在博客园首页看不到的。
blogjava网站首页能看到,你可以点击标题进入可以看到图片二维码信息。

Java爱好者社区
公众号内容简介:

专注于分享Java后端相关技术、老司机实战干货,不限于JVM、并发、设计模式、性能优化、分布式&微服务、云原生、大数据相关主题。
希望关注的你停下脚步,定有所收获。

以前的个人博客内容不好迁移,所以我打算根据自己的多年经验,不断整理输出有价值的内容。
目前公众号内容有关于SpringCloud(微服务框架)、Skywalking(APM监控调用链)、JVM(GC分析、内存泄漏分析)、并发编程相关原创实战文章已出炉。

最近刚开始已经有不少小伙伴关注了,期待能有幸搜索到本博客的同学,可以扫码关注一下,不胜感激。
大家有任何技术、职场、面试上的问题都可以与我交流。

方式一:扫码以下公众号二维码:


方式二:在微信上直接搜索: javatech_cbo

感谢各位小伙伴的支持,后续会在该公众号上输出大量的有价值的实战干货 ,期待与你一同进步与成长。

posted @ 2020-01-07 18:39 David1228 阅读(366) | 评论 (0)编辑 收藏
blogjava网站与博客园合并了,对blogjava还是有感情的。
并且blogjava网站发布的文章是在博客园首页看不到的。
blogjava网站首页能看到,你可以点击标题进入可以看到图片二维码信息。

Java爱好者社区
公众号内容简介:

专注于分享Java后端相关技术、老司机实战干货,不限于JVM、并发、设计模式、性能优化、分布式&微服务、云原生、大数据相关主题。
希望关注的你停下脚步,定有所收获。

以前的个人博客内容不好迁移,所以我打算根据自己的多年经验,不断整理输出有价值的内容。
目前公众号内容有关于SpringCloud(微服务框架)、Skywalking(APM监控调用链)、JVM(GC分析、内存泄漏分析)、并发编程相关原创实战文章已出炉。

最近刚开始已经有不少小伙伴关注了,期待能有幸搜索到本博客的同学,可以扫码关注一下,不胜感激。
大家有任何技术、职场、面试上的问题都可以与我交流。

方式一:扫码以下公众号二维码:


方式二:在微信上直接搜索: javatech_cbo

感谢各位小伙伴的支持,后续会在该公众号上输出大量的有价值的实战干货 ,期待与你一同进步与成长。

posted @ 2019-10-30 14:10 David1228 阅读(281) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2017-09-04 16:33 David1228 阅读(146) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2017-08-02 11:41 David1228 阅读(137) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2017-07-24 19:10 David1228 阅读(6202) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2017-07-19 18:10 David1228 阅读(2513) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2017-06-06 23:10 David1228 阅读(135) | 评论 (0)编辑 收藏
Netty客户端与服务端通信
posted @ 2017-06-06 23:09 David1228 阅读(105) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2017-05-30 19:26 David1228 阅读(1188) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2017-05-30 19:25 David1228 阅读(1080) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2016-12-22 23:01 David1228 阅读(3264) | 评论 (2)编辑 收藏
     摘要:   阅读全文
posted @ 2016-11-04 23:44 David1228 阅读(2099) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2016-07-28 17:57 David1228 阅读(241) | 评论 (0)编辑 收藏
     摘要: JVM调优总结 + jstat 分析jstat -gccause pid 1 每格1毫秒输出结果jstat -gccause pid 2000 每格2秒输出结果不断的在屏幕打印出结果  S0     S1     E     &n...  阅读全文
posted @ 2016-01-03 23:26 David1228 阅读(2527) | 评论 (2)编辑 收藏
     摘要:   阅读全文
posted @ 2015-12-27 16:49 David1228 阅读(732) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2015-10-31 12:37 David1228 阅读(499) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2015-10-30 20:20 David1228 阅读(2567) | 评论 (0)编辑 收藏
转载文章:http://www.qixing318.com/article/by-lua-adhesive-nginx-ecological-environment.html
posted @ 2015-09-08 13:22 David1228 阅读(381) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2015-09-08 09:34 David1228| 编辑 收藏
     摘要:   阅读全文
posted @ 2015-07-29 13:48 David1228 阅读(5374) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2014-12-03 23:56 David1228 阅读(25881) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2013-11-19 11:48 David1228 阅读(23265) | 评论 (1)编辑 收藏
     摘要:   阅读全文
posted @ 2013-11-18 18:01 David1228 阅读(2752) | 评论 (4)编辑 收藏
     摘要:   阅读全文
posted @ 2013-10-31 17:32 David1228 阅读(564) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2013-10-14 09:50 David1228 阅读(20546) | 评论 (6)编辑 收藏
Hibernate不支持left join带on的条件查询。
解决办法:使用原生SQL或者使用HQL方式需要修改hbm文件(如果项目中大部分不适用级联配置情况下)
需求是查询网络信息,网络信息中关联了分区、网络IP(1个网络--N个网络IP),网桥信息.
HQL:
public void queryVnets(Page page) {
        StringBuffer hql = new StringBuffer();
        hql.append("select new Map(vn.id as id, vn.vnName as vnName, b.name as vnType, ");
        hql.append("vn.vnIptype as vnIptype, vn.vnIp as vnIp,vn.vnNat as vnNat, vn.vnFlag as vnFlag, ");
        hql.append("vn.vnetFlag as vnetFlag, (case when sum(vmvn.state)='0' then 0 else 1 endas vnState, ");
        hql.append("vn.useType as useType, vn.createTime as createTime, ");
        hql .append("zone.oneName as oneName, zone.oneHypervisor as oneHypervisor, zone.oneSeq as oneSeq) ");
        hql.append("from VnetTable vn, ZoneTable zone, BridgeTable b ");
        hql.append("left join fetch vn.VnTables vmvn where zone.id = vn.zoneId and vn.vnType = b.id ");

        ... ...
        hql.append(" group by vn.id");
        if (vnState != null && !"".equals(vnState)) {
            if ("0".equals(vnState)) {
                hql.append(" having sum(vmvn.state)=0");
            } else if ("1".equals(vnState)) {
                hql.append(" having sum(vmvn.state)!=0");
            }
        }
    }

hbm配置文件:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.base.mapping.VnetTable" table="vnet_table" >
        <id name="id" type="java.lang.String">
            <column name="ID" length="32" />
            <generator class="uuid.hex" />
        </id>
        <property name="vnId" type="java.lang.Long">
            <column name="VN_ID">
                <comment>创建虚拟网络时得到的ID</comment>
            </column>
        </property>
         ...
        <property name="zoneId" type="java.lang.String">
            <column name="ZONE_ID" length="32">
                <comment>分区ID</comment>
            </column>
        </property>
        <property name="vlanId" type="java.lang.Integer">
            <column name="VLAN_ID">
                <comment>VLAN_ID</comment>
            </column>
        </property>
        <set name="vnTables" lazy="false" order-by="id asc" inverse="false" fetch="join" cascade="all">
            <key column="VN_NID"/>
            <one-to-many class="com.base.mapping.VnTable"/>
        </set>
    </class>
</hibernate-mapping>

理解inverse和cascade,可以参考:http://blog.csdn.net/wkcgy/article/details/6271321
总结: 
<one-to-many>中,建议inverse=”true”,由“many”方来进行关联关系的维护 
<many-to-many>中,只设置其中一方inverse=”false”,或双方都不设置 
Cascade,通常情况下都不会使用。特别是删除,一定要慎重。
操作建议 
  一般对many-to-one和many-to-many不设置级联,这要看业务逻辑的需要;对one-to-one和one-to-many设置级联。
  many-to-many关联关系中,一端设置inverse=”false”,另一端设置为inverse=”true”。在one-to-many关联关系中,设置inverse=”true”,由多端来维护关系表










posted @ 2013-09-12 11:57 David1228 阅读(13106) | 评论 (2)编辑 收藏
-- 以下两个查询效率相当,查询时间均为0.0xx秒,~ 但是Hibernate HQL不支持from后面接子查询,可以直接使用SQL方式解决,ibatis当然可以用了。
SELECT count(*from (
SELECT sum(t2.STATE) as vnSum, t1.ID FROM
vnetinfo_table t1, vm_vn_table t2 
where t1.ID = t2.VN_NID and t1.ZONE_ID = '4028a49c3facdf26013fae12531b286e' GROUP BY t1.ID) t where t.vnSum = 0;

SELECT count(*) FROM vnetinfo_table v ,(
SELECT sum(t2.STATE) as vnSum, t1.ID as idd FROM
vnetinfo_table t1, vm_vn_table t2 
where t1.ID = t2.VN_NID and t1.ZONE_ID = '4028a49c3facdf26013fae12531b286e' GROUP BY t1.ID) t
where v.ID = t.idd and t.vnSum = 0;

-- 查询效率太低了,查询时间均为0.5xx秒左右。要比以上两个SQL耗时很多倍。~ Hibernate支持在where后用子查询作为查询条件。
SELECT count(*) FROM vnetinfo_table v WHERE v.id in 
(SELECT CASE WHEN SUM(t2.STATE)=0 THEN t1.ID ELSE '' END
FROM vnetinfo_table t1, vm_vn_table t2 
where t1.ID = t2.VN_NID and t1.ZONE_ID = '4028a49c3facdf26013fae12531b286e' GROUP BY t1.ID);

-- 使用join方式替换in 查询时间均为0.09x秒左右。明显提高了效率,但是Hibernate HQL任然不支持在这种联合子查询方式。
SELECT count(*) FROM vnetinfo_table v INNER JOIN (SELECT CASE WHEN SUM(t2.STATE)=0 THEN t1.ID ELSE '' END as idd
FROM vnetinfo_table t1, vm_vn_table t2 
WHERE t1.ID = t2.VN_NID and t1.ZONE_ID = '4028a49c3facdf26013fae12531b286e' GROUP BY t1.ID) t ON v.ID = t.idd and t.idd IS not NULL;

附:Mysql中关于Exists用法的介绍请参见:http://www.nowamagic.net/librarys/veda/detail/639
posted @ 2013-08-21 13:47 David1228 阅读(3181) | 评论 (2)编辑 收藏
md5sum命令详解:
linux下的shell命令 ,制作md5码 也用于软件的md5校验
MD5算法常常被用来验证网络文件传输的完整性,防止文件被人篡改。MD5 全称是报文摘要算法(Message-Digest Algorithm 5),此算法对任意长度的信息逐位进行计算,产生一个二进制长度为128位(十六进制长度就是32位)的“指纹”(或称“报文摘要”),不同的文件产生相同的报文摘要的可能性是非常非常之小的。
在linux或Unix上,md5sum是用来计算和校验文件报文摘要的工具程序。一般来说,安装了Linux后,就会有md5sum这个工具,直接在命令行终端直接运行。
1、使用md5sum来产生指纹(报文摘要)命令如下:
md5sum filename > filename.md5 或者
md5sum filename >>filename.md5
也可以把多个文件的报文摘要输出到一个md5文件中,这要使用通配符*,比如某目录下有几个iso文件,要把这几个iso文件的摘要输出到iso.md5文件中,命令如下:
md5sum *.iso > iso.md5
2、使用md5报文摘要验证文件,方法有二:
把下载的文件file和该文件的file.md5报文摘要文件放在同一个目录下,然后用如下命令进行验证:
md5sum -c file.md5
然后如果验证成功,则会输出:正确结果。
实战案例:
需求:虚拟机存在多份备份,当进行备份恢复时,要求检查源备份压缩文件的完整性。那么可以通过md5这种方式来验证。
压缩备份文件并生成md5码,部分shell脚本如下:
#----------------------------------
log "Compressing and moving $SRC_PATH"
exec_and_log "$SSH $SRC_HOST mkdir -p ${SRC_PATH}_compress"
for file in `$SSH $SRC_HOST ls $SRC_PATH | grep -v $SN_SIGN`
do
     exec_and_log "$SSH $SRC_HOST cd $SRC_PATH;sudo chmod -R +r $SRC_PATH/*;tar -Sczvf ${SRC_PATH}_compress/${file}.tgz ${file}"
done
#----------------------------------

#--------------md5 begin-----------------
log "Create backup.md5"
exec_and_log "$SSH $SRC_HOST $MD5SUM ${SRC_PATH}_compress/*.tgz > ${SRC_PATH}_compress/backup.md5"
#--------------md5 end-----------------

#其中 exec_and_log是另一个公共脚本中定义的。shell中可以通过点(.)的方式将脚本引入。该函数内如下:
# Executes a command, if it fails returns error message and exits
# If a second parameter is present it is used as the error message when
# the command fails
function exec_and_log
{
    message=$2

    EXEC_LOG_ERR=`$1 2>&1 1>/dev/null`
    EXEC_LOG_RC=$?

    if [ $EXEC_LOG_RC -ne 0 ]; then
        log_error "Command \"$1\" failed: $EXEC_LOG_ERR"

        if [ -n "$2" ]; then
            error_message "$2"
        else
            error_message "Error executing $1: $EXEC_LOG_ERR"
        fi
        exit $EXEC_LOG_RC
    fi
}

# Logs a message, alias to log_info
function log
{
    log_info "$1"
}

# Log function that knows how to deal with severities and adds the
# script name
function log_function
{
    echo "$1: $SCRIPT_NAME: $2" 1>&2
}

# Logs an info message
function log_info
{
    log_function "INFO" "$1"
}

# Logs an error message
function log_error
{
    log_function "ERROR" "$1"
}

# This function is used to pass error message to the mad
function error_message
{
    (
        echo "ERROR MESSAGE --8<------"
        echo "$1"
        echo "ERROR MESSAGE ------>8--"
    ) 1>&2
}

生成的backup.md5内容:
$ md5sum *.tgz > backup.md5 
2c07174d451a687bc0e401b1dc7d84b8  checkpoint.1376892493.tgz
57a18d7f6eed36565b9012e519985130  checkpoint.1376903188.tgz
b652990806e58a81b41dc1b23db9adda  checkpoint.1376904023.tgz
f4e7adb46a8fde2643e082875cc60e21  checkpoint.1376904289.tgz
ad2a59902652e2896b35507417b7016f  checkpoint.tgz
4bd43eac64f238bb35c7194816da7d23  deployment.0.tgz
ee3d9266cf92f7540cc75a94343bc20a  deployment.7.tgz
fcd5aae37354b5cb66f4b90544eaa5c3  disk.0.tgz
c1ef6d911b441660ec2d1e44b5a56f66  disk.1.iso.tgz
25eae70a31a7c7cff3baade4cd65fe82  disk.1.tgz

检查备份文件是否完整:
exec_and_log "$SSH $SRC_HOST $MD5SUM -c ${SRC_PATH}/backup.md5"

检测结果:
$ md5sum -c backup.md5 
checkpoint.1376892493.tgz: OK
checkpoint.1376903188.tgz: OK
checkpoint.1376904023.tgz: OK
checkpoint.1376904289.tgz: OK
checkpoint.tgz: OK
deployment.0.tgz: OK
deployment.7.tgz: OK
disk.0.tgz: OK
disk.1.iso.tgz: OK
disk.1.tgz: OK
posted @ 2013-08-20 11:34 David1228 阅读(2255) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2013-08-20 09:46 David1228 阅读(278) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2013-08-20 09:44 David1228 阅读(278) | 评论 (0)编辑 收藏
     摘要:   阅读全文
posted @ 2013-07-24 16:11 David1228 阅读(30086) | 评论 (0)编辑 收藏
     摘要: 根据官方的说法,在ibatis3,也就是Mybatis3问世之前,Spring3的开发工作就已经完成了,所以Spring3中还是没有对Mybatis3的支持。因此由Mybatis社区自己开发了一个Mybatis-Spring用来满足Mybatis用户整合Spring的需求。下面就将通过Mybatis-Spring来整合Mybatis跟Spring的用法做一个简单的介绍。MapperFactoryB...  阅读全文
posted @ 2013-07-10 18:07 David1228 阅读(20916) | 评论 (2)编辑 收藏

不得不承认的是,在目前的web应用开发中,Spring的应用越来越广泛,其地位变得相当重要。而在最近推出的Spring 3.2版本中,又引入了一些新的值得关注的特性。本文中将介绍其中一些值得关注的新特性。

一 不再需要web.xml

 在新的Spring 3.2中,可以不再需要web.xml这个文件了,这得益于Servlet 3.0的新特性。

其中,可以使用@WebServlet在需要调用的servlet中,使用注解去设置servlet中的映射关系。这样的话,就可以不再象以往那样要通过在web.xml中对servlet进行配置,十分方便。

此外,Servlet 3.0提供了既能在容器中动态注册servlet的方法,也提供了通过实现

ServletContainerInitializer接口的方法实现在容器启动阶段为容器动态注册Servlet、Filter和listeners。容器会在应用的启动阶段,调用所有实现ServletContainerInitializer接口类中的onStartup()方法。而Spring 3.2中,则进一步简化了这点,只需要实现WebApplicationInitializer接口就可以了,其中提供了一个相关的实现类--AbstractContextLoaderInitializer,它可以动态注册DispatcherServlet。这意味着,只要spring-webmvc.jar放置在web应用的web-inf/lib中,就可以调用Dispatcher servlet了。可以参考如下的例子(来自Spring文档):

  1. public class MyWebApplicationInitializer implements WebApplicationInitializer { 
  2.  
  3.     @Override 
  4.     public void onStartup(ServletContext container) { 
  5.         ServletRegistration.Dynamic registration = container.addServlet("dispatcher"new DispatcherServlet()); 
  6.         registration.setLoadOnStartup(1); 
  7.         registration.addMapping("/example/*"); 
  8.     } 
  9.  

二 支持Java编程式配置在Spring mvc 3.2中,一个不错的特性就是在之前版本中支持使用Java代码配置各种依赖注入的基础上,进一步简化了配置。关于使用Java编程式配置的好处,可以通过下面这个链接文章的介绍去学习

http://blog.frankel.ch/consider-replacing-spring-xml-configuration-with-javaconfig)。
在Spring mvc 3.2中,提供了AbstractContextLoaderInitialize的一个子类AbstractAnnotationConfigDispatcherServletInitializer去实现零XML配置的效果,只需要创建的类继承AbstractAnnotationConfigDispatcherServletInitializer就可以了,如下代码所示:

  1. public  
  2.  
  3. class  
  4.  
  5. SugarSpringWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 
  6.  
  7.     @Override 
  8.     protected Class<?>[] getRootConfigClasses() { 
  9.         return new Class[] { JavaConfig.class }; 
  10.     } 
  11.  
  12.     @Override 
  13.     protected Class<?>[] getServletConfigClasses() { 
  14.         return new Class[] { WebConfig.class }; 
  15.     } 
  16.  
  17.     @Override 
  18.     protected String[] getServletMappings() { 
  19.         return new String[] { "/" }; 
  20.     } 
  21.  

功能更强大的Spring Test 框架现在,单元测试显得越来越重要了,每一个类都建议做好对应的单元测试。在Spring 3.2版本之前,如果要对Spring MVC进行单元测试的话,必须显式去调用某个控制器类中的某个方法,而不能直接单元测试相关的mapping映射。而在Spring mvc 3.2中,重新整合和增强了测试框架的功能,支持直接用/*这样的映射方式去测试某个控制器中的类。同时,之前的开源项目(https://github.com/SpringSource/spring-test-mvc也被收录到Spring mvc 3.2中去了。此外,还新增加了对返回(return),重定向(redirect)model等的测试改进,下面是一个例子:

  1. public class SayHelloControllerIT extends AbstractTestNGSpringContextTests { 
  2.   
  3.     private MockMvc mockMvc; 
  4.   
  5.     @BeforeMethod 
  6.     public void setUp() { 
  7.   
  8.         mockMvc = webAppContextSetup((WebApplicationContext) applicationContext).build(); 
  9.     } 
  10.   
  11.     @Test(dataProvider = "pathParameterAndExpectedModelValue"
  12.     public void accessingSayhelloWithSubpathShouldForwardToSayHelloJspWithModelFilled(String path, String value) throws Exception { 
  13.   
  14.         mockMvc.perform(get("/sayHello/Jo")).andExpect(view().name("sayHello")).andExpect(model().attribute("name""Jo")); 
  15.     } 

本文的示例代码可以在: http://blog.frankel.ch/wp-content/resources/spring-3-2-sweetness/spring-sweet-1.0.0.zip中下载。

原文链接:http://java.dzone.com/articles/spring-32-sweetness

posted @ 2013-07-10 11:48 David1228 阅读(2233) | 评论 (0)编辑 收藏
     摘要: 本文转载自:http://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html场景问题  举个生活中常见的例子——组装电脑,我们在组装电脑的时候,通常需要选择一系列的配件,比如CPU、硬盘、内存、主板、电源、机箱等。为讨论使用简单点,只考虑选择CPU和主板的问题。  事实上,在选择CPU的时候,面临一系列的...  阅读全文
posted @ 2013-07-04 17:07 David1228 阅读(266) | 评论 (0)编辑 收藏
shell中可能经常能看到:>/dev/null 2>&1 

命令的结果可以通过%>的形式来定义输出

分解这个组合:“>/dev/null 2>&1” 为五部分。

1:> 代表重定向到哪里,例如:echo "123" > /home/123.txt
2:/dev/null 代表空设备文件
3:2> 表示stderr标准错误
4:& 表示等同于的意思,2>&1,表示2的输出重定向等同于1
5:1 表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于 "1>/dev/null"

因此,>/dev/null 2>&1 也可以写成“1> /dev/null 2> &1”

那么本文标题的语句执行过程为:
1>/dev/null :首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。
2>&1 :接着,标准错误输出重定向 到 标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。

最常用的方式有:
    
command > file 2>file  与command > file 2>&1

它们有什么不同的地方吗?
      首先command > file 2>file 的意思是将命令所产生的标准输出信息,和错误的输出信息送到file 中.command  > file 2>file 这样的写法,stdout和stderr都直接送到file中, file会被打开两次,这样stdout和stderr会互相覆盖,这样写相当使用了FD1和FD2两个同时去抢占file 的管道。
      而command >file 2>&1 这条命令就将stdout直接送向file, stderr 继承了FD1管道后,再被送往file,此时,file 只被打开了一次,也只使用了一个管道FD1,它包括了stdout和stderr的内容。
      从IO效率上,前一条命令的效率要比后面一条的命令效率要低,所以在编写shell脚本的时候,较多的时候我们会command > file 2>&1 这样的写法。
 
以上转载自:http://sjolzy.cn/shell-in-the-dev-null-2-gt-amp-1-Detailed.html

-
-----------------------------------------------------------------------------------------------------
那么,有这么个需求,我如何能判断远程主机上的某个文件是否存在呢,我能想到的有两种方法,一种方法可以使用expect脚本,但是需要远程主机上安装expect包,但是只需要知道用户名和密码就可以了;第二种方法是要求两台主机之间做好ssh互信,然后如admin,那么通过shell可以直接判断,但是文件宿主权限也需要是admin用户下的。
第二种方法脚本如下:
#!/bin/bash

ssh dst_host sh -s 2>&1 1>/dev/null <<EOF
ls $NEW_DST_DIR
EOF
IS_EXIST=$?
if [ "$IS_EXIST"x = "0"x ]; then
   echo "-The file exists------------------------------"
else
   echo "No file-------------------------------"
fi

--大卫





posted @ 2013-07-02 14:45 David1228 阅读(790) | 评论 (0)编辑 收藏
OpenNebula中主机添加一切正常。
执行$onehost list 主机CPU、内存资源可以正常被监控到。但是,创建虚拟机后,虚拟机状态很长一段时间一直处于pend状态。而OpenNebula的mm_sched调度虚拟机的周期是缺省30秒调度一次,根据调度算法适配一台合适的主机,主机是新添加的而且是有足够资源的,为什么不能部署呢?
我们可以通过查看虚拟机的调度日志$ONE_LOCATION/var/sched.log发现如下错误信息:
Tue Feb 21 [HOST][E]: Exception raised: Unable to transport XML to server and get XML response back.
 HTTP response: 504 Tue Feb 22 14:27:39 2011 [POOL][E]: Could not retrieve pool info from ONE。
解决方法:
在OpenNebula官方的Wiki中可以找到原因,原因是所添加的主机使用了HTTP代理上网了,所以OpenNebula读取了系统的http_proxy环境变量,此时就需要关闭http_proxy。

I can create VMs, but sched.log shows the error "Could not retrieve pool info from ONE". What's wrong?

If the scheduler does not deploy the pending VMs, and messages like these are found in sched.log

[HOST][E]: Exception raised: Unable to transport XML to server and get XML response back.  HTTP response code is 404, not 200 [POOL][E]: Could not retrieve pool info from ONE

Then you need to unset the http_proxy environment variable, or set the no_proxy accordingly.

wiki参考地址(这里汇总了使用或部署one过程中可能遇到的问题以及解决办法):http://wiki.opennebula.org/faq#listing_vms_takes_a_lot_of_time_why

大家对于Opennebula的安装部署感兴趣的话,可以参考vpsee的博客(在Centos上安装和部署Opennebula),讲解的很详细。

vpsee已经试玩了下OpenNebula4.0,由于项目原因,目前我们还在用OpenNebula3.8.1,后面也会测试升级到OpenNebula4.0看看新功能。
升级过程同样也参考下vpsee的OpenNebula3.x升级到OpenNebula4.0,^^ 这么好的资源优先借鉴。

posted @ 2013-06-24 18:01 David1228 阅读(680) | 评论 (0)编辑 收藏
启动和停止OpenNebula shell脚本如下:
给这个脚本起个名字吧,叫做oned

#!/bin/bash
#
# chkconfig: 345 80 15
# description: Startup script for the one .

# Source function library.

. /etc/rc.d/init.d/functions

APP_USER=oneadmin
APP_HOME=/opt/nebula/ONE/

RETVAL=0

start(){
        checkrun
        if [ $RETVAL -eq 1 ]; then
                echo "Starting oned"
                su - $APP_USER -c "$APP_HOME/bin/one start"
    else
       echo "oned is already running."

        fi
}

stop(){
        su - $APP_USER -c "$APP_HOME/bin/oneuser list" > /dev/null 2>&1
        result=$?
        if [ $result -eq 0 ]; then

                echo "Shutting down oned"
                su - $APP_USER -c "$APP_HOME/bin/one stop"

        elif [ $result -eq 255 ]; then

                echo "Shutting down oned"
                pkill -9 -u oneadmin

    fi
}
   
checkrun(){
        su - $APP_USER -c "$APP_HOME/bin/oneuser list" > /dev/null 2>&1
        if [ $? -eq 0 ]; then
             RETVAL=0
             return $RETVAL
    else
             RETVAL=1
             return $RETVAL
        fi
}

status(){
        checkrun
        if [ $RETVAL -eq 0 ]; then
                echo "oned is running."
        else
            echo "oned is stopped."
            exit 1
        fi
}

case "$1" in
start)
        start
        RETVAL=$?
        ;;
stop)
        stop
        RETVAL=$?
        ;;
restart)
        stop
        start
        RETVAL=$?
        ;;
status)
        status
        ;;
*)
        echo "Usage: $0 {start|stop|restart|status}"
        esac
echo $RETVAL
exit 0
Linux中如何设置服务开机自启动,可以参考http://os.51cto.com/art/201301/377515.htm

1. 首先查看服务器默认的运行级别是多少? 目的是在对应运行级别下建立服务的软连接。
 1> 执行命令#runlevel
 [root@compute-63-14]# runlevel
 N 3
 2> 查看/etc/inittab
 [root@compute-63-14 tomcat6]# cat /etc/inittab 
 # inittab is only used by upstart for the default runlevel.
 ... ... 
 id:3:initdefault:
 
2. 将写好的oned脚本拷贝到/etc/init.d/目录下

3. 在/etc/rc.d/rc3.d中建立软链接
cd /etc/init.d/rc.d/rc3.d
ln -s ../init.d/oned S99oned
S99oned是其软链接,S开头代表加载时自启动

以上已测试过,没有问题,同时有兴趣可以试试第二、三种方式。
posted @ 2013-06-04 11:18 David1228 阅读(225) | 评论 (0)编辑 收藏
VNCServer X 桌面默认为 twm, 这时连接进去只能看到终端界面,而看不到远程桌面界面。可修改 /root/.vnc/xstartup 文件,将其改为 GNOME KDE 桌面:
GNOME

[root @ test vnc-4_1_2-x86_linux] # vi /root/.vnc/xstartup
#
/bin/sh
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot –solid grey
vncconfig –iconic &
xterm –geometry 80x24+10+10 –ls –title “$VNCDESKTOP Desktop” &
gnome-session &

KDE:
[root @ test vnc-4_1_2-x86_linux] # vi /root/.vnc/xstartup
#
/bin/sh
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot –solid grey
vncconfig –iconic &
xterm –geometry 80x24+10+10 –ls –title “$VNCDESKTOP Desktop” &
startkde &
修改完毕后须重新启动 VNCServer
[root @ test vnc-4_1_2-x86_linux] # vncserver –kill :1 && vncserver :1
[root @ test vnc-4_1_2-x86_linux] # vncviewer 192.168.98.32:1
连接后即可使用 GNOME KDE 桌面啦(就像 WinXP 的远程桌面一般),也可以通过 WEB 访问,在浏览器中输入http://192.168.0.252:5801 即可,VNC 默认的端口号为5801

转载:http://shaoruisky.blog.163.com/blog/static/92610707201151224518579/
posted @ 2013-03-24 13:07 David1228 阅读(1836) | 评论 (0)编辑 收藏
Spring2.5继续坚持了这个发展趋向,特别是为那些使用Java 5或更新版本java的开发人员提供了进一步简化而强大的新特性。这些新特性包括:注解驱动的依赖性注入(annotation-driven dependency injection),使用注解而非XML元数据来自动侦测classpath上的Spring组件,注解对生命周期方法的支持,一个新的web控制器模型将请求映射到加注解的方法上,在测试框架中支持Junit4,Spring XML命名空间的新增内容,等等。
项目中使用的spring2.5版本。如果想要使用spring提供的注解功能.
applicationContext.xml配置文件中增加如下配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- Using annontations -->
<context:annotation-config></context:annotation-config>
新增以下三项才可以使用注解功能
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config></context:annotation-config>
或者<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/> 注册一个单独的Spring post-processor.
一个没有实现任何接口的业务类,配置如下:
public class LogService extends Service{
public LogBiz(){}
@Resource //默认按名称查找bean. 如果找不到,则按类型匹配bean.
private BaseDao dao;
}
tomcat启动错误1:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'logBiz': Injection of resource fields failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.ccms.base.dao.BaseDAO] is defined: expected single matching bean but found 40: [baseDAO, loginDAO, logDAO]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessAfterInstantiation(CommonAnnotationBeanPostProcessor.java:291)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:876)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:437)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:383)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:353)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:245)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:169)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:242)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:269)
... 32 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.ccms.base.dao.BaseDAO] is defined: expected single matching bean but found 40: [baseDAO, loginDAO, logDAO]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:583)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:418)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:497)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:145)
at org.springframework.beans.factory.annotation.InjectionMetadata.injectFields(InjectionMetadata.java:79)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessAfterInstantiation(CommonAnnotationBeanPostProcessor.java:288)
... 42 more
使用@Resource默认按名称查找bean. 如果找不到,则按类型匹配bean.而名称dao没有找到,所以会根据BaseDAO匹配,但是BaseDAO是一个接口:
<bean id="loginDAO" class="com.test.dao.loginDAO" parent="baseDAO" />
<bean id="logDAO" class="com.test.dao.logDAO" parent="baseDAO" />
<bean id="baseDAO" class="com.ccms.base.dao.BaseDAOImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="simpleJdbcTemplate">
<ref bean="simpleJdbcTemplate" />
</property>
</bean>
有两个实现了BaseDAO接口的类,所以spring就不知道应该使用哪一个了。直接抛出异常。
解决方法1:
我们可以看到baseDAO名称是唯一的, 所以如果想要按照名称匹配,则直接写baseDAO就可以了
@Resource
private BaseDAO baseDAO;
解决方法2:
@Autowired //默认按照类型匹配,同样应为有两个子类bean,所以抛出异常。
@Qualifier("loginDAO") //限定bean
private BaseDAO dao;
参考博客:
http://doc.chinaunix.net/java/200801/240056.shtml
http://stackoverflow.com/questions/10534053/autowiring-two-beans-implementing-same-interface-how-to-set-default-bean-to-au
posted @ 2013-03-21 10:22 David1228 阅读(2295) | 评论 (0)编辑 收藏
     摘要: jdk并发部分,如果英文理解有点小难,可以参考http://www.yiibai.com/java6/java/util/concurrent/package-summary.html本篇转自:http://victorzhzh.iteye.com/blog/1011635很多时候我们希望任务可以定时的周期性的执行,在最初的JAVA工具类库中,通过Timer可以实现定时的周期性的需求,但是有一定的...  阅读全文
posted @ 2013-03-18 18:58 David1228 阅读(1607) | 评论 (0)编辑 收藏
使用开源云工具OpenNebula3.8.1在KVM环境下虚拟机迁移失败问题解决。
1、虚拟机迁移失败1日志:
Fri Mar  8 17:57:18 2013 [LCM][I]: New VM state is SAVE_MIGRATE
Fri Mar  8 17:57:30 2013 [VMM][I]: ExitCode: 0
Fri Mar  8 17:57:30 2013 [VMM][I]: Successfully execute virtualization driver operation: save.
Fri Mar  8 17:57:30 2013 [VMM][I]: ExitCode: 0
Fri Mar  8 17:57:30 2013 [VMM][I]: Successfully execute network driver operation: clean.
Fri Mar  8 17:58:14 2013 [LCM][I]: New VM state is PROLOG_MIGRATE
Fri Mar  8 17:58:14 2013 [TM][I]: mv: -------------------------/one_images_3.8.1/0/42/disk.0
Fri Mar  8 17:58:14 2013 [TM][I]: ExitCode: 0
Fri Mar  8 18:02:28 2013 [TM][I]: mv: Moving bcec162:/one_images_3.8.1/0/42 to node153:/one_images_3.8.1/0/42
Fri Mar  8 18:02:28 2013 [TM][I]: ExitCode: 0
Fri Mar  8 18:02:29 2013 [LCM][I]: New VM state is BOOT
Fri Mar  8 18:02:30 2013 [VMM][I]: ExitCode: 0
Fri Mar  8 18:02:30 2013 [VMM][I]: Successfully execute network driver operation: pre.
Fri Mar  8 18:02:33 2013 [VMM][I]: Command execution fail: /var/tmp/one/vmm/kvm/restore /one_images_3.8.1/0/42/checkpoint node153 42 node153
Fri Mar  8 18:02:33 2013 [VMM][E]: restore: Command "virsh --connect qemu:///system restore /one_images_3.8.1/0/42/checkpoint" failed: error: Failed to restore domain from /one_images_3.8.1/0/42/checkpoint
Fri Mar  8 18:02:33 2013 [VMM][I]: error: unable to set user and group to '0:0' on '/one_images_3.8.1/0/42/disk.1': No such file or directory
Fri Mar  8 18:02:33 2013 [VMM][E]: Could not restore from /one_images_3.8.1/0/42/checkpoint
Fri Mar  8 18:02:33 2013 [VMM][I]: ExitCode: 1
Fri Mar  8 18:02:33 2013 [VMM][I]: Failed to execute virtualization driver operation: restore.
Fri Mar  8 18:02:33 2013 [VMM][E]: Error restoring VM: Could not restore from /one_images_3.8.1/0/42/checkpoint
Fri Mar  8 18:02:34 2013 [DiM][I]: New VM state is FAILED
Sat Mar  9 09:23:46 2013 [DiM][I]: New VM state is DONE.
Sat Mar  9 09:23:46 2013 [TM][W]: Ignored: LOG I 42 ExitCode: 0
Sat Mar  9 09:23:47 2013 [TM][W]: Ignored: LOG I 42 delete: Deleting /one_images_3.8.1/0/42
Sat Mar  9 09:23:47 2013 [TM][W]: Ignored: LOG I 42 ExitCode: 0
Sat Mar  9 09:23:47 2013 [TM][W]: Ignored: TRANSFER SUCCESS 42 -
解决方法:
在mv脚本中TAR拷贝命令前面增加$SUDO命令.
$ONE_LOCATION/var/remotes/tm/ssh/mv
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org)             #
#                                                                            #
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
# not use this file except in compliance with the License. You may obtain    #
# a copy of the License at                                                   #
#                                                                            #
# http://www.apache.org/licenses/LICENSE-2.0                                 #
#                                                                            #
# Unless required by applicable law or agreed to in writing, software        #
# distributed under the License is distributed on an "AS IS" BASIS,          #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
# See the License for the specific language governing permissions and        #
# limitations under the License.                                             #
#--------------------------------------------------------------------------- #
# MV <hostA:system_ds/disk.i|hostB:system_ds/disk.i> vmid dsid
#    <hostA:system_ds/|hostB:system_ds/>
#   - hostX is the target host to deploy the VM
#   - system_ds is the path for the system datastore in the host
#   - vmid is the id of the VM
#   - dsid is the target datastore (0 is the system datastore)
SRC=$1
DST=$2
VMID=$3
DSID=$4
if [ -z "${ONE_LOCATION}" ]; then
    TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh
else
    TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh
fi
. $TMCOMMON
#-------------------------------------------------------------------------------
# Return if moving a disk, we will move them when moving the whole system_ds
# directory for the VM
#-------------------------------------------------------------------------------
SRC=`fix_dir_slashes $SRC`
DST=`fix_dir_slashes $DST`
SRC_PATH=`arg_path $SRC`
DST_PATH=`arg_path $DST`
SRC_HOST=`arg_host $SRC`
DST_HOST=`arg_host $DST`
DST_DIR=`dirname $DST_PATH`
SRC_DS_DIR=`dirname  $SRC_PATH`
SRC_VM_DIR=`basename $SRC_PATH`
if [ `is_disk $DST_PATH` -eq 1 ]; then
    log "-------------------------$DST_PATH"
exit 0
fi
if [ "$SRC" == "$DST" ]; then
    exit 0
fi
ssh_make_path "$DST_HOST" "$DST_DIR"
log "Moving $SRC to $DST"
ssh_exec_and_log "$DST_HOST" "rm -rf '$DST_PATH'" \
    "Error removing target path to prevent overwrite errors"
TAR_COPY="$SSH $SRC_HOST '$SUDO $TAR -C $SRC_DS_DIR -cf - $SRC_VM_DIR'"
TAR_COPY="$TAR_COPY | $SSH $DST_HOST '$TAR -C $DST_DIR -xf -'"
exec_and_log "eval $TAR_COPY" "Error copying disk directory to target host"
exec_and_log "$SSH $SRC_HOST rm -rf $SRC_PATH"
exit 0
-------------------------------------------------------------------------------------------
2、虚拟机迁移失败2日志:
Sat Mar  9 09:34:12 2013 [LCM][I]: New VM state is SAVE_MIGRATE
Sat Mar  9 09:34:24 2013 [VMM][I]: ExitCode: 0
Sat Mar  9 09:34:24 2013 [VMM][I]: Successfully execute virtualization driver operation: save.
Sat Mar  9 09:34:24 2013 [VMM][I]: ExitCode: 0
Sat Mar  9 09:34:24 2013 [VMM][I]: Successfully execute network driver operation: clean.
Sat Mar  9 09:34:25 2013 [LCM][I]: New VM state is PROLOG_MIGRATE
Sat Mar  9 09:34:25 2013 [TM][I]: mv: -------------------------/one_images_3.8.1/0/43/disk.0
Sat Mar  9 09:34:25 2013 [TM][I]: ExitCode: 0
Sat Mar  9 09:36:38 2013 [TM][I]: mv: Moving node153:/one_images_3.8.1/0/43 to bcec162:/one_images_3.8.1/0/43
Sat Mar  9 09:36:38 2013 [TM][I]: mv: -------------------target copyy
Sat Mar  9 09:36:38 2013 [TM][I]: mv: ++++++++++++++++++++++end copy
Sat Mar  9 09:36:38 2013 [TM][I]: ExitCode: 0
Sat Mar  9 09:36:38 2013 [LCM][I]: New VM state is BOOT
Sat Mar  9 09:36:38 2013 [VMM][I]: ExitCode: 0
Sat Mar  9 09:36:38 2013 [VMM][I]: Successfully execute network driver operation: pre.
Sat Mar  9 09:36:42 2013 [VMM][I]: Command execution fail: /var/tmp/one/vmm/kvm/restore /one_images_3.8.1/0/43/checkpoint bcec162 43 bcec162
Sat Mar  9 09:36:42 2013 [VMM][E]: restore: Command "virsh --connect qemu:///system restore /one_images_3.8.1/0/43/checkpoint" failed: error: Failed to restore domain from /one_images_3.8.1/0/43/checkpoint
Sat Mar  9 09:36:42 2013 [VMM][I]: error: internal error process exited while connecting to monitor: Supported machines are:
Sat Mar  9 09:36:42 2013 [VMM][I]: pc         RHEL 6.0.0 PC (alias of rhel6.0.0)
Sat Mar  9 09:36:42 2013 [VMM][I]: rhel6.0.0  RHEL 6.0.0 PC (default)
Sat Mar  9 09:36:42 2013 [VMM][I]: rhel5.5.0  RHEL 5.5.0 PC
Sat Mar  9 09:36:42 2013 [VMM][I]: rhel5.4.4  RHEL 5.4.4 PC
Sat Mar  9 09:36:42 2013 [VMM][I]: rhel5.4.0  RHEL 5.4.0 PC
Sat Mar  9 09:36:42 2013 [VMM][E]: Could not restore from /one_images_3.8.1/0/43/checkpoint
Sat Mar  9 09:36:42 2013 [VMM][I]: ExitCode: 1
Sat Mar  9 09:36:42 2013 [VMM][I]: Failed to execute virtualization driver operation: restore.
Sat Mar  9 09:36:42 2013 [VMM][E]: Error restoring VM: Could not restore from /one_images_3.8.1/0/43/checkpoint
Sat Mar  9 09:36:42 2013 [DiM][I]: New VM state is FAILED
登陆到节点:
[root@bcec162 43]# virsh restore checkpoint 
错误:从 checkpoint 恢复域失败
错误:internal error process exited while connecting to monitor: Supported machines are:
pc         RHEL 6.0.0 PC (alias of rhel6.0.0)
rhel6.0.0  RHEL 6.0.0 PC (default)
rhel5.5.0  RHEL 5.5.0 PC
rhel5.4.4  RHEL 5.4.4 PC
rhel5.4.0  RHEL 5.4.0 PC
修改了bcec162节点的/etc/libvirt/qemu.conf文件:
# The user ID for QEMU processes run by the system instance
user = "root"
# The group ID for QEMU processes run by the system instance
group = "root"
# Whether libvirt should dynamically change file ownership
# to match the configured user/group above. Defaults to 1.
# Set to 0 to disable file ownership changes.
#dynamic_ownership = 0
bcec162节点迁移到node153节点成功。
[root@node153 43]# ll
total 5075464
-rw-r--r-- 1 root     root  287215779 Mar  8 11:11 checkpoint
-rw-r--r-- 1 oneadmin kvm   283538737 Mar  9 09:34 checkpoint.1362712278
-rw-r--r-- 1 oneadmin kvm         920 Mar  9 09:26 deployment.0
-rw-r--r-- 1 root     root 4621008896 Mar  9 10:14 disk.0
-rw-r----- 1 root     root     401408 Mar  9 09:26 disk.1
lrwxrwxrwx 1 oneadmin kvm          29 Mar  9 10:09 disk.1.iso -> /one_images_3.8.1/0/43/disk.1
--------------------------------------------------------------------------------------------------------
3、仅修改node152节点的/etc/libvirt/qemu.conf文件:
# The user ID for QEMU processes run by the system instance
#user = "root"
# The group ID for QEMU processes run by the system instance
#group = "root"
# Whether libvirt should dynamically change file ownership
# to match the configured user/group above. Defaults to 1.
# Set to 0 to disable file ownership changes.
dynamic_ownership = 0
从bcec162节点迁移到node152不成功,日志如下:
Sat Mar  9 10:31:47 2013 [LCM][I]: New VM state is SAVE_MIGRATE
Sat Mar  9 10:31:54 2013 [VMM][I]: save: Moving old checkpoint file /one_images_3.8.1/0/43/checkpoint
Sat Mar  9 10:31:54 2013 [VMM][I]: ExitCode: 0
Sat Mar  9 10:31:54 2013 [VMM][I]: Successfully execute virtualization driver operation: save.
Sat Mar  9 10:31:54 2013 [VMM][I]: ExitCode: 0
Sat Mar  9 10:31:54 2013 [VMM][I]: Successfully execute network driver operation: clean.
Sat Mar  9 10:31:55 2013 [LCM][I]: New VM state is PROLOG_MIGRATE
Sat Mar  9 10:31:55 2013 [TM][I]: mv: -------------------------/one_images_3.8.1/0/43/disk.0
Sat Mar  9 10:31:55 2013 [TM][I]: ExitCode: 0
Sat Mar  9 10:35:02 2013 [TM][I]: mv: Moving bcec162:/one_images_3.8.1/0/43 to node152:/one_images_3.8.1/0/43
Sat Mar  9 10:35:02 2013 [TM][I]: mv: -------------------target copyy
Sat Mar  9 10:35:02 2013 [TM][I]: mv: ++++++++++++++++++++++end copy
Sat Mar  9 10:35:02 2013 [TM][I]: ExitCode: 0
Sat Mar  9 10:35:02 2013 [LCM][I]: New VM state is BOOT
Sat Mar  9 10:35:03 2013 [VMM][I]: ExitCode: 0
Sat Mar  9 10:35:03 2013 [VMM][I]: Successfully execute network driver operation: pre.
Sat Mar  9 10:35:07 2013 [VMM][I]: Command execution fail: /var/tmp/one/vmm/kvm/restore /one_images_3.8.1/0/43/checkpoint node152 43 node152
Sat Mar  9 10:35:07 2013 [VMM][E]: restore: Command "virsh --connect qemu:///system restore /one_images_3.8.1/0/43/checkpoint" failed: error: Failed to restore domain from /one_images_3.8.1/0/43/checkpoint
Sat Mar  9 10:35:07 2013 [VMM][I]: error: operation failed: failed to retrieve chardev info in qemu with 'info chardev'
Sat Mar  9 10:35:07 2013 [VMM][E]: Could not restore from /one_images_3.8.1/0/43/checkpoint
Sat Mar  9 10:35:07 2013 [VMM][I]: ExitCode: 1
Sat Mar  9 10:35:07 2013 [VMM][I]: Failed to execute virtualization driver operation: restore.
Sat Mar  9 10:35:07 2013 [VMM][E]: Error restoring VM: Could not restore from /one_images_3.8.1/0/43/checkpoint
Sat Mar  9 10:35:07 2013 [DiM][I]: New VM state is FAILED
登陆到node152节点执行restore命令:
[root@node152 43]# virsh restore checkpoint
error: Failed to restore domain from checkpoint
error: internal error process exited while connecting to monitor: qemu: could not open disk image /one_images_3.8.1/0/43/disk.0: Permission denied
将/etc/libvirt/qemu.conf文件中注释掉dynamic_ownership=0,开启user=root和group=root. 
如果开启dynamic_ownership则恢复虚拟机也会报出上面的错误信息。
在node152节点上恢复虚拟机:
[root@node152 43]# virsh restore checkpoint
Domain restored from checkpoint
[root@node152 43]# virsh list
 Id Name                 State
----------------------------------
117 one-43               running
参考文章:
https://wiki.archlinux.org/index.php/QEMU_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)
http://hi.baidu.com/juacm/item/f1fc3f98d8428ad07a7f01e2

转载请保持原链接:http://www.blogjava.net/ldwblog/archive/2013/03/08/396187.html
posted @ 2013-03-08 12:03 David1228 阅读(570) | 评论 (0)编辑 收藏
项目组内一位同事,在重构代码过程中将几个模块的Service层接口去掉后. 修改成了没有实现任何接口的类,并且继承了一个抽象基类。
然后我更新代码后执行系统中的该模块,发现部分表数据没有完整持久到数据库中。看了下代码和spring配置文件,原来调整后的Biz的业务类没有配置事务导致的。
修改了下spring配置文件(beanNames绑定了*Biz):
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    <bean id= "propertyConfigurer"          
        class 
= "com.ccms.base.util.DecryptPropertyPlaceholderConfigurer" >          
     <property name="locations" value= "classpath:sysConfig.properties" />          
   </bean>      
    <!-- 
   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName">
            <value>com.mysql.jdbc.Driver</value>
        </property>
        <property name="url">
            <value>${dataSource.jdbcUrl}&amp;useUnicode=true&amp;characterEncoding=UTF-8</value>
        </property>
        <property name="username">
            <value>${dataSource.userName}</value>
        </property>
        <property name="password">
            <value>${dataSource.password}</value>
        </property>
        <property name="maxActive">
            <value>100</value>
        </property>
        <property name="initialSize">
            <value>5</value>
        </property>
        <property name="maxIdle">
            <value>10</value>
        </property>
        <property name="minIdle">
            <value>0</value>
        </property>
        <property name="maxWait">
            <value>-1</value>
        </property>
        <property name="defaultAutoCommit">
            <value>false</value>
        </property>
        <property name="testOnBorrow">
            <value>true</value>
        </property>
        <property name="testWhileIdle">
            <value>true</value>
        </property>
        <property name="timeBetweenEvictionRunsMillis">
            <value>600000</value>
        </property>
        <property name="numTestsPerEvictionRun">
            <value>20</value>
        </property>
        <property name="minEvictableIdleTimeMillis">
            <value>3600000</value>
        </property>
    </bean>
   
-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" >
        <property name="driverClass" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUrl" value="${dataSource.jdbcUrl}&amp;useUnicode=true&amp;characterEncoding=UTF-8" />
        <property name="user" value="${dataSource.userName}" />
        <property name="password" value="${dataSource.password}" />
          <property name="minPoolSize" value="5" />
        <property name="maxPoolSize" value="50" />
        <property name="maxStatements" value="0" />
        <property name="idleConnectionTestPeriod" value="60" />
        <property name="acquireRetryAttempts" value="3" />
    </bean>

    <!-- Session Factory -->
    <bean id="sessionFactory"
        class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource">
            <ref local="dataSource" />
        </property>
    <!-- hbm配置文件的classPath路径 -->
        <property name="mappingDirectoryLocations">
            <list>
                <value>classpath:/com/ccms/base/mapping</value>
            </list>
        </property>

        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.generate_statistics">true</prop>
                <prop key="hibernate.connection.release_mode">auto</prop>
                <prop key="hibernate.autoReconnect">true</prop> 
                <prop key="hibernate.connection.autocommit">false</prop>
                <!-- <prop key="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</prop> -->
            </props>
        </property>
    </bean>

    <bean id="myTransactionManager"
        class
="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref bean="sessionFactory" />
        </property>
    </bean> 

    <bean id="transactionInterceptor"
        class
="org.springframework.transaction.interceptor.TransactionInterceptor">
        <property name="transactionManager" ref="myTransactionManager" />
        <property name="transactionAttributes">
            <props>
                <prop key="*">PROPAGATION_REQUIRED,-Exception</prop>
            </props>
        </property>
    </bean>
    <bean  class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
        <property name="transactionInterceptor"
            ref
="transactionInterceptor" />
    </bean>
    <bean
        
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames">
            <list>
                <value>*Service</value>
                <value>*Biz</value>
            </list>
        </property>
        <property name="interceptorNames">
            <list>
                <value>transactionInterceptor</value>
            </list>
        </property>
    </bean>
</beans>

启动tomcat后报出如下错误信息:
[2013-03-05 10:36:56] [ERROR] Context initialization failed - at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:215) 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loginBiz' defined in ServletContext resource [/WEB-INF/spring-service-resource.xml]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.ccms.login.LoginBiz]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:445)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:383)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:353)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:245)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:169)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:242)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:400)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:736)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:369)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:261)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4135)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4630)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:785)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:445)
at org.apache.catalina.core.StandardService.start(StandardService.java:519)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:581)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.ccms.login.LoginBiz]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:213)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:433)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:299)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:331)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1266)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:438)
... 28 more
Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at net.sf.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:718)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:499)
at net.sf.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:201)
... 34 more
2013-3-5 10:36:56 org.apache.catalina.core.StandardContext listenerStart
严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loginBiz' defined in ServletContext resource [/WEB-INF/spring-service-resource.xml]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.ccms.login.LoginBiz]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:445)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:383)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:353)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:245)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:169)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:242)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:400)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:736)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:369)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:261)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4135)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4630)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:785)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:445)
at org.apache.catalina.core.StandardService.start(StandardService.java:519)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:581)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.ccms.login.LoginBiz]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:213)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:433)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:299)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:331)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1266)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:438)
... 28 more
Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at net.sf.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:718)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:499)
at net.sf.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:201)
... 34 more
2013-3-5 10:36:56 org.apache.catalina.core.StandardContext start

------------------------------------------
通过以上错误分析之:对于实现了接口的类,直接用了JDK的动态代理,把目标对象扔给JDK的Proxy,拿到代理对象就OK了。然而对于没有实现接口的类,Spring借助于CGLIB来实现代理。
解决办法:
当使用CGLIB来实现代理后,没有实现接口的类
1、 通过构造函数形式注入时必须有默认的构造函数,否则就会出现上面的异常。
2、通过生产setter或者getter方法注入。
3、通过修改Spring的CglibProxyFactory工厂类。

详细解析可以参照这篇文章:http://netfork.iteye.com/blog/286215
posted @ 2013-03-05 14:54 David1228 阅读(8375) | 评论 (0)编辑 收藏

Deserializes JavaScript Object Notation (JSON) text to produce a JavaScript value.

JSON.parse(text [, reviver]) 
Arguments

text

Required. Valid JSON text.

reviver

Optional. A function that filters and transforms the results. The deserialized object is traversed recursively, and the reviver function is called for each member of the object in post-order (every object is revived after all its members have been revived). For each member, the following occurs:

  • If reviver returns a valid value, the member value is replaced with the value returned by reviver.

  • If reviver returns what it received, the structure is not modified.

  • If reviver returns null or undefined, the object member is deleted.

The reviver argument is often used to transform JSON representation of International Organization for Standardization (ISO) date strings into Coordinated Universal Time (UTC) format Date objects.

Return Value

A JavaScript value—an object or array.

Exceptions

Exception

Condition

JavaScript parser errors

The input text does not comply with JSON syntax. To correct the error, do one of the following:

  • Modify the text argument to comply with JSON syntax. For more information, see the BNF syntax notation of JSON objects.

  • Make sure that the text argument was serialized by a JSON-compliant implementation, such as, JSON.stringify.

Example

This example uses JSON.parse to deserialize JSON text into the contact object.

var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}'; var contact = JSON.parse(jsontext); var fullname = contact.surname + ", " + contact.firstname; // The value of fullname is "Aaberg, Jesper" 

This example uses JSON.parse to deserialize an ISO-formatted date string. The dateReviver function returns Date objects for members that are formatted like ISO date strings.

var jsontext = '{ "hiredate": "2008-01-01T12:00:00Z", "birthdate": "2008-12-25T12:00:00Z" }'; var dates = JSON.parse(jsontext, dateReviver); var string = dates.birthdate.toUTCString(); // The value of string is "Thu, 25 Dec 2008 12:00:00 UTC"  function dateReviver(key, value) {     var a;     if (typeof value === 'string') {         a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);         if (a) {             return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],                             +a[5], +a[6]));         }     }     return value; }; 
Requirements

Supported in the following document modes: Internet Explorer 8 standards, Internet Explorer 9 standards. See Version Information.

Not supported in the following document modes: Quirks, Internet Explorer 6 standards, Internet Explorer 7 standards.

Serializes a JavaScript value into JavaScript Object Notation (JSON) text.

JSON.stringify(value [, replacer] [, space]) 
value

Required. A JavaScript value, usually an object or array, to be serialized.

replacer

Optional. A function or array that filters and transforms the results.

If replacer is a function, JSON.stringify calls the function, passing in the key and value of each member. The return value is serialized instead of the original value. If the function returns undefined, the member will be excluded from the serialization. The key for the root object is an empty string: "".

If replacer is an array, only members with key values in the array will be serialized. The order of serialization is the same as the order of the keys in the array. Thereplacer array is ignored when the value argument is also an array.

space

Optional. Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.

If space is omitted, the return-value text is generated without any extra white space.

If space is a number, the return-value text is indented with the specified number of white spaces at each level. If space is greater than 10, text is indented 10 spaces.

If space is a non-empty string, such as '\t', the return-value text is indented with the characters in the string at each level.

If space is a string that is longer than 10 characters, the first 10 characters are used.

A string that contains the serialized JSON text.

Exception

Condition

Invalid replacer argument

The replacer argument is not a function or an array.

Circular reference in value argument not supported

The value argument contains a circular reference.

If the value that is being serialized has a toJSON method, the JSON.stringify function calls the toJSON method and uses the return value for serialization. If the return value of the toJSON method is undefined, the member will not be serialized. This enables an object to determine its own JSON representation.

Values that do not have JSON representations, such as undefined, will not be serialized. In objects, they will be dropped. In arrays, they will be replaced with null.

String values begin and end with a quotation mark. All Unicode characters may be enclosed in the quotation marks except for the characters that must be escaped by using a backslash. The following characters must be preceded by a backslash:

  • Quotation mark (")

  • Backslash (\)

  • Backspace (b)

  • Formfeed (f)

  • Newline (n)

  • Carriage return (r)

  • Horizontal tab (t)

  • Four-hexadecimal-digits (uhhhh)

Order of Execution

During the serialization process, if a toJSON method exists for the value argument, JSON.stringify first calls the toJSON method. If it does not exist, the original value is used. Next, if a replacer argument is provided, the value (original value or toJSON return-value) is replaced with the return-value of the replacer argument. Finally, white spaces are added to the value based on the optional space argument to generate the final serialized JSON text.

This example uses JSON.stringify to serialize the contact object to JSON text. The memberfilter array is defined so that only the surname and phone members are serialized. The firstname member is omitted.

var contact = new Object(); contact.firstname = "Jesper"; contact.surname = "Aaberg"; contact.phone = ["555-0100", "555-0120"];  var memberfilter = new Array(); memberfilter[0] = "surname"; memberfilter[1] = "phone"; var jsonText = JSON.stringify(contact, memberfilter, "\t"); /* The value of jsonText is: '{     "surname": "Aaberg",     "phone": [         "555-0100",         "555-0120"     ] }' */ 

This example uses JSON.stringify to serialize an array. The replaceToUpper function converts every string in the array to uppercase.

var continents = new Array(); continents[0] = "Europe"; continents[1] = "Asia"; continents[2] = "Australia"; continents[3] = "Antarctica"; continents[4] = "North America"; continents[5] = "South America"; continents[6] = "Africa";  var jsonText = JSON.stringify(continents, replaceToUpper); /* The value of jsonText is: '"EUROPE,ASIA,AUSTRALIA,ANTARCTICA,NORTH AMERICA,SOUTH AMERICA,AFRICA"' */  function replaceToUpper(key, value) {     return value.toString().toUpperCase(); } 

This example uses the toJSON method to serialize string member values in uppercase.

var contact = new Object();  contact.firstname = "Jesper"; contact.surname = "Aaberg"; contact.phone = ["555-0100", "555-0120"];  contact.toJSON = function(key)  {     var replacement = new Object();     for (var val in this)     {         if (typeof (this[val]) === 'string')             replacement[val] = this[val].toUpperCase();         else             replacement[val] = this[val]     }     return replacement; };  var jsonText = JSON.stringify(contact);  /* The value of jsonText is: '{"firstname":"JESPER","surname":"AABERG","phone":["555-0100","555-0120"]}' */ 

Supported in the following document modes: Internet Explorer 8 standards, Internet Explorer 9 standards. See Version Information.

Not supported in the following document modes: Quirks, Internet Explorer 6 standards, Internet Explorer 7 standards.




http://msdn.microsoft.com/library/cc836459(VS.85).aspx

posted @ 2013-03-04 16:59 David1228 阅读(714) | 评论 (0)编辑 收藏


转载自:http://linuxtoy.org/archives/kvm-issue.html

笔者在部署 KVM 虚拟机时曾遇到一个奇怪的问题,几经探索之后终于解决,现在写出来跟大家分享一下。

笔者在单位部署了一台服务器,上面运行着几部 KVM 虚拟机,分别执行不同的任务。系统上线之后,需要再增加几部虚拟机。因为当初部署服务器时做了虚拟机备份,所以就复制了一个备份的虚拟机。可是新虚拟机启动之后无法在本地网络上找到新虚拟机的 IP 地址(本地网络采用 DHCP 分配 IP 地址)!因为服务器是远程控制的,当然新虚拟机也就无法使用了。

为了查找原因,笔者把虚拟机复制到本地主机上,用正常方法开启。启动过程及登录都很正常,于是检查网卡状况:

$ ifconfig 

可是却只有显示 lo 信息! 怪了,eth0 呢?只有 lo 当然是没有办法同网络通讯的。于是查找一下启动信息:

$ dmesg | grep eth 

发现如下信息:

udev: renamed network interface eth0 to eth1 

原来 eth0 已经没有了,被命名为 eth1, 再看网卡配置

$ cat /etc/network/interfaces auto eth0 iface eth0 inet dhcp 

至此事情水落石出,原来 KVM 是在启动时传递 mac 参数的,如笔者是用下面命令启动 KVM 虚拟机:

$ sudo kvm -m 256 -hda /data/kvm/mail.img -net nic,vlan=0,macaddr=52-54-00-12-30-05 -net tap,vlan=0,ifname=tap5,script=no -boot c -smp 2 -daemonize -nographic & 

注意上面的 macaddr=52-54-00-12-30-05,这就是虚拟机启动后的网卡 mac,因为网络内不可以有相同的 mac,所以启动每个虚拟机的 mac 都要改。可是当换了新的 mac 后,虚拟机里的系统就认为换了新网卡,所以系统改变 eth0 为 eth1,而在网卡设置里面却只设置了 eth0, 所以虚拟机启动之后并没有启动新的 eth1 网卡,当然就连不上网络了。原因找到了之后问题的解决也就非常简单:

$ vi /etc/network/interfaces 

增加以下内容:

auto eth1 iface eth1 inet dhcp 

再重新启动网络:

$ /etc/init.d/networking restart 

至此问题应该就完全解决了。不过有个问题还要注意,如果有多次用不同的 mac 启动虚拟机,可能你的虚拟机里已经有了 eth2, eth3 甚至是 10 都是有可能的,因为你每用一个新的 mac 去启动虚拟机,系统就会增加一个网卡。可以修改下面这个文件:

$ vi /etc/udev/rules.d/70-persistent-net.rules 

删除所有的的 ethX 行,重启虚拟机即可。

{ Thanks 逸飞. }

posted @ 2013-02-20 11:41 David1228 阅读(800) | 评论 (0)编辑 收藏
WARNING: The file has been changed since reading it!!!
Do you really want to write to it (y/n)?y
"/proc/sys/net/ipv4/ip_forward" E667: Fsync failed
Hit ENTER or type command to continue

编辑/etc/sysctl.conf

net.ipv4.ip_forward = 0
改成
net.ipv4.ip_forward = 1
如果此文件中没有这个选项则将其添加上就行。
然后执行命令:#sysctl -p
使其生效。
[root@IBM-007 sudo]# sysctl -p
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
vm.min_free_kbytes = 65536
kernel.panic_on_oops = 1
kernel.panic = 60
[root@IBM-007 sudo]# 
[root@IBM-007 sudo]# 
[root@IBM-007 sudo]# ll /
[root@IBM-007 sudo]# 
再一次的查看
[root@IBM-007 sudo]# cat /proc/sys/net/ipv4/ip_forward
1
可以发现其原来的0就变成了1. 
posted @ 2013-01-30 14:12 David1228 阅读(5550) | 评论 (0)编辑 收藏
#!/bin/bash
# Title   : {stop|start|restart} Tomcat . Default is "restart".
# Author  : Cheng PJ
# E-mail  : 7looki@gmail.com
# Version : 1.0
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
file_name_f1=`echo ${0} | awk -F / '{print $1}'`
file_name_f2=`echo ${0} | awk -F / '{print $NF}'`
file_pwd=`echo ${0} | sed 's#'/${file_name_f2}'$##g'`
if [ -z "${file_name_f1}" ] || [ ${file_name_f1} != ${file_name_f2} ]; then
    cd ${file_pwd}
fi
tomcat_bin=`pwd`
if [ ! -f ${tomcat_bin}/startup.sh ] || [ ! -f ${tomcat_bin}/bootstrap.jar ] || [ ! -f ${tomcat_bin}/catalina.sh ]; then
    echo ""
    echo "This script must be in the directory under \${Tomcat_Home}/bin !"
    echo ""
    exit 1
fi
tomcat_whoami=`whoami`
tomcat_own_user=`ls -l ${tomcat_bin}/startup.sh | awk '{print $3}'`
tomcat_who_run=`ps -ef | grep ${tomcat_bin} |  grep -v "grep\|${0}" | awk '{print $1}'`
tomcat_who_run_other=`ps -ef | grep ${tomcat_bin} | grep -v "grep\|${0}" | awk '{print $1}' | grep -v "${tomcat_who_run}\|root" | sort | uniq`
tomcat_run_num=`ps -ef | grep ${tomcat_bin} |  grep -v "grep\|${0}" | wc -l`
tomcat_echo_stop () {
    echo "Tomcat Stopping ...          [OK]"
    echo ""
}
tomcat_echo_start () {
    echo ""
    echo "Tomcat Starting ...          [OK]"
}
tomcat_echo_error () {
    echo ""
    echo "Tomcat Stopped ERROR ! Please check privilege or something !"
    echo ""
    exit 1
}
tomcat_stop () {
    if [ ${tomcat_who_run} == ${tomcat_whoami} ] || [ ${tomcat_whoami} == "root" ]; then
        ps -ef | grep ${tomcat_bin} |  grep -v "grep\|${0}" | awk '{print $2}' | xargs kill -9
        if [ $? -eq 0 ]; then
            tomcat_echo_stop;
        else
            tomcat_echo_error;
        fi
        
    else
        echo "ERROR ! You must root or ${tomcat_who_run} to run this script !"
        exit 1
    fi
}
tomcat_start () {
    if [ ${tomcat_own_user} == ${tomcat_whoami} ] || [ ${tomcat_own_user} == "root" ]; then
        sh ${tomcat_bin}/startup.sh
        if [ $? -eq 0 ]; then
            tomcat_echo_start;
        else
            tomcat_echo_error;
        fi
    else
        echo "ERROR ! You must root or ${tomcat_own_user} to run this script !"
        exit 1
    fi
}
tomcat_shutdown () {
    if [ ${tomcat_run_num} -eq 0 ]; then
        echo "Tomcat is not running!"
        echo ""
    elif [ ${tomcat_run_num} -eq 1 ]; then
        tomcat_stop;
    else
        if [ ${tomcat_who_run_other} == "" ]; then
            tomcat_stop;
 
        else
            echo "Please shutdown Tomcat with other users (${tomcat_who_run_other}) "
            echo "Tomcat is not stopped !"
            exit 1
        fi
    fi
}
tomcat_startup () {
    tomcat_run_check=`ps -ef | grep ${tomcat_bin} |  grep -v "grep\|${0}" | wc -l`
    if [ ${tomcat_run_check} -eq 0 ]; then
        tomcat_start;
    else
        echo "Tomcat is not stopped ! Please stop Tomcat at first !"
        echo 1
    fi
}
case "$1" in
    start|-start|--start)
        tomcat_startup
        ;;
    stop|-stop|--stop)
        tomcat_shutdown
        ;;
    help|-help|--help)
        echo ""
        echo "This script used for {start|stop|restart} Tomcat !"
        echo ""
        echo "                                      By ST.7looki"
        echo "                                  7looki@gmail.com"
        echo ""
        ;;
    restart|-restart|--restart|*)
        tomcat_shutdown
        sleep 1
        tomcat_startup
esac
posted @ 2013-01-30 10:48 David1228 阅读(1334) | 评论 (2)编辑 收藏
Netperf使用
转载自:http://os.chinaunix.net/a2004/0708/1042/000001042354.shtml 
  本文首先介绍网络性能测量的一些基本概念和方法,然后结合 netperf 工具的使用,具体的讨论如何测试不同情况下的网络性能。
  在构建或管理一个网络系统时,我们更多的是关心网络的可用性,即网络是否连通,而对于其整体的性能往往考虑不多,或者即使考虑到性能的问题,但是却发现没有合适的手段去测试网络的性能。
  
  当开发出一个网络应用程序后,我们会发现,在实际的网络环境使用中,网络应用程序的使用效果不是很理想,问题可能出现在程序的开发上面,也有可能由于实际的网络环境中存在着瓶颈。面对这种问题,程序员一般会一筹莫展,原因就在于不掌握一些网络性能测量的工具。
  
  在本文中,首先介绍网络性能测量的一些基本概念和方法,然后结合 netperf 工具的使用,具体的讨论如何测试不同情况下的网络性能。
  
  网络性能测试概述
  网络性能测量的五项指标
  测量网络性能的五项指标是:
  
  可用性(availability) 
  响应时间(response time) 
  网络利用率(network utilization) 
  网络吞吐量(network throughput) 
  网络带宽容量(network bandwidth capacity) 
  1. 可用性
  
  测试网络性能的第一步是确定网络是否正常工作,最简单的方法是使用 ping 命令。通过向远端的机器发送 icmp echo request,并等待接收 icmp echo reply 来判断远端的机器是否连通,网络是否正常工作。
  
  Ping 命令有非常丰富的命令选项,比如 -c 可以指定发送 echo request 的个数,-s 可以指定每次发送的 ping 包大小。
  
  网络设备内部一般有多个缓冲池,不同的缓冲池使用不同的缓冲区大小,分别用来处理不同大小的分组(packet)。例如交换机中通常具有三种类型的包缓冲:一类针对小的分组,一类针对中等大小的分组,还有一类针对大的分组。为了测试这样的网络设备,测试工具必须要具有发送不同大小分组的能力。Ping 命令的 -s 就可以使用在这种场合。
  
  2. 响应时间
  
  Ping 命令的 echo request/reply 一次往返所花费时间就是响应时间。有很多因素会影响到响应时间,如网段的负荷,网络主机的负荷,广播风暴,工作不正常的网络设备等等。
  
  在网络工作正常时,记录下正常的响应时间。当用户抱怨网络的反应时间慢时,就可以将现在的响应时间与正常的响应时间对比,如果两者差值的波动很大,就能说明网络设备存在故障。
  
  3. 网络利用率
  
  网络利用率是指网络被使用的时间占总时间(即被使用的时间+空闲的时间)的比例。比如,Ethernet 虽然是共享的,但同时却只能有一个报文在传输。因此在任一时刻,Ethernet 或者是 100% 的利用率,或者是 0% 的利用率。
  
  计算一个网段的网络利用率相对比较容易,但是确定一个网络的利用率就比较复杂。因此,网络测试工具一般使用网络吞吐量和网络带宽容量来确定网络中两个节点之间的性能。
  
  4. 网络吞吐量
  
  网络吞吐量是指在某个时刻,在网络中的两个节点之间,提供给网络应用的剩余带宽。
  
  网络吞吐量可以帮组寻找网络路径中的瓶颈。比如,即使 client 和 server 都被分别连接到各自的 100M Ethernet 上,但是如果这两个 100M 的Ethernet 被 10M 的 Ethernet 连接起来,那么 10M 的 Ethernet 就是网络的瓶颈。
  
  网络吞吐量非常依赖于当前的网络负载情况。因此,为了得到正确的网络吞吐量,最好在不同时间(一天中的不同时刻,或者一周中不同的天)分别进行测试,只有这样才能得到对网络吞吐量的全面认识。
  
  有些网络应用程序在开发过程的测试中能够正常运行,但是到实际的网络环境中却无法正常工作(由于没有足够的网络吞吐量)。这是因为测试只是在空闲的网络环境中,没有考虑到实际的网络环境中还存在着其它的各种网络流量。所以,网络吞吐量定义为剩余带宽是有实际意义的。
  
  5. 网络带宽容量
  
  与网络吞吐量不同,网络带宽容量指的是在网络的两个节点之间的最大可用带宽。这是由组成网络的设备的能力所决定的。
  
  测试网络带宽容量有两个困难之处:在网络存在其它网络流量的时候,如何得知网络的最大可用带宽;在测试过程中,如何对现有的网络流量不造成影响。网络测试工具一般采用 packet pairs 和 packet trains 技术来克服这样的困难。
  
  收集网络性能数据的方式
  当确定了网络性能的测试指标以后,就需要使用网络测试工具收集相应的性能数据,分别有三种从网络获取数据的方式:
  
  1. 通过snmp协议直接到网络设备中获取,如net-snmp工具
  
  2. 侦听相关的网络性能数据,典型的工具是tcpdump
  
  3. 自行产生相应的测试数据,如本文中使用的netperf工具
  
  Netperf
  Netperf是一种网络性能的测量工具,主要针对基于TCP或UDP的传输。Netperf根据应用的不同,可以进行不同模式的网络性能测试,即批量数据传输(bulk data transfer)模式和请求/应答(request/reponse)模式。Netperf测试结果所反映的是一个系统能够以多快的速度向另外一个系统发送数据,以及另外一个系统能够以多块的速度接收数据。
  
  Netperf工具以client/server方式工作。server端是netserver,用来侦听来自client端的连接,client端是netperf,用来向server发起网络测试。在client与server之间,首先建立一个控制连接,传递有关测试配置的信息,以及测试的结果;在控制连接建立并传递了测试配置信息以后,client与server之间会再建立一个测试连接,用来来回传递着特殊的流量模式,以测试网络的性能。
  
  TCP网络性能
  由于TCP协议能够提供端到端的可靠传输,因此被大量的网络应用程序使用。但是,可靠性的建立是要付出代价的。TCP协议保证可靠性的措施,如建立并维护连接、控制数据有序的传递等都会消耗一定的网络带宽。
  
  Netperf可以模拟三种不同的TCP流量模式:
  
  1) 单个TCP连接,批量(bulk)传输大量数据
  
  2) 单个TCP连接,client请求/server应答的交易(transaction)方式
  
  3) 多个TCP连接,每个连接中一对请求/应答的交易方式
  
  UDP网络性能
  UDP没有建立连接的负担,但是UDP不能保证传输的可靠性,所以使用UDP的应用程序需要自行跟踪每个发出的分组,并重发丢失的分组。
  
  Netperf可以模拟两种UDP的流量模式:
  
  1) 从client到server的单向批量传输
  
  2) 请求/应答的交易方式
  
  由于UDP传输的不可靠性,在使用netperf时要确保发送的缓冲区大小不大于接收缓冲区大小,否则数据会丢失,netperf将给出错误的结果。因此,对于接收到分组的统计不一定准确,需要结合发送分组的统计综合得出结论。
  
  Netperf的命令行参数
  在unix系统中,可以直接运行可执行程序来启动netserver,也可以让inetd或xinetd来自动启动netserver。
  
  当netserver在server端启动以后,就可以在client端运行netperf来测试网络的性能。netperf通过命令行参数来控制测试的类型和具体的测试选项。根据作用范围的不同,netperf的命令行参数可以分为两大类:全局命令行参数、测试相关的局部参数,两者之间使用--分隔:
  
  netperf [global options]-- [test-specific options]
  
  这里我们只解释那些常用的命令行参数,其它的参数读者可以查询netperf的man手册。
  
  -H host :指定远端运行netserver的server IP地址。
  
  -l testlen:指定测试的时间长度(秒)
  
  -t testname:指定进行的测试类型,包括TCP_STREAM,UDP_STREAM,TCP_RR,TCP_CRR,UDP_RR,在下文中分别对它们说明。
  
  在后面的测试中,netserver运行在192.168.0.28,server与client通过局域网连接(100M Hub)。
  
  Netperf测试网络性能
  测试批量(bulk)网络流量的性能
  
  批量数据传输典型的例子有ftp和其它类似的网络应用(即一次传输整个文件)。根据使用传输协议的不同,批量数据传输又分为TCP批量传输和UDP批量传输。
  
  1. TCP_STREAM
  
  Netperf缺省情况下进行TCP批量传输,即-t TCP_STREAM。测试过程中,netperf向netserver发送批量的TCP数据分组,以确定数据传输过程中的吞吐量:
  
   ./netperf -H 192.168.0.28 -l 60
  TCP STREAM TEST to 192.168.0.28
  Recv  Send  Send
  Socket Socket Message Elapsed
  Size  Size  Size   Time   Throughput
  bytes bytes  bytes  secs.  10^6bits/sec
 
   87380 16384 16384  60.00   88.00
 
  从netperf的结果输出中,我们可以知道以下的一些信息:
  
  1) 远端系统(即server)使用大小为87380字节的socket接收缓冲
  
  2) 本地系统(即client)使用大小为16384字节的socket发送缓冲
  
  3) 向远端系统发送的测试分组大小为16384字节
  
  4) 测试经历的时间为60秒
  
  5) 吞吐量的测试结果为88Mbits/秒
  
  在缺省情况下,netperf向发送的测试分组大小设置为本地系统所使用的socket发送缓冲大小。
  
  TCP_STREAM方式下与测试相关的局部参数如下表所示:
  
 

  通过修改以上的参数,并观察结果的 。






posted @ 2013-01-21 12:31 David1228 阅读(328) | 评论 (0)编辑 收藏
使用httpd时候碰到一个问题,共享一下。
BC-EC配置tomcat的时候占用8443端口,如果tomcat服务器又作为http服务器,启动httpd服务的时候就报错,8443端口被占用。反过来httpd占用8443,tomcat启动就报错。
解决办法:
编辑 /etc/httpd/conf.d/nss.conf配置文件,将该文件中的
nss.conf:Listen 8443
nss.conf:<VirtualHost _default_:8443>
改成
nss.conf:Listen 8444
nss.conf:<VirtualHost _default_:8444>
 
这样启动httpd和tomcat就互不影响了。
posted @ 2013-01-18 11:22 David1228 阅读(1880) | 评论 (0)编辑 收藏
--------------------------- 下面是在不启动虚机的情况下,修改虚机磁盘文件的方法(增加一种调试的手段) ---------------------------------
-- 首先关闭虚机
# losetup /dev/loop100 /one_images/5/images/disk.0
# kpartx -a /dev/loop100
-- 通过以上两个命令后,可以在/dev/mapper/目录下看到虚机的两个分区设备 loop100p1、loop100p2 (一般loop100p1是根分区)(loop设备找一个空闲的即可,我这里写的是loop100)
# mount /dev/mapper/loop100p1 /mnt
-- 将虚机根分区挂载到/mnt目录,这时虚机的文件系统结构就都在/mnt目录下了(可以进行读写操作)
# umount /mnt
# kpartx -d /dev/loop100
# losetup -d /dev/loop100
-- 通过以上三个命令卸载,重新启动虚机,修改都生效了。(测试虚机系统centos-5.5-x86_64)
posted @ 2013-01-18 11:21 David1228 阅读(252) | 评论 (0)编辑 收藏
记录下,转自:http://blog.csdn.net/wonderful19891024/article/details/6166264

主机自带硬盘超过300GB,目前只划分使用了3个主分区,不到70GB,如 下:
[root@db2 ~]# df -h 
Filesystem Size Used Avail Use% Mounted on 
/dev/sda1 29G 3.7G  24G 14% / 
/dev/sda2 29G  22G 5.2G 81% /oracle 
tmpfs    2.0G    0 2.0G  0% /dev/shm 

[root@db2 ~]# cat /proc/partitions
major minor  #blocks  name

   8     0  311427072 sda
    sda1
   8     2   30716280 sda2
   8     3    8193150 sda3
   8    16     976896 sdb
   8    32     976896 sdc

现在需要给系统添加1个100GB的空间存放数据文件,而又不影响现有系统上业务的运行,
使用fdisk结合partprobe命令不重启系统添加 一块新的磁盘分区。操作步骤如下:

 

 


第1步,添加新的磁盘分区 
[root@db2 ~]# fdisk /dev/sda
The number of cylinders for this disk is set to 38770.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)

Command (m for help): p

Disk /dev/sda: 318.9 GB, 318901321728 bytes
255 heads, 63 sectors/track, 38770 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1        3824    30716248+  83  Linux
/dev/sda2            3825        7648    30716280   83  Linux
/dev/sda3            7649        8668     8193150   82  Linux swap / Solaris

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Selected partition 4
First cylinder (8669-38770, default 8669):
Using default value 8669
Last cylinder or +size or +sizeM or +sizeK (8669-38770, default 38770): +100G   
Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: 


Device or resource busy.
The kernel still uses the old table.
The new table will be used at the next reboot.
Syncing disks.
[root@db2 ~]#


第2步,使用工具partprobe让kernel读取分区信息 
[root@db2 ~]# partprobe
使用fdisk工具只是将分区信息写到磁盘,如果需要mkfs磁盘分区则需要重启系统,
而使用partprobe则可以使kernel重新读取分区 信息,从而避免重启系统。



第3步,格式化文件系统 
[root@db2 ~]# mkfs.ext3 /dev/sda4
mke2fs 1.39 (29-May-2006)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
12222464 inodes, 24416791 blocks
1220839 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4294967296
746 block groups
32768 blocks per group, 32768 fragments per group
16384 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 
    2654208, 4096000, 7962624, 11239424, 20480000, 23887872

Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information:

done

This filesystem will be automatically checked every 26 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
[root@db2 ~]#



第4步,mount新的分区/dev/sda4 
[root@db2 ~]# e2label  /dev/sda4 /data
[root@db2 ~]# mkdir /data
[root@db2 ~]# mount /dev/sda4 /data
[root@db2 ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1             29753556   3810844  24406900  14% /
/dev/sda2             29753588  11304616  16913160  41% /oracle
tmpfs                  2023936         0   2023936   0% /dev/shm
/dev/sda4             96132968    192312  91057300   1% /data
[root@db2 ~]#


posted @ 2012-11-29 14:56 David1228 阅读(264) | 评论 (0)编辑 收藏
个人说明:以下作者应该是在Ubuntu OS上做的测试。 感谢作者vpsee。
               本人在公司的Red Hat Enterprise Linux Server release 6.1 (Santiago) 服务器上做的测试,可参见最下面截图,监控Tomcat和其他日志信息。很是方便哈^^.
               由于Redhat OS上没有apt-get,如果缺少相应软件包,可以通过yum或者iso源方式安装缺少的软件。


转自:http://www.vpsee.com/2012/11/install-real-time-log-monitoring-tool-log-io/#comments 
日志是个好东西,对技术人员来说写日志能纪录成长,分享经验;对机器来说纪录日志能及时发现错误,为日后的排错提供信息。如果还在一台机器上用 tail -f 监听单个日志或者 multitail 监听多个日志也太 out 了,我们需要一种工具能纪录上百台机器、不同类型的日志,并最好能汇集到一个界面里方便查看,最好还是实时的。log.io 就是这样一个实时日志监控工具,采用 node.js + socket.io 开发,使用浏览器访问,每秒可以处理超过5000条日志变动消息。有一点要指出来的是 log.io 只监视日志变动并不存储日志,不过这个没关系,我们知道日志存储在哪个机器上。

和其他的监控工具一样,log.io 也采用服务器-客户端的模式。log.io 由两部分组成:server harvester, server 运行在机器 A(服务器)上监视和纪录其他机器发来的日志消息;log harvester 运行在机器 B(客户端)上用来监听和收集机器 B 上的日志改动,并将改动发送给机器 A,每个需要纪录日志的机器都需要一个 harvester.

在机器 A B

因为 log.io 基于 node.js,所以在服务器和客户端都要安装 node.js,这里采用编译安装的办法,首先安装需要的依赖包:

$ sudo apt-get install g++ make git libssl-dev pkg-config

下载 node.js 源代码,编译并安装:

$ wget http://nodejs.org/dist/v0.8.14/node-v0.8.14.tar.gz

$ tar zxvf node-v0.8.14.tar.gz

$ cd node-v0.8.14/

$ ./configure

$ make

$ sudo make install

安装 NPM

$ curl https://npmjs.org/install.sh | sudo sh

安装 log.io(包含了 log server log harvester

$ sudo npm config set unsafe-perm true

$ sudo npm install -g --prefix=/usr/local log.io

在机器 A 上启动 server

$ sudo log.io server start

在机器 B 上配置和启动 harvester

server 用来监听各个机器发来的日志消息,harvester 用来把本机的日志发给 server,所以 harvester 配置的时候需要指定 server 的主机地址(或域名)。如何告诉 harvester 哪些日志需要监控呢?log_file_paths 就是指定日志路径的地方。下面的配置是 harvester auth.log harvester.log 这两个日志的改动发送给 server

$ sudo vi /etc/log.io/harvester.conf

exports.config = {

  // Log server host & port

  server: {

    host: 'log.vpsee.com', // 也可以用 IP 地址

    port: 8998,

  },

 

  // Watch the following log files, defined by label:path mappings

  log_file_paths: {

    logio_auth: '/var/log/auth.log',

    logio_harvester: '/var/log/log.io/harvester.log',

  },

 

  instance_name : 'log_node_1'

}

启动 harvester

$ sudo log.io harvester start

测试

打开浏览器访问 log server 所在的机器 A,域名是 log.vpsee.com(也可以用 IP 地址),端口是 8998
======================================================================================
本人测试时harvester.conf文件配置如下:

/* Log.io log harvester configuration */
exports.config = {
  // Log server host & port
  server: {
    host: '192.168.32.92',
    port: 8998,
  },
  // Watch the following log files, defined by label:path mappings
  log_file_paths: {
    logio_tomcat: '/usr/local/tomcat6/logs/catalina.out',
logio_oned: '/opt/nebula/ONE/var/oned.log',    
logio_harvester: '/var/log/log.io/harvester.log',
  },
  // Define name of current machine.
  // Alternatively, you can set this name in /etc/profile:
  // export LOGIO_HARVESTER_INSTANCE_NAME='my_log_machine'
  // If so, comment out the line below
  instance_name : 'log_node_1'
}

posted @ 2012-11-06 15:49 David1228 阅读(1967) | 评论 (0)编辑 收藏
RHEL6 已经推出很久了 ,没想到在 RedHat 自家的 RHEL6 上安装 KVM 还有这么多问题,难道不应该是像 Apache/MySQL 那样安装完就可以用的么?(注:除去商标,CentOS 就是 RHEL,CentOS6 和 RHEL6 是一回事)。以下操作在 CentOS 6.2 最小化安装版本 CentOS-6.2-x86_64-minimal.iso 上完成,其他版本可能不会遇到本文提到的部分问题。

检查 CPU

和 Xen 不同,KVM 需要有 CPU 的支持(Intel VT 或 AMD SVM),在安装 KVM 之前检查一下 CPU 是否提供了虚拟技术的支持:

# egrep 'vmx|svm' /proc/cpuinfo ... flags		: fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm dca sse4_1 sse4_2 popcnt aes lahf_lm ida arat dts tpr_shadow vnmi flexpriority ept vpid 

安装 KVM

安装 KVM 很容易,要正常运行的话还需要折腾一下:

# yum -y install qemu-kvm libvirt python-virtinst bridge-utils 

安装完后关闭 selinux 并重启系统,然后确认一下是否 kvm 安装成功:

# vi /etc/sysconfig/selinux SELINUX=disabled  # reboot  # lsmod | grep kvm kvm_intel              50412  3  kvm                   305988  1 kvm_intel  # stat /dev/kvm   File: `/dev/kvm'   Size: 0         	Blocks: 0          IO Block: 4096   character special file Device: 5h/5d	Inode: 10584       Links: 1     Device type: a,e8 Access: (0666/crw-rw-rw-)  Uid: (    0/    root)   Gid: (   36/     kvm) Access: 2012-04-18 16:00:46.276341129 +0200 Modify: 2012-04-18 16:00:46.276341129 +0200 Change: 2012-04-18 16:00:46.276341129 +0200 

再来确认一下 libvirt 是否能正常启动和关闭。重启 libvirtd 服务的话会报错,查看日志发现 internal error Failed to create mDNS client 错误,这个问题容易改正,安装 avahi 即可,也可以去 /etc/libvirt/libvirtd.conf 设置 mdns_adv = 0,VPSee 这里采用安装 avahi 的方法:

# /etc/init.d/libvirtd restart Stopping libvirtd daemon:                                  [FAILED] Starting libvirtd daemon:                                  [  OK  ]  # tail /var/log/libvirt/libvirtd.log  2012-04-18 13:51:03.032+0000: 18149: info : libvirt version: 0.9.4, package: 23.el6_2.7 (CentOS BuildSystem , 2012-04-16-14:12:59, c6b5.bsys.dev.centos.org) 2012-04-18 13:51:03.032+0000: 18149: error : virNetServerMDNSStart:460 : internal error Failed to create mDNS client: Daemon not running  # yum -y install avahi # /etc/init.d/messagebus restart # /etc/init.d/avahi-daemon restart 

重启 libvirtd 服务继续报错,发现缺少 dmidecode 包,安装 dmidecode 后终于重启 libvirtd 成功 :

# /etc/init.d/libvirtd restart Stopping libvirtd daemon:                                  [FAILED] Starting libvirtd daemon:                                  [  OK  ]  # tail /var/log/libvirt/libvirtd.log  2012-04-18 13:54:54.654+0000: 18320: info : libvirt version: 0.9.4, package: 23.el6_2.7 (CentOS BuildSystem , 2012-04-16-14:12:59, c6b5.bsys.dev.centos.org) 2012-04-18 13:54:54.654+0000: 18320: error : virSysinfoRead:465 : internal error Failed to find path for dmidecode binary  # yum -y install dmidecode  # /etc/init.d/libvirtd restart Stopping libvirtd daemon:                                  [  OK  ] Starting libvirtd daemon:                                  [  OK  ] 

现在 kvm 和 libvirt 都安装成功和运行了,但并不表示可用了,问题接着来。

安装虚拟机

从 6 系列开始 RedHat 推荐使用 virt-install/virsh 系列工具操作 kvm,而不是直接使用 qemu-kvm,所以 qemu-kvm 被移到一个不起眼的地方 /usr/libexec/,做个链接:

# qemu-kvm -bash: qemu-kvm: command not found  # ls /usr/libexec/qemu-kvm  /usr/libexec/qemu-kvm  # ln -sf /usr/libexec/qemu-kvm /usr/bin/kvm 

VPSee 采用 RedHat 推荐的方式(virt-install)安装虚拟机,这里以安装 ubuntu-11.10-server-amd64.iso 为例:

# virt-install \ --name ubuntu \ --ram 512 \ --vcpus=1 \ --disk path=/root/ubuntu.img,size=10 \ --accelerate \ --cdrom /root/ubuntu-11.10-server-amd64.iso \ --graphics vnc 

开始安装,创建硬盘 ubuntu.img 后就报错,用的是 root 帐号居然还 Permission denied?!

Starting install... Creating storage file ubuntu.img                                 | 10.0 GB     00:00      ERROR    internal error Process exited while reading console log output: char device redirected to /dev/pts/1 qemu-kvm: -drive file=/root/ubuntu.img,if=none,id=drive-ide0-0-0,format=raw,cache=none: could not open disk image /root/ubuntu.img: Permission denied  Domain installation does not appear to have been successful. If it was, you can restart your domain by running:   virsh --connect qemu:///system start ubuntu otherwise, please restart your installation. 

修改 qemu.conf 配置,把下面几个地方的注释去掉,然后把 dynamic_ownership 的值改成0,禁止 libvirtd 动态修改文件的归属:

# vi /etc/libvirt/qemu.conf ... user = "root" group = "root" dynamic_ownership = 0 ... 

重启 libvirtd 服务再用上面的 virt-install 命令安装就应该可以了。这个时候 vnc 默认绑定的是本机 127.0.0.1,如果其他机器想用 vnc 客户端访问这台 kvm 服务器正在安装的 ubuntu 的话需要把 vnc 绑定到服务器的 IP 地址或者绑定到全局 0.0.0.0. 修改 qemu.conf 文件取消 vnc_listen 一行前面的注释,记得重启 libvirtd:

# vi /etc/libvirt/qemu.conf ... vnc_listen = "0.0.0.0" ...
转载自:http://www.vpsee.com/?s=qemu.conf
posted @ 2012-10-31 13:59 David1228| 编辑 收藏
假设您今天要开发一个动画编辑程式,动画由影格(Frame)组成,数个影格组合为动画清单,动画清单也可以由其它已完成的动画清单组成,也可以在动画清单与清单之间加入个别影格。无论是影格或动画清单都可以播放,而动画清单负责的就是组合影格或动画清单,所以可以这么设计:




对于Frame而言,Playlist是一个容器,然而Playlist也实作Playable,所以它也可以播放,您可以进一步地将Playlist组合至另一个Playlist中,以形成更长的播放清单。以Java实现的话。
以Java實現的話。
import java.util.*;

interface Playable {
void play();
}

class Frame implements Playable {
private String image;
Frame(String image) {
this.image = image;
}
public void play() {
System.out.println("播放 " + image);
}
}

class Playlist implements Playable {
private List<Playable> list = new ArrayList<Playable>();
public void add(Playable playable) {
list.add(playable);
}
public void play() {
for(Playable playable : list) {
playable.play();
}
}
}

public class Main {
public static void main(String[] args) {
Frame logo = new Frame("片頭 LOGO");

Playlist playlist1 = new Playlist();
playlist1.add(new Frame("Duke 左揮手"));
playlist1.add(new Frame("Duke 右揮手"));

Playlist playlist2 = new Playlist();
playlist2.add(new Frame("Duke 走左腳"));
playlist2.add(new Frame("Duke 走右腳"));

Playlist all = new Playlist();
all.add(logo);
all.add(playlist1);
all.add(playlist2);

all.play();
}
}

以Python實現的話:
class Frame:
def __init__(self, image):
self.image = image
def play(self):
print("播放 " + self.image)

class Playlist:
def __init__(self):
self.list = []
def add(self, playable):
self.list.append(playable);
def play(self):
for playable in self.list:
playable.play()

logo = Frame("片頭 LOGO")

playlist1 = Playlist()
playlist1.add(Frame("Duke 左揮手"))
playlist1.add(Frame("Duke 右揮手"))

playlist2 = Playlist()
playlist2.add(Frame("Duke 走左腳"))
playlist2.add(Frame("Duke 走右腳"))

all = Playlist()
all.add(logo)
all.add(playlist1)
all.add(playlist2)

all.play();以UML来表示Composite模式的结构:



具有层次性或组合性的物件可以使用Composite模式,像是电路元件、视窗元件等,使用Composite模式可以大大减低这些元件设计的复杂度,以Java标准API中AWT视窗元件为例,
Component上有个paint()方法,可以进行元件的绘制,Container可以容纳Component(如Button、Label等),而Container继承Component,所以Container也可以容纳Container,这也是Composite模式的实际例子:
 

from : http://caterpillar.onlyfun.net/Gossip/index.html 



posted @ 2012-10-12 16:20 David1228 阅读(230) | 评论 (0)编辑 收藏

云计算用一个朋友的话来说:”做云计算最苦逼的就是得时时刻刻为一些可能一辈子都碰不到的事做好准备。更苦逼的就是刚以为一个问题不会遇到,立刻就发生了。。。“。这个还真的没有办法,谁让哥我是搞云计算的呢,简单一个虚拟化就搞的你蛋疼,你还能想其它的吗?一直纠结在做虚拟化使用什么镜像格式,刚刚开始用了raw的file,后来发现LVM的很多特性对于虚拟化还是有比较理想的能力,而且性能也很不错就用了LVM。后来被VMware骗了跑去搞Esxi接触了VMDK,最近研究openstack发现了qcow2格式,貌似现在很流行呀。也说不上分析这些镜像格式的能力,就简单说说自己的一些使用心得。

目前主要有那些格式来作为虚拟机的镜像:
raw
(default) the raw format is a plain binary image of the disc image, and is very portable. On filesystems that support sparse files, images in this format only use the space actually used by the data recorded in them.
老牌的格式了,用一个字来说就是裸,也就是赤裸裸,你随便dd一个file就模拟了一个raw格式的镜像。由于裸的彻底,性能上来说的话还是不错的。目前来看,KVM和XEN默认的格式好像还是这个格式。因为其原始,有很多原生的特性,例如直接挂载也是一件简单的事情。
裸的好处还有就是简单,支持转换成其它格式的虚拟机镜像对裸露的它来说还是很简单的(如果其它格式需要转换,有时候还是需要它做为中间格式),空间使用来看,这个很像磁盘,使用多少就是多少(du -h看到的大小就是使用大小),但如果你要把整块磁盘都拿走的话得全盘拿了(copy镜像的时候),会比较消耗网络带宽和I/O。接下来还有个有趣的问题,如果那天你的硬盘用着用着不够用了,你咋办,在买一块盘。但raw格式的就比较犀利了,可以在原来的盘上追加空间:
dd if=/dev/zero of=zeros.raw bs=1024k count=4096(先创建4G的空间)
cat foresight.img zeros.raw > new-foresight.img(追加到原有的镜像之后)
当然,好东西是吹出来的,谁用谁知道,还是有挺多问题的。由于原生的裸格式,不支持snapshot也是很正常的。传说有朋友用版本管理软件对raw格式的文件做版本管理从而达到snapshot的能力,估计可行,但没试过,这里也不妄加评论。但如果你使用LVM的裸设备,那就另当别论。说到LVM还是十分的犀利的,当年用LVM做虚拟机的镜像,那性能杠杠的。而且现在好多兄弟用虚拟化都采用LVM来做的。在LVM上做了很多的优化,国外听说也有朋友在LVM增量备份方面做了很多的工作。目前来LVM的snapshot、性能、可扩展性方面都还是有相当的效果的。目前来看的话,备份的话也问题不大。就是在虚拟机迁移方面还是有很大的限制。但目前虚拟化的现状来看,真正需要热迁移的情况目前需求还不是是否的强烈。虽然使用LVM做虚拟机镜像的相关公开资料比较少,但目前来看牺牲一点灵活性,换取性能和便于管理还是不错的选择。

对于LVM相关的特性及使用可以参考如下链接:

http://www.ibm.com/developerworks/linux/library/l-lvm2/index.html

cow
copy-on-write format, supported for historical reasons only and not available to QEMU on Windows
曾经qemu的写时拷贝的镜像格式,目前由于历史遗留原因不支持窗口模式。从某种意义上来说是个弃婴,还没得它成熟就死在腹中,后来被qcow格式所取代。

qcow
the old QEMU copy-on-write format, supported for historical reasons and superseded by qcow2

一代的qemu的cow格式,刚刚出现的时候有比较好的特性,但其性能和raw格式对比还是有很大的差距,目前已经被新版本的qcow2取代。其性能可以查看如下链接:
http://www.linux-kvm.org/page/Qcow2

qcow2
QEMU copy-on-write format with a range of special features, including the ability to take multiple snapshots, smaller images on filesystems that don’t support sparse files, optional AES encryption, and optional zlib compression
现在比较主流的一种虚拟化镜像格式,经过一代的优化,目前qcow2的性能上接近raw裸格式的性能,这个也算是redhat的官方渠道了,哈哈,希望有朋友能拍他们砖:

https://fedoraproject.org/wiki/Features/KVM_qcow2_Performance

对于qcow2的格式,几点还是比较突出的,qcow2的snapshot,可以在镜像上做N多个快照:

  • 更小的存储空间,即使是不支持holes的文件系统也可以(这下du -h和ls -lh看到的就一样了)
  • Copy-on-write support, where the image only represents changes made to an underlying disk image(这个特性SUN ZFS表现的淋漓尽致)
  • 支持多个snapshot,对历史snapshot进行管理
  • 支持zlib的磁盘压缩
  • 支持AES的加密

vmdk 
VMware 3 & 4, or 6 image format, for exchanging images with that product
VMware的格式,这个格式说的蛋疼一点就有点牛X,原本VMware就是做虚拟化起家,自己做了一个集群的VMDK的pool,做了自己的虚拟机镜像格式。又拉着一些公司搞了一个OVF的统一封包。从性能和功能上来说,vmdk应该算最出色的,由于vmdk结合了VMware的很多能力,目前来看,KVM和XEN使用这种格式的情况不是太多。但就VMware的Esxi来看,它的稳定性和各方面的能力还是可圈可点。

vdi
VirtualBox 1.1 compatible image format, for exchanging images with VirtualBox.
SUN收购了VirtualBox,Oracle又收购了SUN,这么说呢,vdi也算虚拟化这方面的一朵奇葩,可惜的是入主的两家公司。SUN太专注于技术(可以说是IT技术最前端也不为过),Oracle又是开源杀手(mysql的没落)。单纯从能力上来说vdi在VirtualBox上的表现还是不错的。也是不错的workstation级别的产品。

说了这么多虚拟机镜像格式,这么多虚拟化,做云计算的伤不起呀,得为长期发展考虑,也有朋友对镜像的转换做了很多事情,简单看看几种镜像的转化:

VMDK–>qcow2:

kevin@kevin:~# qemu-img convert -f vmdk -O qcow2 SLES11SP1-single.vmdk SLES11SP1-single.img

http://www.ibm.com/developerworks/cn/linux/l-cn-mgrtvm3/index.html

qcow2–>raw:

kevin@kevin:~$ qemu-img convert -O qcow2 image-raw.raw image-raw-converted.qcow

转载自:http://www.prajnagarden.com/?p=248 
posted @ 2012-10-11 15:43 David1228 阅读(495) | 评论 (0)编辑 收藏
通过源码包安装、配置Mysql详细步骤:

1、上传mysql-5.5.8-linux2.6-x86_64.tar.gzWeb服务器的/usr/local/目录下

2、解压并重命名

# cd /usr/local

# tar –xvzf mysql-5.5.8-linux2.6-x86_64.tar.gz

# mv mysql-5.5.8-linux2.6-x86_64 mysql

3、配置/etc/my.cnf

1)安装操作系统时如果安装了MySql就会生成/etc/my.cnf,而系统自带的MySql版本较低,所以替换已有的/etc/my.cnf,替换之前可以备份my.cnf

#mv /etc/my.cnf  /etc/my.cnf_bak

# cp /usr/local/mysql/support-files/my-medium.cnf /etc/my.cnf

2)编辑/etc/my.cnf,配置IP连接,在mysqld中加入下边的红色字体

#vi /etc/my.cnf

[mysqld]

port            = 3306

socket          = /tmp/mysql.sock

skip-name-resolve

skip-external-locking

3)保存,退出。

4、添加mysql用户和用户组

如果系统已经安装了mysql,则在添加mysql用户和用户组的时候会提示mysql用户(或用户组)已经存在,这种提示是正常的。

# groupadd mysql

# useradd -g mysql mysql

5、修改mysql目录权限

1)设定root用户可以访问

# chown -R root /usr/local/mysql

2)设定mysql组和mysql用户能访问/usr/local/mysql/usr/local/mysql/data

# chgrp -R mysql /usr/local/mysql

#chown -R mysql /usr/local/mysql/data

6、创建mysql系统数据库

# cd /usr/local/mysql

#./scripts/mysql_install_db --user=mysql&

7、使用mysql用户启动mysqld

#/usr/local/mysql/bin/mysqld_safe  -user=mysql&

8、设定MySqlroot用户的密码

假设root用户的密码为123456,根据实际环境自行设定

#/usr/local/mysql/bin/mysqladmin -u root password 123456

9、使用root用户登录MySql

根据步骤8设定的用户密码登录mysql

# cd /usr/local/mysql/bin

#./mysql -u root -p     

Enter password:

10、开启mysql远程访问

1)赋予root用户远程访问权限

# grant all privileges on *.* to root @"%" identified by "123456";

#flush privileges;

2)参数说明

a)   grant all privileges:赋予所有权限,all可以替换为相关操作;

b)   *.*:说明数据库和表名,*代表所有;

c)   root:说明是给root用户设定权限,可以替换为其他用户;

d)   %:这里是Host名称,允许所有的就用%;

e)   123456:是root用户的密码;

f)   flush privileges:是把新赋权限表刷新加载到内存,可以理解为即时生效。

11、配置MySql自动启动

编辑/etc/rc.d/rc.local文件,在文件最底端加入启动语句

# vi /etc/rc.d/rc.local

……

/usr/local/mysql/bin/mysqld_safe -user=mysql&

通过rpm包安装、配置及卸载mysql的详细过程.

  以MySQL-server-4.0.14-0.i386.rpm为例,放在/data目录下

  cd /data

  rpm -ivh MySQL-server-4.0.14-0.i386.rpm

  安装完成后在/usr/share/mysql目录中会有一个mysql的启动脚本mysql.server及示例配置文件等(如my-huge.cnf、my-large.cnf、my-medium.cnf)

  拷贝一个示例配置文件作为mysql的配置文件:

  cp /usr/share/mysql/my-medium.cnf /etc/my.cnf

  rpm包安装完后自动将mysql安装成系统服务,所以可以使用下面命令启动、停止mysql

  启动mysql

  /etc/init.d/mysql start 或 service mysql start

  停止mysql

  /etc/init.d/mysql stop 或 service mysql stop

  到此,mysql服务就安装配置完成。

  安装mysql客户端

  rpm -ivh MySQL-client-4.0.14-0.i386.rpm

  mysql安装好后目录结构如下:

  工具程序在/usr/bin目录中---ls /usr/bin/mysql*

  服务器程序/usr/sbin/mysqld

  数据目录/var/lib/mysql

  默认情况下mysql将错误日志文件、二进制日志文件及进程文件写在/var/lib/mysql目录中,如localhost.err、localhost.pid、localhost-bin.001等

  要改变这些情况可以修改/etc/my.cnf文件

  如将日志文件写在/var/log目录中,可以在my.cnf文件中加入下面两行:

  [mysqld_safe]

  err-log = /var/log/mysqld.log

  有个实用程序/usr/bin/mysql_install_db,该程序可以用来初始化 mysql数据库,即创建/var/log/mysql目录,及创建mysql数据库(mysql授权表等信息)及test数据库(空库),如果不小心删 除了/var/log/mysql目录可以通过该程序来初始化.

  卸载mysql

  rpm -qa|grep -i mysql

  rpm -ev MySQL-server-4.0.14-0 MySQL-client-4.0.14-0

  卸载后/var/lib/mysql中的数据及/etc/my.cnf不会删除,如果确定没用后就手工删除

  rm -f /etc/my.cnf

  rm -rf /var/lib/mysql

posted @ 2012-10-11 15:21 David1228 阅读(209) | 评论 (0)编辑 收藏

一、命令行方式

关闭要调整的虚拟机,编辑虚拟机配置文件

#virsh edit 'your vm name'

找到配置文件中的以下字段:

<graphics type='vnc' port='-1'/>

加入键盘的语言布局后如下:

<graphics type='vnc' port='-1' keymap='en-us'/>

保存退出后,重新载入虚拟机配置文件

#virsh create /etc/libvirt/qemu/'your vm name'.xml

如果要避免这种情况,在使用virt-install安装的时候,就加入键盘布局的字段

--keymap=en-us 

二、virt-manager方式

在虚拟关闭的状态下,通过virt-manager界面选中相应的虚拟机:

open-->Details-->Display VNC-->keymap-->en-us

保存后再启动虚拟机就可以了
转载自:http://cncto.blog.51cto.com/blog/235831/886946

posted @ 2012-08-06 12:10 David1228 阅读(2824) | 评论 (0)编辑 收藏

【简介】

Python(蟒蛇)是一种动态解释型的编程语言。Python可以在Windows、UNIX、MAC等多种操作系统上使用,也可以在Java、.NET开发平台上使用。

python logo

python logo

 

【特点】

1 Python使用C语言开发,但是Python不再有C语言中的指针等复杂的数据类型。

2 Python具有很强的面向对象特性,而且简化了面向对象的实现。它消除了保护类型、抽象类、接口等面向对象的元素。

3 Python代码块使用空格或制表符缩进的方式分隔代码。

4 Python仅有31个保留字,而且没有分号、begin、end等标记。

5 Python是强类型语言,变量创建后会对应一种数据类型,出现在统一表达式中的不同类型的变量需要做类型转换。

python_book

python book

【搭建开发环境】

1 可以到www.python.org下载安装包,然后通过configure、make、make install进行安装。

2 也可以到www.activestate.com去下载ActivePython组件包。(ActivePython是对Python核心和常用模块的二进制包装,它是ActiveState公司发布的Python开发环境。ActivePython使得Python的安装更加容易,并且可以应用在各种操作系统上。ActivePython包含了一些常用的Python扩展,以及Windows环境的编程接口)。对ActivePython来说,如果你是windows用户,下载msi包安装即可;如果你是Unix用户,下载tar.gz包直接解压即可。

3 Python的IDE,包括PythonWin、Eclipse+PyDev插件、Komodo、EditPlus

【版本】

python2与python3是目前主要的两个版本。

如下两种情况下,建议使用python2:

1 你无法完全控制你即将部署的环境时;

2 你需要使用一些特定的第三方包或扩展时;

python3是官方推荐的且是未来全力支持的版本,目前很多功能提升仅在python3版本上进行。

【hello world】

1 创建hello.py

2 编写程序:

  1. if __name__ == '__main__':  
  2. print "hello word" 

3 运行程序:

  1. python ./hello.py 

【注释】

1 无论是行注释还是段注释,均以#加一个空格来注释。

2 如果需要在代码中使用中文注释,必须在python文件的最前面加上如下注释说明:

  1. # -* - coding: UTF-8 -* - 

3 如下注释用于指定解释器

  1. #! /usr/bin/python 

【文件类型】

1 Python的文件类型分为3种,即源代码、字节代码和优化代码。这些都可以直接运行,不需要进行编译或连接。

2 源代码以.py为扩展名,由python来负责解释;

3 源文件经过编译后生成扩展名为.pyc的文件,即编译过的字节文件。这种文件不能使用文本编辑器修改。pyc文件是和平台无关的,可以在大部分操作系统上运行。如下语句可以用来产生pyc文件:

  1. import py_compile  
  2. py_compile.compile(‘hello.py’) 

4 经过优化的源文件会以.pyo为后缀,即优化代码。它也不能直接用文本编辑器修改,如下命令可用来生成pyo文件:

  1. python -O -m py_complie hello.py 

【变量】

1 python中的变量不需要声明,变量的赋值操作即使变量声明和定义的过程。

2 python中一次新的赋值,将创建一个新的变量。即使变量的名称相同,变量的标识并不相同。用id()函数可以获取变量标识:

  1. x = 1 
  2. print id(x)  
  3. x = 2 
  4. print id(x) 

3 如果变量没有赋值,则python认为该变量不存在

4 在函数之外定义的变量都可以称为全局变量。全局变量可以被文件内部的任何函数和外部文件访问。

5 全局变量建议在文件的开头定义。

6 也可以把全局变量放到一个专门的文件中,然后通过import来引用:

gl.py文件中内容如下:

  1. _a = 1 
  2. _b = 2 

use_global.py中引用全局变量:

  1. import gl  
  2. def fun():  
  3. print gl._a  
  4. print gl._b  
  5. fun() 

【常量】

python中没有提供定义常量的保留字。可以自己定义一个常量类来实现常量的功能。

  1. class _const:  
  2. class ConstError(TypeError): pass 
  3. def __setattr__(self,name,vlaue):  
  4. if self.__dict__.has_key(name):  
  5. raise self.ConstError, “Can’t rebind const(%s)”%name  
  6. self.__dict__[name]=value  
  7. import sys  
  8. sys.modules[__name__]=_const() 

【数据类型】

1 python的数字类型分为整型、长整型、浮点型、布尔型、复数类型。

2 python没有字符类型

3 python内部没有普通类型,任何类型都是对象。

4 如果需要查看变量的类型,可以使用type类,该类可以返回变量的类型或创建一个新的类型。

5 python有3种表示字符串类型的方式,即单引号、双引号、三引号。单引号和双引号的作用是相同的。python程序员更喜欢用单引号,C/Java程序员则习惯使用双引号表示字符串。三引号中可以输入单引号、双引号或换行等字符。

【运算符和表达式】

1 python不支持自增运算符和自减运算符。例如i++/i–是错误的,但i+=1是可以的。

2 1/2在python2.5之前会等于0.5,在python2.5之后会等于0。

3 不等于为!=或<>

4 等于用==表示

5 逻辑表达式中and表示逻辑与,or表示逻辑或,not表示逻辑非

【控制语句】

1 条件语句:

  1. if (表达式) :  
  2. 语句1  
  3. else :  
  4. 语句2 

2 条件语句:
 

  1. if (表达式) :  
  2. 语句1  
  3. elif (表达式) :  
  4. 语句2  
  5. …  
  6. elif (表达式) :  
  7. 语句n  
  8. else :  
  9. 语句m 

3 条件嵌套:

  1. if (表达式1) :  
  2. if (表达式2) :  
  3. 语句1  
  4. elif (表达式3) :  
  5. 语句2  
  6. …  
  7. else:  
  8. 语句3  
  9. elif (表达式n) :  
  10. …  
  11. else :  
  12. … 

4 python本身没有switch语句。

5 循环语句:

  1. while(表达式) :  
  2. …  
  3. else :  
  4. … 

6 循环语句:

  1. for 变量 in 集合 :  
  2. …  
  3. else :  
  4. … 

7 python不支持类似c的for(i=0;i<5;i++)这样的循环语句,但可以借助range模拟:

  1. for x in range(0,5,2):  
  2. print x 

【数组相关】

1 元组(tuple):python中一种内置的数据结构。元组由不同的元素组成,每个元素可以存储不同类型的数据,如字符串、数字甚至元素。元组是写保护的,即元组创建之后不能再修改。元组往往代表一行数据,而元组中的元素代表不同的数据项。可以把元组看做不可修改的数组。创建元组示例如下:

  1. tuple_name=(“apple”,”banana”,”grape”,”orange”) 

2 列表(list):列表和元组相似,也由一组元素组成,列表可以实现添加、删除和查找操作,元素的值可以被修改。列表是传统意义上的数组。列表创建示例如下:

  1. list=[“apple”,”banana”,”grage”,”orange”] 

可以使用append方法来在尾部追加元素,使用remove来删除元素。

3 字典(dictionary):由键-值对组成的集合,字典中的值通过键来引用。键和值之间用冒号隔开,键-值对之间用逗号隔开,并且被包含在一对花括号中。创建示例如下:

  1. dict={“a”:”apple”, “b”:”banana”, “g”:”grage”, “o”:”orange”} 

4 序列:序列是具有索引和切片能力的集合。元组、列表和字符串都属于序列。

【函数相关】

1 python程序由包(package)、模块(module)和函数组成。包是由一系列模块组成的集合。模块是处理某一类问题的函数和类的集合。

2 包就是一个完成特定任务的工具箱。

3 包必须含有一个__init__.py文件,它用于标识当前文件夹是一个包。

4 python的程序是由一个个模块组成的。模块把一组相关的函数或代码组织到一个文件中,一个文件即是一个模块。模块由代码、函数和类组成。导入模块使用import语句。

5 包的作用是实现程序的重用。

6 函数是一段可以重复多次调用的代码,函数定义示例如下:

  1. def arithmetic(x,y,operator):  
  2. result={  
  3. “+”:x+y,  
  4. “-“:x-y,  
  5. “*”:x*y,  
  6. “/”:x/y  

7 函数返回值可以用return来控制。

【字符串相关】

1 格式化输出:

  1. format=”%s%d” % (str1,num)  
  2. print format 

2 用+进行字符串的合并:

  1. str1=”hello”  
  2. str2=”world”  
  3. result=str1+str2 

3 字符串截取可以通过索引/切片,也可以通过split函数。

4 通过切片截取字符串:

  1. word=”world”  
  2. print word[0:3] 

5 python使用==和!=来进行字符串比较。如果比较的两个变量的类型不相同,那么结果必然为不同。

【文件处理】

1 简单处理文件:

  1. context=”hello,world”  
  2. f=file(“hello.txt”,’w’)  
  3. f.write(context);  
  4. f.close() 

2 读取文件可以使用readline()函数、readlines()函数和read函数。

3 写入文件可以使用write()、writelines()函数

【对象和类】

1 python用class保留字来定义一个类,类名的首字符要大写。当程序员需要创建的类型不能用简单类型来表示时,就需要定义类,然后利用定义的类创建对象。定义类示例:

  1. class Fruit:  
  2. def grow(self):  
  3. print “Fruit grow” 

2 当一个对象被创建后,包含了三方面的特性,即对象的句柄、属性和方法。创建对象的方法:

  1. fruit = Fruit()  
  2. fruit.grow() 

3 python没有保护类型的修饰符

4 类的方法也分为公有方法和私有方法。私有函数不能被该类之外的函数调用,私有的方法也不能被外部的类或函数调用。

5 python使用函数”staticmethod()“或”@ staticmethod“指令的方法把普通的函数转换为静态方法。静态方法相当于全局函数。

6 python的构造函数名为__init__,析构函数名为__del__

7 继承的使用方法:

  1. class Apple(Fruit):  
  2. def … 

【连接mysql】

1 用MySQLdb模块操作MySQL数据库非常方便。示例代码如下:

  1. import os, sys  
  2. import MySQLdb  
  3. try:  
  4. conn MySQLdb.connect(host=’localhost’,user=’root’,passwd=’’,db=’address’  
  5. except Exception,e:  
  6. print e  
  7. sys.exit()  
  8. cursor=conn.cursor()  
  9. sql=’insert into address(name, address) values(%s, %s)’  
  10. value=((“zhangsan”,”haidian”),(“lisi”,”haidian”))  
  11. try 
  12. cursor.executemany(sql,values)  
  13. except Exception, e:  
  14. print e  
  15. sql=”select * from address”  
  16. cursor.execute(sql)  
  17. data=cursor.fetchall()  
  18. if data  
  19. for x in data:  
  20. print x[0],x[1]  
  21. cursor.close()  
  22. conn.close() 

谢谢!

原文链接: http://roclinux.cn/?p=2338


 

posted @ 2012-07-10 09:35 David1228 阅读(200) | 评论 (0)编辑 收藏
一、问题描述
    根据CentOS-6.0-x86_64-bin-DVD1.iso制作虚拟机镜像后,使用该镜像创建的虚

拟机都是网卡eth1,虽然能设置上ip但是虚拟网关并不能设置成功。
    并且随着镜像->虚拟机->镜像->虚拟机类似流程迭代,网卡ethx会递增。总结一

句话:就是eth0不起作用。
    
二、解决问题如下:

    1、在grub里增加biosdevname=0的启动参数,形如

    kernel /vmlinuz-2.6.32-131.21.1.el6.i686 ro root=/dev/mapper/vg_test-

lv_root rd_LVM_LV=vg_test/lv_root rd_LVM_LV=vg_test/lv_swap rd_NO_LUKS rd_NO_MD 

rd_NO_DM LANG=en_US.UTF-8 SYSFONT=latar
    cyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=us crashkernel=auto rhgb quiet 

biosdevname=0

    2、删除udev的配置文件rm -f /etc/udev/rules.d/70-persistent-net.rules。

(我的做法比较彪悍,直接把rules.d干掉了。)

    第3、4、5步是针对单个主机或者虚拟机而言的,我们保证镜像中的eth0网卡配置

文件存在,名字为ifcfg-eth0文件中DEVICE=eth0。
    
    3、把网卡配置文件改名

        mv ifcfg-em1 ifcfg-eth0

    4、把网卡配置文件内容修正,把em1的全部改成eth0

        perl -p -i -e ‘s/em1/eth0/g’ ifcfg-eth0 

    5、重启系统即可

    6、配置ssh
        6.1:/etc/ssh/sshd_config   配置文件中修改或加入UseDNS=no,将

#UseDNS=yes 改成:UseDNS=no
        6.2:/etc/ssh/sshd_config   配置文件中将#GSSAPIAuthentication 

no 的#号去掉,更改成GSSAPIAuthentication no
        6.3:/etc/ssh/sshd_config   配置文件中将PermitRootLogin no修改

为yes 
        6.4:   
        6.5:/etc/ssh/sshd_config   配置文件中将PasswordAuthentication 

no修改为yes就可以了
        6.6:/etc/nsswitch.conf     配置文件中,将hosts:files dns  改

成:hosts:files
        6.7:/etc/init.d/sshd restart         重启sshd进程使配置生效
        
        其中6.1、6.2、6.6都是处于性能方面考虑
    
    7、镜像中存在bcec提供的setIp、rc.local等脚本。
    
    经过在39.4环境测试,操作过程从原始镜像 -> 新虚拟机 -> 制作镜像镜像 -> 

新镜像虚拟机,网卡都没有问题,都是eth0。

 Centos6.0制作镜像网卡问题总结-zhgp 
posted @ 2012-06-15 11:07 David1228 阅读(832) | 评论 (0)编辑 收藏

禁用 SSH 远程主机的公钥检查

SSH 公钥检查是一个重要的安全机制,可以防范中间人劫持等黑客攻击。但是在特定情况下,严格的 SSH 公钥检查会破坏一些依赖 SSH 协议的自动化任务,就需要一种手段能够绕过 SSH 的公钥检查。

首先看看什么是 SSH 公钥检查

SSH 连接远程主机时,会检查主机的公钥。如果是第一次该主机,会显示该主机的公钥摘要,提示用户是否信任该主机:
The authenticity of host '192.168.0.110 (192.168.0.110)' can't be established. RSA key fingerprint is a3:ca:ad:95:a1:45:d2:57:3a:e9:e7:75:a8:4c:1f:9f. Are you sure you want to continue connecting (yes/no)? 
当选择接受,就会将该主机的公钥追加到文件 ~/.ssh/known_hosts 中。当再次连接该主机时,就不会再提示该问题了。 如果因为某种原因(服务器系统重装,服务器间IP地址交换,DHCP,虚拟机重建,中间人劫持),该IP地址的公钥改变了,当使用 SSH 连接的时候,会报错:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that the RSA host key has just been changed. The fingerprint for the RSA key sent by the remote host is e9:0c:36:89:7f:3c:07:71:09:5a:9f:28:8c:44:e9:05. Please contact your system administrator. Add correct host key in /home/jiangxin/.ssh/known_hosts to get rid of this message. Offending key in /home/jiangxin/.ssh/known_hosts:81 RSA host key for 192.168.0.110 has changed and you have requested strict checking. Host key verification failed. 
上面的警告信息说的是:
  • 服务器公钥已经改变,新的公钥的摘要是:e9:0c:36:89:7f:3c:07:71:09:5a:9f:28:8c:44:e9:05.
  • 该服务器原来的公钥记录在文件 ~/.ssh/known_hosts 中第 81 行。
如果确认不是中间人劫持,需要连接到该服务器,怎么办呢?最简单的就是用 vi 打开 ~/.ssh/known_hosts 文件,定位到 81 行,将该行删除。之后就可以使用 ssh 连接了。

如何让连接新主机时,不进行公钥确认?

在首次连接服务器时,会弹出公钥确认的提示。这会导致某些自动化任务,由于初次连接服务器而导致自动化任务中断。或者由于  ~/.ssh/known_hosts 文件内容清空,导致自动化任务中断。 SSH 客户端的 StrictHostKeyChecking 配置指令,可以实现当第一次连接服务器时,自动接受新的公钥。只需要修改 /etc/ssh/ssh_config 文件,包含下列语句:
Host *  StrictHostKeyChecking no 
或者在 ssh 命令行中用 -o 参数
$ ssh  -o StrictHostKeyChecking=no  192.168.0.110

如何防止远程主机公钥改变导致 SSH 连接失败

当确认中间人劫持攻击风险比较小的情况下,才可以使用下面的方法,禁用 SSH 远程主机的公钥检查。 SSH 客户端提供一个 UserKnownHostsFile 配置,允许指定不同的 known_hosts 文件。那么将 known_hosts 指向不同的文件,不就不会造成公钥冲突导致的中断了么?
$ ssh -o UserKnownHostsFile=/dev/null 192.168.0.110 The authenticity of host '192.168.0.110 (192.168.0.110)' can't be established. RSA key fingerprint is e9:0c:36:89:7f:3c:07:71:09:5a:9f:28:8c:44:e9:05. Are you sure you want to continue connecting (yes/no)? 
看,提示信息由公钥改变中断警告,变成了首次连接的提示。 和之前提到的 StrictHostKeyChecking 配置配合使用,则不再有任何警告出现了:
$ ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null 192.168.0.110 Warning: Permanently added '192.168.0.110' (RSA) to the list of known hosts. jiangxin@192.168.0.110's password: 
如果设置了无口令 SSH 登录(即通过客户端公钥认证),就可以直接连接到远程主机。这是基于 SSH 协议的自动化任务常用的手段。

转自: http://www.worldhello.net/2010/04/08/1026.html 
可参考资料:http://www.symantec.com/connect/articles/ssh-host-key-protection
posted @ 2012-06-15 09:30 David1228 阅读(269) | 评论 (0)编辑 收藏

在Set中有一个排序的集合SortedSet,用来保存按照自然顺序排列的对象。Queue中同样引入了一个支持排序的FIFO模型。

并发队列与Queue简介 中介绍了,PriorityQueue和PriorityBlockingQueue就是支持排序的Queue。显然一个支持阻塞的排序Queue要比一 个非线程安全的Queue实现起来要复杂的多,因此下面只介绍PriorityBlockingQueue,至于PriorityQueue只需要去掉 Blocking功能就基本相同了。

 转自: http://www.blogjava.net/xylz/archive/2010/07/30/327582.htm

排序的BlockingQueue — PriorityBlockingQueue

先简单介绍下PriorityQueue,因为PriorityBlockingQueue内部就是通过PriorityQueue适配实现的,只不过通过锁进行同步和阻塞而已。

PriorityQueue是一个数组实现的,是一个二叉树的实现,这个二叉树的任意一个节点都比其子节点要小,这样顶点就是最小的节点。每一个元 素或者节点要么本身是可比较的(Comparable),或者队列本身带有一个比较器(Comparator<? super E>),所有元素就是靠比较自身的大小来确定顺序的。而数组中顶点就是数组的第0个元素,因此出队列的话总是取第0个元素。对于第0个元素,其子节 点是第1个元素和第2个元素,对于第1个元素,其子元素又是第3/4个元素,以此类推,第i个元素的父节点就是(i-1)/2。这样任意一个元素加入队列 就从其父节点(i-1)/2开始比较,一旦新节点比父节点小就交换两个节点,然后继续比较新节点与其新的父节点。知道所有节点都是按照父节点一定比子节点 小的顺序排列。这是一个有点复杂的算法,此处不再讨论更多的细节。不管是删除还是查找,我们只需要了解的顶点(索引为0的元素)总是最小的。

特别需要说明的是PriorityQueue是一个无界的队列,也就是说一旦元素的个数达到了数组的大小,那么就将数组扩大50%,这样这个数组就是无穷大的。当然了如果达到了整数的最大值就会得到一个OutOfMemoryError,这个是由逻辑保证的。

 

对于PriorityBlockingQueue而言,由于是无界的,因此就只有非空的信号,也就是说只有take()才能阻塞,put是永远不会阻塞(除非达到Integer.MAX_VALUE直到抛出一个OutOfMemoryError异常)。

只有take()操作的时候才可能因为队列为空而挂起。同时其它需要操作队列变化和大小的只需要使用独占锁ReentrantLock就可以了,非常方便。需要说明的是PriorityBlockingQueue采用了一个公平的锁。

 

总的来说PriorityBlockingQueue 不是一个FIFO的队列,而是一个有序的队列,这个队列总是取“自然顺序”最小的对象,同时又是一个只能出队列阻塞的BlockingQueue,对于入队列却不是阻塞的。所有操作都是线程安全的。

 

直接交换的BlockingQueue — SynchronousQueue

 

这是一个很有意思的阻塞队列,其中每个插入操作必须等待另一个线程的移除操作,同样任何一个移除操作都等待另一个线程的插入操作。因此此队列内部其 实没有任何一个元素,或者说容量是0,严格说并不是一种容器。由于队列没有容量,因此不能调用peek操作,因为只有移除元素时才有元素。

一个没有容量的并发队列有什么用了?或者说存在的意义是什么?

SynchronousQueue 的实现非常复杂,当然了如果真要去分析还是能够得到一些经验的,但是前面分析了过多的结构后,发现越来越陷于数据结构与算法里面了。我的初衷是通过研究并 发实现的原理来更好的利用并发来最大限度的利用可用资源。所以在后面的章节中尽可能的少研究数据结构和算法,但是为了弄清楚里面的原理,必不可免的会涉及 到一些这方面的知识,希望后面能够适可而止。

再回到话题。SynchronousQueue 内部没有容量,但是由于一个插入操作总是对应一个移除操作,反过来同样需要满足。那么一个元素就不会再SynchronousQueue 里面长时间停留,一旦有了插入线程和移除线程,元素很快就从插入线程移交给移除线程。也就是说这更像是一种信道(管道),资源从一个方向快速传递到另一方 向。

需要特别说明的是,尽管元素在SynchronousQueue 内部不会“停留”,但是并不意味之SynchronousQueue 内部没有队列。实际上SynchronousQueue 维护者线程队列,也就是插入线程或者移除线程在不同时存在的时候就会有线程队列。既然有队列,同样就有公平性和非公平性特性,公平性保证正在等待的插入线 程或者移除线程以FIFO的顺序传递资源。

显然这是一种快速传递元素的方式,也就是说在这种情况下元素总是以最快的方式从插入着(生产者)传递给移除着(消费者),这在多任务队列中是最快处理任务的方式。在线程池的相关章节中还会更多的提到此特性。

 

事实上在《并发队列与Queue简介》 中介绍了还有一种BlockingQueue的实现DelayQueue,它描述的是一种延时队列。这个队列的特性是,队列中的元素都要延迟时间(超时时 间),只有一个元素达到了延时时间才能出队列,也就是说每次从队列中获取的元素总是最先到达延时的元素。这种队列的场景就是计划任务。比如以前要完成计划 任务,很有可能是使用Timer/TimerTask,这是一种循环检测的方式,也就是在循环里面遍历所有元素总是检测元素是否满足条件,一旦满足条件就 执行相关任务。显然这中方式浪费了很多的检测工作,因为大多数时间总是在进行无谓的检测。而DelayQueue 却能避免这种无谓的检测。在线程池的计划任务部分还有更加详细的讨论此队列实现。

 

下面就对常见的BlockingQueue进行小节下,这里不包括双向的队列,尽管ConcurrentLinkedQueue不是可阻塞的Queue,但是这里还是将其放在一起进行对比。

 

并发队列比较

如果不需要阻塞队列,优先选择ConcurrentLinkedQueue;如果需要阻塞队列,队列大小固定优先选择 ArrayBlockingQueue,队列大小不固定优先选择LinkedBlockingQueue;如果需要对队列进行排序,选择 PriorityBlockingQueue;如果需要一个快速交换的队列,选择SynchronousQueue;如果需要对队列中的元素进行延时操 作,则选择DelayQueue。

posted @ 2012-03-19 14:45 David1228 阅读(306) | 评论 (0)编辑 收藏

2012-01-08 18:14:40     我来说两句 
收藏
以前从来没有使用过ruby,这两天刚好要使用GitHub上的离线wiki系统gollum,所以要在偶的ubuntu下安装ruby和ruby-gems。其中遇到一些问题:
 
 
 
如果使用apt-get install ruby 和apt-get install rubygems1.8
 
当使用gem install 命令时报以下错误:
 
 
 
ERROR: While executing gem ... (TypeError) instance of Date needs to have method `marshal_load
 
 
 
可能是Ubuntu环境的原因,那么就改用rvm安装,参考了http://beginrescueend.com/rvm/install/
 
若以非root模式安装:
 
 
 
bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )
 
 
 
 
 添加rvm scripts路径变量到bash:
 
 
 
     echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # Load RVM function' >> ~/.bash_profile
 
  
 
 让新的bash生效:
 
 
 
     source ~/.bash_profile
 
 
 
安装ruby1.9.2:
 
    rvm install 1.9.2
 
 
 
让系统默认使用1.92:
 
    rvm use 1.9.2 --default
 
 
 
 
 
 
检查安装是否OK:
 
    ruby  -v
 
--------------------------------------------
 
接下来安装rubygems
 
先到官网下载安装包http://rubygems.org/pages/download
 
 
 
 
然后安装
 
ruby setup.rb
 
 
 
 
默认采用淘宝的Gem镜像站点
 
 
 
 
gem source http://ruby.taobao.org/
 
 
 
 
接下来就可以使用gem install xxx命令了,just enjoy it!
 
 
 
 
PS:如过使用gem install报错,可能是Ubuntu本身少一些依赖,比如我安装gollum时缺少依赖libxml2,libxslt,
 
缺少啥就install 啥:
 
 
 
apt-get install libxml2
 
apt-get install libxslt
 
转自:
http://www.2cto.com/os/201201/116337.html
posted @ 2012-03-14 10:08 David1228 阅读(832) | 评论 (0)编辑 收藏
 rpm --erase --allmatches --nodeps xmlrpc-c-devel-1.16.24-1206.1840.el5_7.4
posted @ 2012-02-14 17:31 David1228 阅读(316) | 评论 (0)编辑 收藏

<2012年2月>
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910

常用链接

留言簿(3)

随笔分类

随笔档案

文章档案

新闻分类

新闻档案

相册

收藏夹

Java

Linux知识相关

Spring相关

云计算/Linux/虚拟化技术/

友情博客

多线程并发编程

开源技术

持久层技术相关

搜索

  •  

积分与排名

  • 积分 - 310303
  • 排名 - 161

最新评论

阅读排行榜

评论排行榜