摘要:
阅读全文
posted @
2017-09-04 16:33 David1228 阅读(294) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2017-08-02 11:41 David1228 阅读(309) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2017-07-24 19:10 David1228 阅读(11369) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2017-07-19 18:10 David1228 阅读(3408) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2017-06-06 23:10 David1228 阅读(284) |
评论 (0) |
编辑 收藏
posted @
2017-06-06 23:09 David1228 阅读(238) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2017-05-30 19:26 David1228 阅读(3267) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2017-05-30 19:25 David1228 阅读(1244) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2016-12-22 23:01 David1228 阅读(4595) |
评论 (2) |
编辑 收藏
摘要:
阅读全文
posted @
2016-11-04 23:44 David1228 阅读(2283) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2016-07-28 17:57 David1228 阅读(393) |
评论 (0) |
编辑 收藏
摘要: JVM调优总结 + jstat 分析jstat -gccause pid 1 每格1毫秒输出结果jstat -gccause pid 2000 每格2秒输出结果不断的在屏幕打印出结果 S0 S1 E &n...
阅读全文
posted @
2016-01-03 23:26 David1228 阅读(2981) |
评论 (2) |
编辑 收藏
摘要:
阅读全文
posted @
2015-12-27 16:49 David1228 阅读(1081) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2015-10-31 12:37 David1228 阅读(660) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2015-10-30 20:20 David1228 阅读(2872) |
评论 (0) |
编辑 收藏
转载文章:
http://www.qixing318.com/article/by-lua-adhesive-nginx-ecological-environment.html
posted @
2015-09-08 13:22 David1228 阅读(506) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2015-09-08 09:34 David1228|
编辑 收藏
摘要:
阅读全文
posted @
2015-07-29 13:48 David1228 阅读(5544) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2014-12-03 23:56 David1228 阅读(28316) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2013-11-19 11:48 David1228 阅读(23718) |
评论 (1) |
编辑 收藏
摘要:
阅读全文
posted @
2013-11-18 18:01 David1228 阅读(2891) |
评论 (4) |
编辑 收藏
摘要:
阅读全文
posted @
2013-10-31 17:32 David1228 阅读(695) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2013-10-14 09:50 David1228 阅读(21735) |
评论 (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 end) as 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 阅读(16662) |
评论 (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 阅读(3751) |
评论 (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 阅读(2432) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2013-08-20 09:46 David1228 阅读(387) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2013-08-20 09:44 David1228 阅读(387) |
评论 (0) |
编辑 收藏
摘要:
阅读全文
posted @
2013-07-24 16:11 David1228 阅读(33392) |
评论 (0) |
编辑 收藏
摘要: 根据官方的说法,在ibatis3,也就是Mybatis3问世之前,Spring3的开发工作就已经完成了,所以Spring3中还是没有对Mybatis3的支持。因此由Mybatis社区自己开发了一个Mybatis-Spring用来满足Mybatis用户整合Spring的需求。下面就将通过Mybatis-Spring来整合Mybatis跟Spring的用法做一个简单的介绍。MapperFactoryB...
阅读全文
posted @
2013-07-10 18:07 David1228 阅读(21409) |
评论 (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文档):
- public class MyWebApplicationInitializer implements WebApplicationInitializer {
-
- @Override
- public void onStartup(ServletContext container) {
- ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
- registration.setLoadOnStartup(1);
- registration.addMapping("/example/*");
- }
-
- }
二 支持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
就可以了,如下代码所示:
- public
-
- class
-
- SugarSpringWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
-
- @Override
- protected Class<?>[] getRootConfigClasses() {
- return new Class[] { JavaConfig.class };
- }
-
- @Override
- protected Class<?>[] getServletConfigClasses() {
- return new Class[] { WebConfig.class };
- }
-
- @Override
- protected String[] getServletMappings() {
- return new String[] { "/" };
- }
-
- }
三功能更强大的
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
等的测试改进,下面是一个例子:
- public class SayHelloControllerIT extends AbstractTestNGSpringContextTests {
-
- private MockMvc mockMvc;
-
- @BeforeMethod
- public void setUp() {
-
- mockMvc = webAppContextSetup((WebApplicationContext) applicationContext).build();
- }
-
- @Test(dataProvider = "pathParameterAndExpectedModelValue")
- public void accessingSayhelloWithSubpathShouldForwardToSayHelloJspWithModelFilled(String path, String value) throws Exception {
-
- mockMvc.perform(get("/sayHello/Jo")).andExpect(view().name("sayHello")).andExpect(model().attribute("name", "Jo"));
- }
- }
本文的示例代码可以在:
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 阅读(2337) |
评论 (0) |
编辑 收藏
摘要: 本文转载自:http://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html场景问题 举个生活中常见的例子——组装电脑,我们在组装电脑的时候,通常需要选择一系列的配件,比如CPU、硬盘、内存、主板、电源、机箱等。为讨论使用简单点,只考虑选择CPU和主板的问题。 事实上,在选择CPU的时候,面临一系列的...
阅读全文
posted @
2013-07-04 17:07 David1228 阅读(392) |
评论 (0) |
编辑 收藏
shell中可能经常能看到:>/dev/null 2>&1 命令的结果可以通过%>的形式来定义输出分解这个组合:“>/dev/null 2>&1” 为五部分。1:> 代表重定向到哪里,例如:echo "123" > /home/123.txt2:/dev/null 代表空设备文件3:2> 表示stderr标准错误4:& 表示等同于的意思,2>&1,表示2的输出重定向等同于15: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 阅读(947) |
评论 (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。
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 阅读(1066) |
评论 (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 阅读(412) |
评论 (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 阅读(2758) |
评论 (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 阅读(2485) |
评论 (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 阅读(1752) |
评论 (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 阅读(748) |
评论 (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}&useUnicode=true&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}&useUnicode=true&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 阅读(10741) |
评论 (0) |
编辑 收藏
Deserializes JavaScript Object Notation (JSON) text to produce a JavaScript value.
JSON.parse(text [, reviver])
- 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.
A JavaScript value—an object or array.
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.
|
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; };
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.
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:
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 阅读(874) |
评论 (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 阅读(966) |
评论 (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 failedHit 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 阅读(6278) |
评论 (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 阅读(1480) |
评论 (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 阅读(444) |
评论 (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 阅读(2715) |
评论 (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 阅读(384) |
评论 (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 阅读(371) |
评论 (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 只监视日志变动并不存储日志,不过这个没关系,我们知道日志存储在哪个机器上。
posted @
2012-11-06 15:49 David1228 阅读(2179) |
评论 (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 阅读(323) |
评论 (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 阅读(627) |
评论 (0) |
编辑 收藏
通过源码包安装、配置Mysql详细步骤:1、上传mysql-5.5.8-linux2.6-x86_64.tar.gz到Web服务器的/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、设定MySql的root用户的密码
假设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 阅读(329) |
评论 (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 阅读(3103) |
评论 (0) |
编辑 收藏
【简介】
Python(蟒蛇)是一种动态解释型的编程语言。Python可以在Windows、UNIX、MAC等多种操作系统上使用,也可以在Java、.NET开发平台上使用。
python logo
【特点】
1 Python使用C语言开发,但是Python不再有C语言中的指针等复杂的数据类型。
2 Python具有很强的面向对象特性,而且简化了面向对象的实现。它消除了保护类型、抽象类、接口等面向对象的元素。
3 Python代码块使用空格或制表符缩进的方式分隔代码。
4 Python仅有31个保留字,而且没有分号、begin、end等标记。
5 Python是强类型语言,变量创建后会对应一种数据类型,出现在统一表达式中的不同类型的变量需要做类型转换。
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 编写程序:
- if __name__ == '__main__':
- print "hello word"
3 运行程序:
- python ./hello.py
【注释】
1 无论是行注释还是段注释,均以#加一个空格来注释。
2 如果需要在代码中使用中文注释,必须在python文件的最前面加上如下注释说明:
- # -* - coding: UTF-8 -* -
3 如下注释用于指定解释器
- #! /usr/bin/python
【文件类型】
1 Python的文件类型分为3种,即源代码、字节代码和优化代码。这些都可以直接运行,不需要进行编译或连接。
2 源代码以.py为扩展名,由python来负责解释;
3 源文件经过编译后生成扩展名为.pyc的文件,即编译过的字节文件。这种文件不能使用文本编辑器修改。pyc文件是和平台无关的,可以在大部分操作系统上运行。如下语句可以用来产生pyc文件:
- import py_compile
- py_compile.compile(‘hello.py’)
4 经过优化的源文件会以.pyo为后缀,即优化代码。它也不能直接用文本编辑器修改,如下命令可用来生成pyo文件:
- python -O -m py_complie hello.py
【变量】
1 python中的变量不需要声明,变量的赋值操作即使变量声明和定义的过程。
2 python中一次新的赋值,将创建一个新的变量。即使变量的名称相同,变量的标识并不相同。用id()函数可以获取变量标识:
- x = 1
- print id(x)
- x = 2
- print id(x)
3 如果变量没有赋值,则python认为该变量不存在
4 在函数之外定义的变量都可以称为全局变量。全局变量可以被文件内部的任何函数和外部文件访问。
5 全局变量建议在文件的开头定义。
6 也可以把全局变量放到一个专门的文件中,然后通过import来引用:
gl.py文件中内容如下:
- _a = 1
- _b = 2
use_global.py中引用全局变量:
- import gl
- def fun():
- print gl._a
- print gl._b
- fun()
【常量】
python中没有提供定义常量的保留字。可以自己定义一个常量类来实现常量的功能。
- class _const:
- class ConstError(TypeError): pass
- def __setattr__(self,name,vlaue):
- if self.__dict__.has_key(name):
- raise self.ConstError, “Can’t rebind const(%s)”%name
- self.__dict__[name]=value
- import sys
- 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 条件语句:
- if (表达式) :
- 语句1
- else :
- 语句2
2 条件语句:
- if (表达式) :
- 语句1
- elif (表达式) :
- 语句2
- …
- elif (表达式) :
- 语句n
- else :
- 语句m
3 条件嵌套:
- if (表达式1) :
- if (表达式2) :
- 语句1
- elif (表达式3) :
- 语句2
- …
- else:
- 语句3
- elif (表达式n) :
- …
- else :
- …
4 python本身没有switch语句。
5 循环语句:
- while(表达式) :
- …
- else :
- …
6 循环语句:
- for 变量 in 集合 :
- …
- else :
- …
7 python不支持类似c的for(i=0;i<5;i++)这样的循环语句,但可以借助range模拟:
- for x in range(0,5,2):
- print x
【数组相关】
1 元组(tuple):python中一种内置的数据结构。元组由不同的元素组成,每个元素可以存储不同类型的数据,如字符串、数字甚至元素。元组是写保护的,即元组创建之后不能再修改。元组往往代表一行数据,而元组中的元素代表不同的数据项。可以把元组看做不可修改的数组。创建元组示例如下:
- tuple_name=(“apple”,”banana”,”grape”,”orange”)
2 列表(list):列表和元组相似,也由一组元素组成,列表可以实现添加、删除和查找操作,元素的值可以被修改。列表是传统意义上的数组。列表创建示例如下:
- list=[“apple”,”banana”,”grage”,”orange”]
可以使用append方法来在尾部追加元素,使用remove来删除元素。
3 字典(dictionary):由键-值对组成的集合,字典中的值通过键来引用。键和值之间用冒号隔开,键-值对之间用逗号隔开,并且被包含在一对花括号中。创建示例如下:
- dict={“a”:”apple”, “b”:”banana”, “g”:”grage”, “o”:”orange”}
4 序列:序列是具有索引和切片能力的集合。元组、列表和字符串都属于序列。
【函数相关】
1 python程序由包(package)、模块(module)和函数组成。包是由一系列模块组成的集合。模块是处理某一类问题的函数和类的集合。
2 包就是一个完成特定任务的工具箱。
3 包必须含有一个__init__.py文件,它用于标识当前文件夹是一个包。
4 python的程序是由一个个模块组成的。模块把一组相关的函数或代码组织到一个文件中,一个文件即是一个模块。模块由代码、函数和类组成。导入模块使用import语句。
5 包的作用是实现程序的重用。
6 函数是一段可以重复多次调用的代码,函数定义示例如下:
- def arithmetic(x,y,operator):
- result={
- “+”:x+y,
- “-“:x-y,
- “*”:x*y,
- “/”:x/y
- }
7 函数返回值可以用return来控制。
【字符串相关】
1 格式化输出:
- format=”%s%d” % (str1,num)
- print format
2 用+进行字符串的合并:
- str1=”hello”
- str2=”world”
- result=str1+str2
3 字符串截取可以通过索引/切片,也可以通过split函数。
4 通过切片截取字符串:
- word=”world”
- print word[0:3]
5 python使用==和!=来进行字符串比较。如果比较的两个变量的类型不相同,那么结果必然为不同。
【文件处理】
1 简单处理文件:
- context=”hello,world”
- f=file(“hello.txt”,’w’)
- f.write(context);
- f.close()
2 读取文件可以使用readline()函数、readlines()函数和read函数。
3 写入文件可以使用write()、writelines()函数
【对象和类】
1 python用class保留字来定义一个类,类名的首字符要大写。当程序员需要创建的类型不能用简单类型来表示时,就需要定义类,然后利用定义的类创建对象。定义类示例:
- class Fruit:
- def grow(self):
- print “Fruit grow”
2 当一个对象被创建后,包含了三方面的特性,即对象的句柄、属性和方法。创建对象的方法:
- fruit = Fruit()
- fruit.grow()
3 python没有保护类型的修饰符
4 类的方法也分为公有方法和私有方法。私有函数不能被该类之外的函数调用,私有的方法也不能被外部的类或函数调用。
5 python使用函数”staticmethod()“或”@ staticmethod“指令的方法把普通的函数转换为静态方法。静态方法相当于全局函数。
6 python的构造函数名为__init__,析构函数名为__del__
7 继承的使用方法:
- class Apple(Fruit):
- def …
【连接mysql】
1 用MySQLdb模块操作MySQL数据库非常方便。示例代码如下:
- import os, sys
- import MySQLdb
- try:
- conn MySQLdb.connect(host=’localhost’,user=’root’,passwd=’’,db=’address’
- except Exception,e:
- print e
- sys.exit()
- cursor=conn.cursor()
- sql=’insert into address(name, address) values(%s, %s)’
- value=((“zhangsan”,”haidian”),(“lisi”,”haidian”))
- try
- cursor.executemany(sql,values)
- except Exception, e:
- print e
- sql=”select * from address”
- cursor.execute(sql)
- data=cursor.fetchall()
- if data
- for x in data:
- print x[0],x[1]
- cursor.close()
- conn.close()
谢谢!
posted @
2012-07-10 09:35 David1228 阅读(304) |
评论 (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 阅读(983) |
评论 (0) |
编辑 收藏
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 阅读(418) |
评论 (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 阅读(392) |
评论 (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 阅读(980) |
评论 (0) |
编辑 收藏
rpm --erase --allmatches --nodeps xmlrpc-c-devel-1.16.24-1206.1840.el5_7.4
posted @
2012-02-14 17:31 David1228 阅读(435) |
评论 (0) |
编辑 收藏
Http状态码以及常见Http Header返回状态详解
2011-05-17 15:36
站 长经常会遇到一些http状态码的问题。而所谓的404页就是服务器404重定向状态返回页面。数字404指的是404号状态码。一般常用到的有200号 状态码和404号状态码。200号表示网页被下载成功,而404号表示不能成功下载并产生错误。下面是HTTP状态码一览表。 1xx:请求收到,继续处理 2xx:操作成功收到,分析、接受 3xx:完成此请求必须进一步处理 4xx:请求包含一个错误语法或不能完成 5xx:服务器执行一个完全有效请求失败 100——客户必须继续发出请求 101——客户要求服务器根据请求转换HTTP协议版本 200——交易成功 201——提示知道新文件的URL 202——接受和处理、但处理未完成 203——返回信息不确定或不完整 204——请求收到,但返回信息为空 205——服务器完成了请求,用户代理必须复位当前已经浏览过的文件 206——服务器已经完成了部分用户的GET请求 300——请求的资源可在多处得到 301——删除请求数据 302——在其他地址发现了请求数据 303——建议客户访问其他URL或访问方式 304——客户端已经执行了GET,但文件未变化 305——请求的资源必须从服务器指定的地址得到 306——前一版本HTTP中使用的代码,现行版本中不再使用 307——申明请求的资源临时性删除 400——错误请求,如语法错误 401——请求授权失败 402——保留有效ChargeTo头响应 403——请求不允许 404——没有发现文件、查询或URl 405——用户在Request-Line字段定义的方法不允许 406——根据用户发送的Accept拖,请求资源不可访问 407——类似401,用户必须首先在代理服务器上得到授权 408——客户端没有在用户指定的饿时间内完成请求 409——对当前资源状态,请求不能完成 410——服务器上不再有此资源且无进一步的参考地址 411——服务器拒绝用户定义的Content-Length属性请求 412——一个或多个请求头字段在当前请求中错误 413——请求的资源大于服务器允许的大小 414——请求的资源URL长于服务器允许的长度 415——请求资源不支持请求项目格式 416——请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请求 也不包含If-Range请求头字段 417——服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下 一级服务器不能满足请求 500——服务器产生内部错误 501——服务器不支持请求的函数 502——服务器暂时不可用,有时是为了防止发生系统过载 503——服务器过载或暂停维修 504——关口过载,服务器使用另一个关口或服务来响应用户,等待时间设定值较长 505——服务器不支持或拒绝支请求头中指定的HTTP版本 ------------------------------------------------------- 英文版: 100:Continue 101:Switching Protocols 102:Processing 200:OK 201:Created 202:Accepted 203:Non-Authoriative Information 204:No Content 205:Reset Content 206:Partial Content 207:Multi-Status 300:Multiple Choices 301:Moved Permanently 302:Found 303:See Other 304:Not Modified 305:Use Proxy 306:(Unused) 307:Temporary Redirect 400:Bad Request 401:Unauthorized 402:Payment Granted 403:Forbidden 404:File Not Found 405:Method Not Allowed 406:Not Acceptable 407:Proxy Authentication Required 408:Request Time-out 409:Conflict 410:Gone 411:Length Required 412:Precondition Failed 413:Request Entity Too Large 414:Request-URI Too Large 415:Unsupported Media Type 416:Requested range not satisfiable 417:Expectation Failed 422:Unprocessable Entity 423:Locked 424:Failed Dependency 500:Internal Server Error 501:Not Implemented 502:Bad Gateway 503:Service Unavailable 504:Gateway Timeout 505:HTTP Version Not Supported 507:Insufficient Storage ------------------------------------------------------- 200号状态码 220.181.32.30 - - [02/Sep/2008:00:01:23 +0800] "GET /article/0572/72570.shtml HTTP/1.1" 200 28361 "-" "Baiduspider+(+http://www.baidu.com/search/spider.htm)" 服务器日志中的200表示使用GET传递方式网页72570.shtml下载成功。即:当用户或爬虫程序向网站服务器发出浏览请求时,服务器返回 HTTP 数据流里包含某种状态码,200响应号即状态码中的一种,表示本网页被成功下载。 301号状态码 220.181.32.30 - - [02/Sep/2008:00:01:31 +0800] "GET /my/view.php?aid=14183 HTTP/1.1" 301 - "-" "Baiduspider+(+http://www.baidu.com/search/spider.htm)" 服务器日志中的301表示使用GET传递方式动态网页aid=14183成功跳转。即:当用户或爬虫程序向网站服务器发出浏览请求时,服务器返回 HTTP 数据流包含某种状态码,301 重定向即状态码中的一种,表示本网页永久性转移到另一个地址。实际操作中我们可以将多个域名指向同一个网址,这也是搜索引擎唯一认可的一种网站转向的方 式。 404状态码
出现404状态码就证明有URL地址的网页浏览不到。很多时候由于网站的改版,使很多旧版网站url地址失效。这是你需要建立404状态页来保证你 网站通畅,能够达到一种回路的效果。切记404状态页需要单独设计,不能直接在服务器端直接跳转回首页。否则,搜索引擎会大量抓取网站首页失误当成404 页处理。 HTTP 404 错误意味着链接指向的网页不存在,即原始网页的URL失效,这种情况经常会发生,很难避免,比如说:网页URL生成规则改变、网页文件更名或移动位置、导 入链接拼写错误等,导致原来的URL地址无法访问;当Web 服务器接到类似请求时,会返回一个404 状态码,告诉浏览器要请求的资源并不存在。但是,Web服务器默认的404错误页面,无论Apache还是IIS,均十分简陋、呆板且对用户不友好,无法 给用户提供必要的信息以获取更多线索,无疑这会造成用户的流失。 因此,很多网站均使用自定义404错误的方式以提供用户体验避免用户流失。一般而言,自定义404页面通用的做法是在页面中放置网站快速导航链接、搜索框以及网站提供的特色服务,这样可以有效的帮助用户访问站点并获取需要的信息。 ------------------------------------------------------- 100 Continue指示客户端应该继续请求。回送用于通知客户端此次请求已经收到,并且没有被服务器拒绝。 客户端应该继续发送剩下的请求数据或者请求已经完成,或者忽略回送数据。服务器必须发送 最后的回送在请求之后。 101 Switching Protocols 服务器依照客服端请求,通过Upgrade头信息,改变当前连接的应用协议。服务器将根据Upgrade头立刻改变协议 在101回送以空行结束的时候。 Successful ================================= 200 OK 指示客服端的请求已经成功收到,解析,接受。 201 Created 请求已经完成并一个新的返回资源被创建。被创建的资源可能是一个URI资源,通常URI资源在Location头指定。回送应该包含一个实体数据 并且包含资源特性以及location通过用户或者用户代理来选择合适的方法。实体数据格式通过煤体类型来指定即content-type头。最开始服务器 必须创建指定的资源在返回201状态码之前。如果行为没有被立刻执行,服务器应该返回202。 202 Accepted 请求已经被接受用来处理。但是处理并没有完成。请求可能或者根本没有遵照执行,因为处理实际执行过程中可能被拒绝。 203 Non-Authoritative Information 204 No Content 服务器已经接受请求并且没必要返回实体数据,可能需要返回更新信息。回送可能包含新的或更新信息由entity-headers呈现。 205 Reset Content 服务器已经接受请求并且用户代理应该重新设置文档视图。 206 Partial Content 服务器已经接受请求GET请求资源的部分。请求必须包含一个Range头信息以指示获取范围可能必须包含If-Range头信息以成立请求条件。 Redirection ================================== 300 Multiple Choices 请求资源符合任何一个呈现方式。 301 Moved Permanently 请求的资源已经被赋予一个新的URI。 302 Found 通过不同的URI请求资源的临时文件。 303 See Other 304 Not Modified 如果客服端已经完成一个有条件的请求并且请求是允许的,但是这个文档并没有改变,服务器应该返回304状态码。304 状态码一定不能包含信息主体,从而通常通过一个头字段后的第一个空行结束。 305 Use Proxy 请求的资源必须通过代理(由Location字段指定)来访问。Location资源给出了代理的URI。 306 Unused 307 Temporary Redirect Client Error ===================== 400 Bad Request 因为错误的语法导致服务器无法理解请求信息。 401 Unauthorized 如果请求需要用户验证。回送应该包含一个WWW-Authenticate头字段用来指明请求资源的权限。 402 Payment Required 保留状态码 403 Forbidden 服务器接受请求,但是被拒绝处理。 404 Not Found 服务器已经找到任何匹配Request-URI的资源。 405 Menthod Not Allowed Request-Line请求的方法不被允许通过指定的URI。 406 Not Acceptable 407 Proxy Authentication Required 408 Reqeust Timeout 客服端没有提交任何请求在服务器等待处理时间内。 409 Conflict 410 Gone 411 Length Required 服务器拒绝接受请求在没有定义Content-Length字段的情况下。 412 Precondition Failed 413 Request Entity Too Large 服务器拒绝处理请求因为请求数据超过服务器能够处理的范围。服务器可能关闭当前连接来阻止客服端继续请求。 414 Request-URI Too Long 服务器拒绝服务当前请求因为URI的长度超过了服务器的解析范围。 415 Unsupported Media Type 服务器拒绝服务当前请求因为请求数据格式并不被请求的资源支持。 416 Request Range Not Satisfialbe 417 Expectation Failed Server Error =================================== 500 Internal Server Error 服务器遭遇异常阻止了当前请求的执行 501 Not Implemented 服务器没有相应的执行动作来完成当前请求。 502 Bad Gateway 错误的网关 503 Service Unavailable 因为临时文件超载导致服务器不能处理当前请求。 504 Gateway Timeout 505 Http Version Not Supported 常见返回状态码有200(正常)、404(无法访问)、500(页面中PHP/ASP/ASPX等有错误)、301(永久重定向)、302(普通跳转如js跳转,http跳转,asp中respone.redirect跳转及PHP使用的header发送的普通跳转等)。 常见Http Header返回状态详解:
当用户点击或搜索引擎向网站服务器发出浏览请求时,服务器将返回Http Header Http头信息状态码,常见几种如下: 1、Http/1.1 200 OK 访问正常 表示成功访问,为网站可正常访问时的状态。
2、Http/1.1 301 Moved Permanently301重定向永久重定向 对搜索引擎相对友好的跳转方式,当网站更换域名时可将原域名作301永久重定向到新域名,原域名权重可传递到新域名,也常有将不含www的域名301跳转到含www的,如xxx.com通过301跳转到www.xxx.com
3、Http/1.1 302 Found 为临时重定向 易被搜索引擎判为作弊,比如asp程序的response.Redirect()跳转、js跳转或静态http跳转。
4、Http/1.1 400 Bad Request 域名绑定错误 一般是服务器上域名未绑定成功,未备案等情况。
5、Http/1.1 403 Forbidden 没有权限访问此站 你的IP被列入黑名单,连接的用户过多,可以过后再试,网站域名解析到了空间,但空间未绑定此域名等情况。
6、Http/1.1 404 Not Found 文件或目录不存在 表示请求文件、目录不存在或删除,设置404错误页时需确保返回值为404。常有因为404错误页设置不当导致不存在的网页返回的不是404而导致搜索引擎降权。
7、Http/1.1 500 Internal Server Error 程序或服务器错误 表示服务器内部程序错误,出现这样的提示一般是程序页面中出现错误,如小的语法错误,数据连接故障等。
转载自: |
posted @
2012-01-17 14:47 David1228|
编辑 收藏
Java
//冒泡排序(升序和降序) 两层循环,外层排序控制,【内层排序比较大小,交换位置】
public static int[] bubbleSort(int[] arr){
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1 ; j++) {
if(arr[j] > arr[j + 1]){
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
//最大元素找到
System.out.println("第" + (i + 1) + "趟排序");
for (int k = 0; k < arr.length; k++) {
System.out.println(arr[k] + " ");
}
}
return arr;
}
二分查找理论实践参考
http://www.sunchis.com/html/java/2011/0426/323.html
public static void main(String[] args) {
int[] arr = new int[]{2,3,6,4,8,5,9,11,15,12,14,13};
int value = 9;
//System.out.println(directSerach(arr, 18));
arr = MaoPaoSortTest.bubbleSort(arr);
binarySerach(arr, 18);
}
/** *//**
* 直接查找 优点:很好理解,适合数据量小的查找 缺点:数据量大速度很慢. 降低查找效率
*/
public static int directSerach(int[] arr, int value){
for (int i = 0; i < arr.length; i++) {
if(value == arr[i]){
return i;
}
}
return -1;
}
/** *//**
* 二分查找方法 待查找的数组要有序.将有序数组一分为二
* 定义最小索引值low、最大索引值high、定义中间索引值middle.
* while(condition), condition low<=high
* 根据最大索引值和最小索引值计算中间值索引值middle,并将arr[middle]值与value比较.
* 1.如果value等于arr[middle],则直接返回middle索引值.
* 如果value大于arr[middle],则数组分隔的左侧过滤掉.将low索引值重置:middle+1
* 如果value小于arr[middle],则数组分隔的右侧过滤掉.将high索引值重置:middle-1
*/
public static int binarySerach(int[] arr, int value){
int low = 0; //最小下标索引
int high = arr.length; //最大下标索引
int middle = 0; //中间索引
while (low <= high) {
middle = (high + low) / 2;
//test
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
if(i == middle){
System.out.print("#");
}
System.out.print(" ");
}
System.out.println();
if(value == arr[middle]){
return middle;
}
if(value < arr[middle]){
high = middle - 1;
}
if(value > arr[middle]){
low = middle + 1;
}
}
return -1;
}
posted @
2012-01-14 15:39 David1228 阅读(238) |
评论 (0) |
编辑 收藏
xen环境下(centos操作系统)vnc配置
name = 'one-85'
#O CPU_CREDITS = 256
memory = '2048'
bootloader = "/usr/bin/pygrub"
disk = [
'file:/one_images/85/images/disk.0,xvda,w',
'file:/one_images/85/images/disk.1,xvdb,w',
'file:/one_images/85/images/disk.2,sdc,r',
]
vif = [
' mac=02:00:c0:a8:a3:a8,ip=192.168.163.168,bridge=xenbr0',
]
vcpus=2
vfb = [ 'type=vnc,vncunused=1,keymap=en-us,vnclisten=0.0.0.0' ]
posted @
2012-01-10 15:32 David1228 阅读(547) |
评论 (0) |
编辑 收藏
转载自:
http://conkeyn.iteye.com/blog/734186
总结还不错的
- jQuery获取Select选择的Text和Value:
- 语法解释:
- 1. $("#select_id").change(function(){//code...}); //为Select添加事件,当选择其中一项时触发
- 2. var checkText=$("#select_id").find("option:selected").text(); //获取Select选择的Text
- 3. var checkValue=$("#select_id").val(); //获取Select选择的Value
- 4. var checkIndex=$("#select_id ").get(0).selectedIndex; //获取Select选择的索引值
- 5. var maxIndex=$("#select_id option:last").attr("index"); //获取Select最大的索引值
- jQuery设置Select选择的 Text和Value:
- 语法解释:
- 1. $("#select_id ").get(0).selectedIndex=1; //设置Select索引值为1的项选中
- 2. $("#select_id ").val(4); // 设置Select的Value值为4的项选中
- 3. $("#select_id option[text='jQuery']").attr("selected", true); //设置Select的Text值为jQuery的项选中
- jQuery添加/删除Select的Option项:
- 语法解释:
- 1. $("#select_id").append("<option value='Value'>Text</option>"); //为Select追加一个Option(下拉项)
- 2. $("#select_id").prepend("<option value='0'>请选择</option>"); //为Select插入一个Option(第一个位置)
- 3. $("#select_id option:last").remove(); //删除Select中索引值最大Option(最后一个)
- 4. $("#select_id option[index='0']").remove(); //删除Select中索引值为0的Option(第一个)
- 5. $("#select_id option[value='3']").remove(); //删除Select中Value='3'的Option
- 5. $("#select_id option[text='4']").remove(); //删除Select中Text='4'的Option
-
- http://www.cnblogs.com/SAL2928/archive/2008/10/28/1321285.html
-
- jquery radio取值,checkbox取值,select取值,radio选中,checkbox选中,select选中,及其相关
- 获 取一组radio被选中项的值
- var item = $('input[@name=items][@checked]').val();
- 获 取select被选中项的文本
- var item = $("select[@name=items] option[@selected]").text();
- select下拉框的第二个元素为当前选中值
- $('#select_id')[0].selectedIndex = 1;
- radio单选组的第二个元素为当前选中值
- $('input[@name=items]').get(1).checked = true;
-
- 获取值:
-
- 文本框,文本区域:$("#txt").attr("value");
- 多选框 checkbox:$("#checkbox_id").attr("value");
- 单选组radio: $("input[@type=radio][@checked]").val();
- 下拉框select: $('#sel').val();
-
- 控制表单元素:
- 文本框,文本区域:$("#txt").attr("value",'');//清空内容
- $("#txt").attr("value",'11');// 填充内容
-
- 多选框checkbox: $("#chk1").attr("checked",'');//不打勾
- $("#chk2").attr("checked",true);// 打勾
- if($("#chk1").attr('checked')==undefined) //判断是否已经打勾
-
- 单选组 radio: $("input[@type=radio]").attr("checked",'2');//设置value=2的项目为当前选中项
- 下拉框 select: $("#sel").attr("value",'-sel3');//设置value=-sel3的项目为当前选中项
- $("<option value='1'>1111</option><option value='2'>2222</option>").appendTo("#sel")//添加下拉框的option
- $("#sel").empty();// 清空下拉框
-
- ----------------------------------------------------------------------------------------------------
-
-
-
- //遍历option和添加、移除option
- function changeShipMethod(shipping){
- var len = $("select[@name=ISHIPTYPE] option").length
- if(shipping.value != "CA"){
- $("select[@name=ISHIPTYPE] option").each(function(){
- if($(this).val() == 111){
- $(this).remove();
- }
- });
- }else{
- $("<option value='111'>UPS Ground</option>").appendTo($("select[@name=ISHIPTYPE]"));
- }
- }
-
-
- //取得下拉選單的選取值
-
- $(#testSelect option:selected').text();
- 或$("#testSelect").find('option:selected').text();
- 或$("#testSelect").val();
- //////////////////////////////////////////////////////////////////
- 记 性不好的可以收藏下:
- 1,下拉框:
-
- var cc1 = $(".formc select[@name='country'] option[@selected]").text(); //得到下拉菜单的选中项的文本(注意中间有空格)
- var cc2 = $('.formc select[@name="country"]').val(); //得到下拉菜单的选中项的值
- var cc3 = $('.formc select[@name="country"]').attr("id"); //得到下拉菜单的选中项的ID属性值
- $("#select").empty();//清空下拉框 //$("#select").html('');
- $("<option value='1'>1111</option>").appendTo("#select")//添加下拉框的option
-
- 稍微解释一下:
- 1.select[@name='country'] option[@selected] 表示具有name 属性,
- 并 且该属性值为'country' 的select元素 里面的具有selected 属性的option 元素;
- 可以看出有@开头的就表示后面跟 的是属性。
-
- 2,单选框:
- $("input[@type=radio][@checked]").val(); //得到单选框的 选中项的值(注意中间没有空格)
- $("input[@type=radio][@value=2]").attr("checked",'checked'); //设置单选框value=2的为选中状态.(注意中间没有空格)
-
- 3,复选框:
- $("input[@type=checkbox][@checked]").val(); //得到复选框的选中的第一项的值
- $("input[@type=checkbox][@checked]").each(function() { //由于复选框一般选中的是多个,所以可以循环输出
- alert($(this).val());
- });
-
- $("#chk1").attr("checked",'');//不打勾
- $("#chk2").attr("checked",true);// 打勾
- if($("#chk1").attr('checked')==undefined){} //判断是否已经打勾
-
-
- 当然jquery的选择器是强大的. 还有很多方法.
-
- <script src="jquery-1.2.1.js" type="text/javascript"></script>
- <script language="javascript" type="text/javascript">
- $(document).ready(function(){
- $("#selectTest").change(function()
- {
- //alert("Hello");
- //alert($("#selectTest").attr("name"));
- //$("a").attr("href","xx.html");
- //window.location.href="xx.html";
- //alert($("#selectTest").val());
- alert($("#selectTest option[@selected]").text());
- $("#selectTest").attr("value", "2");
-
- });
- });
- </script>
-
-
- <a href="#">aaass</a>
-
- <!--下拉框-->
- <select id="selectTest" name="selectTest">
- <option value="1">11</option>
- <option value="2">22</option>
- <option value="3">33</option>
- <option value="4">44</option>
- <option value="5">55</option>
- <option value="6">66</option>
- </select>
- jquery radio取值,checkbox取值,select取值,radio选中,checkbox选中,select选中,及其相关获取一组radio被选中 项的值
- var item = $('input[@name=items][@checked]').val();
- 获取select被选 中项的文本
- var item = $("select[@name=items] option[@selected]").text();
- select 下拉框的第二个元素为当前选中值
- $('#select_id')[0].selectedIndex = 1;
- radio单选组的第二个 元素为当前选中值
- $('input[@name=items]').get(1).checked = true;
- 获取值:
- 文本 框,文本区域:$("#txt").attr("value");
- 多选框 checkbox:$("#checkbox_id").attr("value");
- 单选组radio: $("input[@type=radio][@checked]").val();
- 下拉框select: $('#sel').val();
- 控 制表单元素:
- 文本框,文本区域:$("#txt").attr("value",'');//清空内容
- $("#txt").attr("value",'11');// 填充内容
- 多选框checkbox: $("#chk1").attr("checked",'');//不打勾
- $("#chk2").attr("checked",true);// 打勾
- if($("#chk1").attr('checked')==undefined) //判断是否已经打勾
- 单选组radio: $("input[@type=radio]").attr("checked",'2');//设置value=2的项目为当前选中项
- 下拉框 select: $("#sel").attr("value",'-sel3');//设置value=-sel3的项目为当前选中项
- $("<optionvalue='1'& gt;1111</option><optionvalue='2'>2222</option& gt;").appendTo("#sel")//添加下拉框的option
- $("#sel").empty();// 清空下拉框
-
- 获取一组radio被选中项的值
- var item = $('input[@name=items][@checked]').val();
- 获取select被选中项的文本
- var item = $("select[@name=items] option[@selected]").text();
- select下拉框的第二个元素为当 前选中值
- $('#select_id')[0].selectedIndex = 1;
- radio单选组的第二个元素为当前选中值
- $('input[@name=items]').get(1).checked = true;
- 获取值:
- 文本框,文本区域:$("#txt").attr("value");
- 多选框 checkbox:$("#checkbox_id").attr("value");
- 单选组radio: $("input[@type=radio][@checked]").val();
- 下拉框select: $('#sel').val();
- 控 制表单元素:
- 文本框,文本区域:$("#txt").attr("value",'');//清空内容
- $("#txt").attr("value",'11');// 填充内容
- 多选框checkbox: $("#chk1").attr("checked",'');//不打勾
- $("#chk2").attr("checked",true);// 打勾
- if($("#chk1").attr('checked')==undefined) //判断是否已经打勾
- 单选组radio: $("input[@type=radio]").attr("checked",'2');//设置value=2的项目为当前选中项
- 下拉框 select: $("#sel").attr("value",'-sel3');//设置value=-sel3的项目为当前选中项
- $("<option value='1'>1111</option><option value='2'>2222</option>").appendTo("#sel")//添加下拉框的option
- $("#sel").empty();// 清空下拉框
query获取数据并生成下拉菜单,记下来,免得又弄丢.这东东一不用就忘,郁闷~!!!
<script type="text/javascript">
$(document).ready(function() {
GetByJquery();
$("#ddlProvince").change(function() { GetCity() });
$("#ddlCity").change(function() { GetDistrict() });
});
function GetByJquery() {
$("#ddlProvince").empty(); //清空省份SELECT控件
$.getJSON("/ajax/GetProvinceList", function(data) {
$.each(data, function(i, item) {
$("<option></option>")
.val(item["ProvinceID"])
.text(item["ProvinceName"])
.appendTo($("#ddlProvince"));
});
GetCity();
});
}
function GetCity() {
$("#ddlCity").empty(); //清空城市SELECT控件
var url ="/ajax/GetCityList/" + $("#ddlProvince").val();
$.getJSON(url, function(data) {
$.each(data, function(i, item) {
$("<option></option>")
.val(item["CityID"])
.text(item["CityName"])
.appendTo($("#ddlCity"));
});
GetDistrict();
});
}
function GetDistrict() {
$("#ddlDistrict").empty(); //清空市区SELECT控件
var url = "/ajax/GetDistrictList/" + $("#ddlCity").val();
$.getJSON(url, function(data) {
$.each(data, function(i, item) {
$("<option></option>")
.val(item["DistrictID"])
.text(item["DistrictName"])
.appendTo($("#ddlDistrict"));
});
});
}
</script>
posted @
2011-11-28 14:35 David1228 阅读(1630) |
评论 (0) |
编辑 收藏
http://sebug.net/paper/python/pr01.html#s01
前言
目录表
- 本书的读者
- 本书的由来
- 本书目前的状况
- 官方网站
- 约定条款
- 反馈
- 值得思考的一些东西
Python语言可能是第一种即简单又功能强大的编程语言。它不仅适合于初学者,也适合于专业人员使用,更加重要的是,用Python编程是一种愉 快的事。本身将帮助你学习这个奇妙的语言,并且向你展示如何即快捷又方便地完成任务——真正意义上“为编程问题提供的完美解决方案!”
本书可以作为Python编程语言的一本指南或者教程。它主要是为新手而设计,不过对于有经验的程序员来说,它同样有用。
即便你对计算机的了解只是如何在计算机上保存文本文件,你都可以通过本书学习Python。如果你有编程经验,你也可以使用本书学习Python。
如果你以前有编程经验,那么你将会对Python语言和其他你所钟爱的编程语言之间的区别感兴趣。对此我为你指出了许多这样的区别。顺便提醒你,Python将很快成为你最喜欢的编程语言!
posted @
2011-10-13 14:30 David1228 阅读(325) |
评论 (0) |
编辑 收藏
转载自 http://hi.baidu.com/fwmf/blog/item/e4284cee092e66f5b3fb9575.html
週一, 05/05/2008 - 14:55 — sunchiahome
Xen - Networking
Step 0 : Xen底下的網路架構
Step 1 : 虛擬還是實體
Step 2 : network-bridge
Step 3 : network-nat
Step 4 : network-route
Step 5 : 參考網頁
Step 0 : Xen底下的網路架構
在虛擬化下的環境就屬網路裝置最為複雜難懂,不過模式大致可以畫分成 3 種 1.network-bridge , 2.network-nat 和 3.network-route 最主要就是看的懂虛擬與實際的網路裝置是怎麼對應的(Logical NICs <-> Physical NICs).
不管是 Xen 還是 VMware 虛擬化下的網路裝置,主要都是透過這 3 種不同的模式讓 Guest OS 的虛擬網路裝置透過實體的網路接出去.這邊我直接以 RHEL5 Xen 的環境下來做說明.剛開始使用 Xen 的人一定會對於他的網路架構搞不清楚.光是在 Dom0 用 ifconfig 就可以看到好多以前沒看過的裝置出現,因為 Dom0 能直接與 Hypervisor 溝通所以所有 DomU 所產生的虛擬裝置都會在在這裡秀出來.
[root@benjr ~]#ifconfig eth0 Link encap:Ethernet HWaddr 00:02:B3:9D:87:65 .... 略 .... lo Link encap:Local Loopback .... 略 .... peth0 Link encap:Ethernet HWaddr FE:FF:FF:FF:FF:FF .... 略 .... vif0.0 Link encap:Ethernet HWaddr FE:FF:FF:FF:FF:FF .... 略 .... vif1.0 Link encap:Ethernet HWaddr FE:FF:FF:FF:FF:FF .... 略 .... virbr0 Link encap:Ethernet HWaddr 00:00:00:00:00:00 .... 略 .... xenbr0 Link encap:Ethernet HWaddr FE:FF:FF:FF:FF:FF .... 略 .... |
一般的 Linux 下的網路裝置名稱為 eth0,eth1...,但是在 Xen 底下許多的硬體裝置都是虛擬出來的(包括 Dom0 下的網路裝置也是). 這裡你會看到 eth0, lo, peth0, vif0.0, vif1.0, virbr0, xenbr0. 這些是什麼東西阿,我們直接來看下面這一張圖你會清楚了解 Xen 底下的網路裝置是怎麼一回事.下面我會針對每一項做說明.
因為使用不同的模式會有不同的虛擬裝置出現,所以上面的圖示是使用 RHEL5 所預設的 network-bridge 模式,上圖我只列出了 eth0, peth0, vif0.0, vif1.0 以及, 其中為例出的 lo 是 Loop device 也就是我們常在使用的 127.0.0.1 至於 virbr0 則是在 QEMU 所提供的 Bridge NAT 模式上來使用請參考 QEMU-Bridge NAT http://benjr.tw/?q=node/520 .
Step 1 : 虛擬還是實體
Xen 主要網路裝置可以分成兩種,一個就是實體 Physical 的(peth0,peth1...)而另一種就是虛擬 Logical 出來的(eth0,eth1...)以及(vif<id#>.0,vif<id#>.1..),實體的可以很清楚的知道是 pethx,但是虛擬的怎麼這麼複雜呢!!!先看看下面這張圖就會很清楚了.
我們先來看目前所有的 Guest OS 有哪一些再來做說明.當然你看到的會和我的不盡相同.系統會依據不同的實體和虛擬的網路裝置以及 Guest OS 的不同做調整的.
#列出所有 domU [root@benjr ~]# xm list Name Id Mem(MB) VCPUs State Time(s) Domain-0 0 7619 4 r---- 43213.6 rhel4 1 512 1 -b--- 9601 |
規則很簡單:
1.不管是在 Dom0,還是DomU 你會看到 eth0,eth1...這些都是虛擬出來的網路卡裝置.
2.在 Dom0 裡面你可以看到 vif<id#>.0,vif<id#>.1...的裝置存在,因為 Dom0 能直接與 Hypervisor 溝通所以所有 DomU 所產生的虛擬裝置都會在在這裡秀出來.
3.他們的對應也相當簡單, vif<id#>.x 中的 id 就是 DomU 的 id 所以你在 Dom0 底下的 eth0 是對應到 vif0.0, eth1 是對應到 vif0.1 如此依序下去(最多能產生的網路裝置為八個),至於 vif1.0 就是某個 Dom U(ID=1) 的 eth0 我們可以透過 #xm list 看 DomU 所對應的 id 為何!!
目前我的環境只有 Dom0(RHEL5) 以及一個 Guest OS(RHEL4),因為實體的網路卡裝置有 2 個所以我設定的 2 個 Xen Bridge,分別對應到不同的虛擬網卡,所以 Xen 底下整個網路裝置就像下面所示.
Peth0 -> 實體網路卡裝置(Physical NIC)
Peth1 -> 實體網路卡裝置(Physical NIC)
Dom0 -> eth0 -> vif0.0
Dom0 -> eth1 -> vif0.1
Dom1(RHEL4) -> eth0 -> vif1.0
Dom1(RHEL4) -> eth1 -> vif1.1
4.至於這些虛擬的裝置會如何對應到真實的裝置這就跟你所使用的模式有關,還記得剛剛提到的模式(network-bridge)下面的指令可以讓你目前 環境 peth 是如何對應vif
[root@benjr ~]# brctl show bridge name bridge id STP enabled interfaces virbr0 8000.000000000000 no xenbr0 8000.feffffffffff no peth0 vif0.0 vif1.0 xenbr1 8000.fefffffffffe no peth1 vif0.1 vif1.1 [root@benjr scripts]# /etc/xen/scripts/network-bridge status .... 略 .... bridge name bridge id STP enabled interfaces virbr0 8000.000000000000 no xenbr0 8000.feffffffffff no peth0 vif0.0 vif1.0 xenbr1 8000.fefffffffffe no peth1 vif0.1 vif1.1 .... 略 .... |
Dom0 -> eth0 -> vif0.0 -> xenbr0 -> peth0 (實體網路卡裝置 Physical NIC)
Dom1(RHEL4) -> eth0 -> vif1.0 -> xenbr0 -> peth0 (實體網路卡裝置Physical NIC)
Dom0 -> eth1 -> vif0.1 -> xenbr1 -> peth1 (實體網路卡裝置Physical NIC)
Dom1(RHEL4) -> eth1 -> vif1.1 -> xenbr1 -> peth1 (實體網路卡裝置Physical NIC)
note: 其中的 vif<id#>.x 會隨著 DomU 關機而消失.
因為網卡是虛擬出來的所以 MAC 不太可能跟著網卡一起,所以每當產生新的 Guest Virtula Network(虛擬網卡)就會依據規則來產生:
XEN:
虛擬網路裝置的 mac 是如何產生的,他是有一個規則性的. mac :XY:XX:XX:XX:XX:XX ,mac 使用16進制來顯示 X 可為任何的16進制(0~9,A,B,C,D,E,F), Y 則只能使用 2, 6, A 或 E. 不過 Xen 建議使用的範圍 00:16:3e:xx:xx:xx. 這個區段是保留給 Xen 使用的.
VMware:
mac : 00:0c:29:xx:xx:xx 或是 00:50:56:xx:xx:xx 這個區段是保留給 VMware 使用的,VMware 建議固定 mac address 使用的範圍 00:50:56:[00-3F]:xx:xx . 要不然就讓系統來指定.
Step 2 : network-bridge
要使用哪種模式定義在 /etc/xen/xend-conf.sxp 系統預設使用 Bridge 模式,主要會啟動 network-bridge 與 vif-bridge 這兩個 shell script.在這個模式下會看到一個裝置 xenbr0 ,接下來我會針對 xenbr0 來說明這是什麼東西.要認識 xenbr0 的最好方式是直接看 Networking 啟動時的步驟,當 Dom0 的 xend 啟動時, 首先會執行 /etc/xen/scripts/network-bridge 這個 script, 網路啟動步驟如下:
1.首先產生一個新的 bridge 名稱為 xenbr0
2.此時實體的網路裝置 eth0 會被關閉
3.實體的 eth0 IP 和 MAC addresses 會複製到虛擬的網路裝置中 veth0
4.實體的網路裝置 eth0 名稱會被修改成 peth0
5.虛擬的網路裝置 veth0 名稱會被修改成 eth0
6.peth0 和 vif0.0 會被連接到 bridge xenbr0 (此時的 xenbr0 就如同一個 switch)
7.bridge xenbr0, peth0, eth0 和 vif0.0 都會被啟動.
note: Dom0上的防火牆是不會引響到 DomU 的網路流通的.
當 RHEL5 Xen 安裝完成時系統預設的 Bridge(xenbri0) 只有一個,但是當我們有多張網卡時就需要手動設定多個 Bridge.假設系統沒有經過其他設定,其網路組態就像下面所描述的 Dom0(eth0) -> vif0.0 -> xenbr0 -> peth0.
如果我們系統上有多張實體網卡時就可以透過修改設定檔 /etc/xen/xend- config.sxp 讓虛擬的網路裝置可以透過其他實體裝置連接網路.
[root@benjr ~]# vi /etc/xen/xend-config.sxp ... #(network-script network-bridge) (network-script my-network-script) ... #把上面的修改成我自己設定的 網路 script 名稱(my-network-script).接下來將我們的 my-network-script 修改成我們需要的組態即可. [root@benjr ~]# vi /etc/xen/scripts/my-network-script #!/bin/sh /etc/xen/scripts/network-bridge start vifnum=0 netdev=eth0 bridge=xenbr0 /etc/xen/scripts/network-bridge start vifnum=1 netdev=eth1 bridge=xenbr1 [root@benjr ~]# chmod a+x /etc/xen/scripts/my-network-script #不要忘記修改檔案的屬性. |
如果你是要臨時增加一個 Bridge 可用下面的指令.建立一個 Network bridge
[root@benjr ~]#/etc/xen/scripts/network-bridge start vifnum=1 bridge=xenbr1 netdev=eth1 vifnum=1 ;虛擬裝置號碼,系統預設有 8 個 loopback 裝置可以使用,而預設值為 0.可以在開機時指定 loopback 最大到32個 nloopbacks=<N> bridge=xenbr1 ;設定 Network Bridge 名稱為 xenbr1,預設值為 xenbr${vifnum}. netdev=eth1 ;設定 Network Bridge xenbr1 透過實體 eth1 連接外部.預設值為 eth$(vifnum} |
但是 DomU 啟動時是依據 vif-bridge 這個script 來執行.
當 domU 啟動時, xend (running in dom0) 會來執行這個 vif-bridge script, 虛擬網路啟動步驟如下:
1.將 vif<id#>.0 連接到適當的 xenbr0
2.啟動 vif<id#>.0 .
所有的 scripts 都存放在 /etc/xen/scripts. 而 Bridge 只是 Xen 其中一種的網路模式,其他的還有 NAT's Networking 與 Routed Networking 這些後面會再介紹.
Step 3 : network-nat
RHEL5 Xen 的網路環境預設為 bridge 模式,如果不合你使用時可以選擇其他的模式 network-nat 或是 network-route ,不過這裡先介紹一下 NAT 的模式,先來說說什麼是 NAT ,NAT 的全名就是 network address translation,最常應用在將 Private IP 轉換成 Public IP ,Private IP 只限是用於私人網路,此類的封包無法在 Internet 上傳送,如 10.0.0.0(subnet mask : 10.255.255.255) ,172.16.0.0(subnet mask : 172.31.255.255) 以及 192.168.0.0(subnet mask : 192.168.255.255) 唯有 Public IP 是在 Internet 可以被合法傳遞,所以 NAT 最主要的目的就是為了將內部的 Private IP 透過轉換將資料可以在 Internet 上傳送.使用這種方式的好處是外部無法直接和 Guest OS 相連接,這樣間接的加強的系統的安全性.
還記得設定檔在 Dom0(RHEL 5) Xen 的網路設定目錄 /etc/xen/xend-conf.sxp 將預設的 bridge 改成 NAT 模式.
[root@benjr ~]# vi /etc/xen/xend-config.sxp (network-script network-nat) #(network-script network-bridge) #(network-script network-route) (vif-script vif-nat) #(vif-script vif-bridge) #(vif-script vif-route) |
記得將 (network-script network-bridge) ,(vif-script vif-bridge) 做 "#" (把它當成註記).這樣所有的 Guest OS 當將可以使用 NAT 的模式,但是還需要修改一下 Guest OS 的設定檔案.不過先將 xen 的服務重新啟動.
[root@benjr ~]# /etc/init.d/xend restart |
修改 Guest OS 的設定檔,目前我系統上面有一個 GuesOS : RHEL4 ID=1,設定檔名稱也為 RHEL4
[root@benjr ~]# vi /etc/xen/rhel4 name = "rhel4" uuid = "cf67710d-b756-086b-8cde-be61d2faca1b" maxmem = 512 memory = 512 vcpus = 1 bootloader = "/usr/bin/pygrub" on_poweroff = "destroy" on_reboot = "restart" on_crash = "restart" vfb = [ "type=vnc,vncunused=1,keymap=en-us" ] disk = [ "phy:/dev/sda5,xvda,w" ] vif = [ "mac=00:16:3e:27:95:c0,ip=10.0.0.1" ] |
- name
這就是 VM 的名稱,虛擬化的環境下其 VM 名稱必須為唯一的.
- uuid
通用唯一識別碼(Universally Unique Identifier,UUID),系統會指定一個唯一的 uuid 來給每一台 VM.
- maxmem
通常我們在指定記憶體大小給 Guest VM 時可以先指定多一點,但是多指定的時候並不會真的使用到這麼多,先指定的優點是系統可以線上直接增加 VM 記憶體大小.
- memory
目前 VM 所真正使用的記體的多寡.
- vcpus
在 VM 所使用的邏輯 CPU 數目.
- bootloader
/usr/bin/pygrub 是 VM 所使用的 Bootloader 主要也就是將 VM 的 kernel/initrd 載入系統,類似於 GRUB,Xen 主要使用了 paravirtualized 的技術,他並不像是 VMware 使用 full virtualization 還有模擬出 BIOS 的環境.pygrub 還包含了一項 PXEBoot 的功能.
- on_poweroff/reboot/crash
當系統在 poweroff/reboot/crash VM 所對應的動作為何,系統在 poweroff 是做 destory 其實也就是 poweroff 主要是將 VM 的記憶體肆放並將硬碟資料確切寫回,而 reboot/crash 則是將 VM 重新開機.
- vfb
Xen 底下的 VM 都是透過 VNC 來傳送畫面,所以這裡的 vfb(virtual framebuffer device) 就是設定系統畫面與輸入裝置 Keyboard/Mouse.
- disk
虛擬的 VM 所使用的硬碟模式可以為實體 partition 也可以為 image 的方式.
- vif
這就是這一次要修改的重點 vif(virtual network devices).也就是和網路裝置相關的設定.vif = [ "mac=00:16:3e:27:95:c0,ip=10.0.0.1" ] 其中的 mac 可以不設定主要就是 IP,必須和 VM OS 所設定的 IP 相同.
回到 DomU 的 Guest OS (RHEL4) 將 IP 設定成跟剛剛在 Dom0 設定的一模一項.
# Xen Virtual Ethernet [root@DomU ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 ONBOOT=yes BOOTPROTO=static IPADDR=10.0.0.1 NETMASK=255.255.255.0 GATEWAY=10.0.0.128 |
並且將 DomU 網路的服務重新啟動
[root@DomU ~]#service network restart |
將 DOMU(RHEL4) 重新啟動,回到DOM0 第一件事情你會發現 xen bridge(xenbr0) 不見了,而且 vif1.0(Guest OS:RHEL4 ID=1) 多了 IP 的設定值,這個是給 Guest OS 所使用的 default gateway.預設 default gateway 為 10.0.0.128 ,如果你的 DomU 的 Guest OS 有很多時,在 Dom0 下的每一個網路裝置 vif(Dom ID).0 都會產生不同的 default gateway 從 10.0.0.128 開始接下來的就會是 10.0.0.129.如此依序下去,不過在 DomU 的 Guest OS 只要隨便指定任何一個 default gateway 都可以. 當你選擇的網路為 NAT 時你的 Dom0 的網路裝置就像是一台 NAT ,所有的 Guest OS(DomU) 都會透過 NAT 來轉送 private IP 的資料.
1. 所有 domU 上的虛擬機器都是在相同的 Private 私人網域.
2. 所有 domU 虛擬機器的封包都必須透過 dom0 的 NAT 去連結到其他的網路.
3. 如同一般的 NAT 所有 domU 上的虛擬機器都是被隱藏在 private 私人網域,所以外部不能直接連接到 DomU 上的虛擬機器.必須透過 Dom0 的 default gateway.
現在回 Dom 0 觀察一下網路環境有什麼改變.使用指令 "ifconfig" 可以很清楚看到 vif1.0 自動得到的 IP 為 10.0.0.128
[root@benjr ~]# ifconfig vif1.0 vif1.0 Link encap:Ethernet HWaddr FE:FF:FF:FF:FF:FF inet addr:10.0.0.128 Bcast:0.0.0.0 Mask:255.255.255.255 inet6 addr: fe80::fcff:ffff:feff:ffff/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:98 errors:0 dropped:0 overruns:0 frame:0 TX packets:73 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:32 RX bytes:11014 (10.7 KiB) TX bytes:9404 (9.1 KiB) |
使用 "iptables -L" 來看目前防火牆 iptables 狀態的確多了 10.0.0.1 的規則.
[root@benjr ~]# iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT udp -- anywhere anywhere udp dpt:domain ACCEPT tcp -- anywhere anywhere tcp dpt:domain ACCEPT udp -- anywhere anywhere udp dpt:bootps ACCEPT tcp -- anywhere anywhere tcp dpt:bootps Chain FORWARD (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere 192.168.122.0/24 state RELATED,ESTABLISHED ACCEPT all -- 192.168.122.0/24 anywhere ACCEPT all -- anywhere anywhere REJECT all -- anywhere anywhere reject-with icmp-port-unreachable REJECT all -- anywhere anywhere reject-with icmp-port-unreachable ACCEPT all -- 10.0.0.1 anywhere PHYSDEV match --physdev-in vif1.0 ACCEPT udp -- anywhere anywhere PHYSDEV match --physdev-in vif1.0 udp spt:bootpc dpt:bootps Chain OUTPUT (policy ACCEPT) target prot opt source destination |
使用指令 "route" 可以看到只要是傳給 10.0.0.1 (VM:RHEL4) 都是經過 vif1.0
[root@benjr ~]# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 10.0.0.1 * 255.255.255.255 UH 0 0 0 vif1.0 192.168.122.0 * 255.255.255.0 U 0 0 0 virbr0 192.8.1.0 * 255.255.255.0 U 0 0 0 eth0 169.254.0.0 * 255.255.0.0 U 0 0 0 eth0 |
如果你要讓 VM 虛擬機透過 dhcp 自動得到 ip,可以參考下列幾篇文章.
http://www.nikhef.nl/pub/projects/grid/gridwiki/index.php/Xen_3.2,_CentO...
Step 4 : network-route
未完成
Step 5 : 參考網頁
http://wiki.xensource.com/xenwiki/XenNetworking
http://wiki.kartbuilding.net/index.php/Xen_Networking
posted @
2011-09-25 23:01 David1228 阅读(319) |
评论 (0) |
编辑 收藏
红帽中出现This system is not registered with RHN这个的原因是因为红帽中没有注册RHN。解决办法:(假定你已安装yum,且网络畅通)更改yum的源,即更换/etc/yum.repos.d/rhel-debuginfo.repo 这个文件。进入/etc/yum.repos.d/目录,终端中输入wget http://docs.linuxtone.org/soft/lemp/CentOS-Base.repo即可在此目录下得到CentOS- Base.repo文件,这是centos的源文件,只需将其重命名为rhel-debuginfo.repo即可,以前的文件做个备份。
posted @
2011-09-22 17:56 David1228 阅读(2281) |
评论 (0) |
编辑 收藏
9月2日,新东方“相信未来——2011中国大学新生学习规划公益巡讲”首场讲座在北京圆明园遗址公园南门广场举行。新东方教育科技集团董事长兼首席执行官俞敏洪和创新工场董事长兼首席执行官李开复先后登台演讲,来自北京大学、清华大学、北京科技大学、中央民族大学、首都师范大学等首都51所高校的近万名大学新生聆听了这场关于学习、成长的精彩讲座。以下为俞敏洪演讲全文:
亲爱的来自北京各个高校的同学们:
大家下午好!
非常感谢大家来到这么一个特殊的地方,也感谢大家在下午顶着非常晒的太阳,来这儿听我和李开复跟大家聊大学生活。
请问我们现在坐的地方的背后是什么?圆明园。可以说中国的近代史就是由圆明园的废墟开始的历史。圆明园是哪一年被烧掉的?大家都知道1860年英法联军。为什么远离万里之外的英国和法国跑到我们中国这个首都之地把圆明园给烧掉?最根本的原因是什么?是因为圆明园里面有好东西吗?是因为圆明园没人保护吗?还是因为圆明园中国人民当时没有能力保护?很明显的是没有能力保护。谁都知道,中国近100多年的发展史是一部耻辱的历史。近30年中国改革开放的历史,是一部从耻辱中间不断地站起来的历史。
今天的中国在世界上已经有了一定的地位。20年前我申请到美国去的时候,不断地被拒签,今天我们想要去美国或者西方其他国家基本上可以拿到签证,这一点表明了我们变得不断强大。但是,站在这个地方,我们可以清楚地知道,一个国家如果很贫弱的话就会受到欺负。这是为什么邓小平总结了一句话,非常简单的一句话,叫做“发展是硬道理”。今天的中国有了一定的地位,但是依然不够强大。我们所说的强大,不是说要能够战胜所有的国家,不是说要打到英国大英博物馆或者打到法国的卢浮宫,去把东西抢回来。我们所说的强大,是从经济、政治、文化到精神的强大。
我们在座的每个人一辈子的历史,它可以是光荣的,也可以是耻辱的;它可以是失败的,也可以是成功的。你想变得成功,你想变得光荣,不在于外在的任何条件,而在于你自身。不在于说你本身现在是什么地位,而在于一辈子你到底具备什么样的梦想。我们很多同学在一路奋斗以后,走进了北京的大学。在座的有来自有北大、清华这样的名牌学校,也有像吉利大学这样的民办学校。似乎我们进入大学的门槛和分数是不一样的,但是同学们请记住,这只是你人生的一个起点。在过去从小学到中学毕业的12年的历史,我们经历了艰苦卓绝的奋斗。因为如果我们不努力、不奋斗,就不可能走进大学。但是,走进大学,只是一次生命真正的开始。
我们大家都知道,只要你保证身体健康就能活很多年。假如我们能活到100岁,那你还有80年的事要做。很多同学说,我现在已经比别的同学差得很远,我未来到底怎么样才能改善?我有一句话,人最重要的是志向,是内心的渴望,而不是外在的条件。从外在条件来说,我们人一辈子,从出生的那一天开始就是不平等的,生而不平等,这是一个事实。你出生在农民家里和出生在官宦家里的条件是不一样的,能得到的资源也是不一样的。但是,我们人的一辈子的奋斗过程,就是不断地去使自己有能力获取更大的资源、实现更大的梦想,并且回过头来把这种资源贡献给社会的过程。所以,当有人问我说,俞老师,我这辈子还能追上别人吗?像你这样的成就或者像你做的事情,我未来还可以做到吗?我可以肯定地告诉你:只要我能做到,你就能做到;只要李开复能做到,你就能做到;只要马云能做到,你就能做到。因为我们这些人的起点并不比你更高,某种意义上说,甚至应该比你更低。人生一辈子不是百米赛跑,如果百米赛跑早跑一秒钟或者晚跑一秒钟,你可能就会晚到一秒钟或者早到一秒钟。人生走的是无穷无尽的马拉松,马拉松不需要去计较你的起点是落后了还是站在第一名,马拉松计较的是你到底能够走多远,到底能够坚持走多久。如果说你能坚持走出足够的距离,哪怕你放慢一点儿速度,只要前进的方向是清晰的,未来你就能走出别人所没有走出来的距离,你就能看到别人没有看到的风景。我只是希望我们在座的所有同学们,不要像圆明园一样,最后自己被倒成一片废墟,而自己的生命回顾起来也是一片废墟。我们希望的是,现在趁着我们还很年轻,趁着我们还有理想,趁着我们还有激情,就应该让生命进一步地前行,让生命进一步地发出光彩和热。
同学们,我们现在站在了新的起点上,就是我们的大学生活。我刚才说过,如果我们大学生活要往前走的话,我们不需要太关注过去,不需要关注现在所在的大学是好还是坏,不需要关注家庭出身是农民还是工人,不需要关注长相是好看还是难看,甚至未来不需要关注你到底能够到国外去读书还是留在国内读书,因为所有这一切都是外在的东西。外在的东西尽管在一定阶段对我们来说是很重要的,但是从长远的一辈子来说,对我们来说是不重要的。
以大学为例子,我们进了北大或者清华这样的大学固然好,但并不是每一个走进北大的学生就必然成功。我看到了很多北大的学生,进了北大就不学习了;看到很多北大的学生,由于学习压力非常重,心理很有问题;也看到了一些北大的学生,在大学毕业以后无所事事。当然,我想清华等这样的学校也有这样的情况。但是我看到很多二本三本的学生,他们在经过了自己全力以赴的努力以后,研究生就考上了北大、清华或者是进入了世界名牌大学。
我认识的一个朋友,中专毕业以后,经过了一段时间的工作,他发现中专学历远远不够。他之所以上中专,不是因为他笨,而是因为他的家庭条件实在太差。在当时那个年代,应该是接近30年以前,上中专一般都是师范学院,而师范学院是不需要交任何费用的,所以他只能选择中专。工作以后,发现这是远远不够的。后来就开始努力自学,上了大专。考上以后,他觉得大专还是不够。现在一般来说要学到本科才能考研究生,但那时只要是大专毕业了就可以考研究生。所以,大专毕业之后,他下定决心要考研究生,而且要考就考最好的学校。所以,最后目标锁定在北大。他辞掉了工作,在北大外面租了一间房子,努力自学了三年,最后终于考上了北京大学政治系的研究生。北大毕业以后,成了公务员,进入了北京非常好的一个中央单位工作。在中央单位工作的时候,觉得自己一杯开水、一张报纸这样的日子不是自己想要奋斗的目标,所以业余时间就来新东方学托福、学GRE,目标是要到世界名牌大学读书。在新东方学了差不多两年,把这两门考试考过去了,最后通过努力,进入了哈佛大学肯尼迪政治学院。毕业以后,在国外工作了一段时间,刚好遇到中国政府希望到国外招聘一些在国外毕业后想回到中国工作的机会。回来以后,很快进入了中国的厅局级管理干部的行列。由于他的志向,由于他的努力,由于他中西方文化结合的背景,所以很快变成了中国的比较重要的管理干部之一。
有无数的中专生就是以中专生结束了自己的一辈子。但是我们有可以看到,有一个中专生可以奋斗到哈佛大学的毕业生,这就是一路奋斗的历程。我们常常说,名牌大学的人好像有一些更加硬性的条件,但我刚才也说过了,并不是每一个名牌大学的人都能成功。
我跟马云有很多相似之处。马云高考考了三年,我也考了三年;马云考的是英语专业,我也考的是英语专业;三年以后,我考上了北京大学,他考上了杭州师范学院。大家都知道,这是一所大家都没听说过的学校。如果你现在曾经听说过这个学校,一定是因为先听说了马云,才听说了这所学校。我跟马云到今天为止还有很多相似之处,我们两个人都可以用英文做报告,我们两个人到今天为止依然保持着自己的学士学位。也就是说,我们的最高学历是学士。但是大家可以看到,学校和学位不能阻挡一个人的成长。我曾经认为我比马云要做得更好一点儿,因为我毕竟是北大的。但是,大家都知道,马云一个人做出了我10个人可能都做不出的事情。我做了近20年只做出一个新东方,马云真正的创业(阿里巴巴)是1999年开始的,也就是比我做得还要晚。但是他现在除了阿里巴巴以外,有支付宝、有淘宝网。如果支付宝和淘宝网再上市的话,这两个公司的市值将是上百亿美金左右。
所以大家可以看到,一个人的成功跟你所上的学校没有必然的联系,跟你内心的冲动有关系,跟你内心的渴望有关系。所以我常常说,一个人可以过贫困的生活,一个人可以过孤独的生活,但是一个人不能过内心没有火焰的生活,一个人不能过内心没有渴望和向往的生活。我说的这些渴望和向往,不是指你每天渴望吃一顿饭,不是说你每天渴望喝两瓶啤酒,不是说渴望每天要交几个女朋友或者男朋友,尽管你可以有这些渴望,但是所有这些渴望应该放在你更大的渴望之上。这份渴望,就是渴望自己能够变得伟大,渴望自己能够变得成功,渴望自己能够变得有影响力,渴望自己能够养活自己、养活家庭,渴望自己为这个社会做贡献。这种渴望是你走向未来的强大动力。
一个人就像一个植物一样,如果内心没有长大的种子,你永远长不大。这是我在中央电视台说过的著名的树和草的比喻。如果你内心只是草的种子,你就是草;如果你内心是树的种子,你必然会长成树。在人的心里,树的种子和草的种子是可以变换的,不像自然界,让松树的种子变成杨树是不太容易的,让草的种子变成松树也是不可能的。但是,人是可变的,人的改变往往是一瞬间的事情。只要你内心想要把自己变得崇高、变得伟大,你就能改变。所以,首先我们要求在座的同学都要做到一点,就是要有一个渴望自己成长的种子。
人的成长有两种:一种叫做自然成长;另一种叫做心灵的成长。我们在座的所有同学都可以自然地成长。你完全可以预料到你18岁到30岁会是怎么样,30岁到40岁怎么样,到50岁怎么样。现在如果经过电脑的精确计算,你能够精确地看到90岁长成什么样。我曾经输入过我的头像,发现90岁是一个干瘪的、头发花白、满脸皱纹的,但充满智慧的老头形象。我相信我这个人可能一辈子什么都会丢掉,但是有一点肯定不会丢,就是我对生活的渴望和对自己创造的渴望。在我的生命中,杨振宁教授一直是我学习榜样。杨振宁教授今年已接近90岁的生命,还在不断地到处做演讲,指导年轻的科学家。人是一种可以不断地燃烧,可以源源不断地发现自己的能量,可以不断地产生燃气的这样一种动物。你只要想烧,永远是烧不完的。 大家有没有发现一个现象:只有懒惰的人身体才会不好,而勤奋、有理想的人往往身体会不断地好起来。像年纪大的人中间,那些勤劳的人往往很少得老年痴呆症,而那些不需要干活的人常常会得老年痴呆症。为什么?他不再行动,不再动脑子。从这个意义上来说,人像动物一样,是要干活的。任何一个动物,如果失去了捕食的能力,就会被饿死。所以,你可以看到在非洲草原上被活活饿死的狮子。为什么?因为它失去了捕食能力。
我们可以预料自己活多少岁,甚至可以预料我们的长相是什么样的。但是,请在座的同学想一想,你能预料你30岁能获得什么成就吗?你能预料你40岁获得什么成就吗?你能预料你80岁获得什么成就吗?你预料不到。人只有这一点没法预料,你永远没法预料你的潜力。但是,你的潜力在什么地方?在你的心里面。我从来没有预料到今天我所做的一切事情是我能够做出来的。今天我能做出一点儿事情来,是因为我对生命有一种内在的渴望和向往。
我的家在长江边上,从小坐在长江边看着太阳从东方升起,从西方落下,看着船来船往,我就产生了一种渴望。这种渴望后来我总结了一句话,叫做穿越地平线走向未来的渴望,就是走向远方。生命中有榜样也是非常重要的,在我的生命中有一个家乡的榜样,他的家就在我的隔壁,这个人的名字大家都知道,叫徐霞客。我们从小就听徐霞客的故事,给我带来的一种感觉是,如果说一个榜样离你很远,你可能会把他当作神。比如说,我让你把丘吉尔、毛泽东、秦始皇、刘邦、曹雪芹、鲁迅当作榜样,你觉得他们离你很远。但是,如果就住在鲁迅的三昧书屋边上长大的,你就可能觉得鲁迅离你很近。所以,我从小就有这样一个感觉:如果徐霞客在400多年前就能够走遍中国的山山水水,把自己走成一个伟大的人物,那为什么我不能?所以,榜样的力量是无穷的。我从小有一个一般农村的孩子不会产生的眼界,就是我希望自己能够走遍中国的山山水水。
人最大的痛苦是什么?就是你有了一个更加容易的选择,往往就会往更加容易的选择上去走。更加容易的选择往往导致你降低自己的人生目标和标准。当初如果有农民工的话,我就不会那么辛苦地去考大学,因为考大学肯定比当农民工更加难。但是,当你发现一个更加难的事情通过自己的努力也能达到,更加难的目标就值得你去努力。
人要有一个向往。我当时的这种向往就是希望自己能够走出去。这样的向往,使我最后能够走进北大。我连续三年高考。第一年高考,英语考了33分,连中专都没有录取。;第二年英语考了55分,也是连中专都没录取;但是,由于第三年的努力,我很多门课都考到了90多分,其中最突出的一门成绩(除了英语)就是地理,地理当时满分100分,我考了97分,如果没有徐霞客这么伟大的地理学家的影子,我不会对地理如此感兴趣。到今天为止,中国的前几百个城市在什么地方,只要把城市名称说出来,我就可以在地图上几乎毫无悬念地标注出来。确实,一个梦想可以催生你的一片生命。我已经充分意识到,现在走遍中国是不够的,必须走遍世界。因为这个世界上有太多的精彩等待你去探索,有太多的地方等待你去寻找。也是因为出于这样的目标,在新东方在中国上市还是美国上市的时候,我毫不犹豫地选择了新东方必须到美国去上市,不是说因为我喜欢美国,而是因为我知道,走向了美国纽约证券交易所,新东方就走向了世界,它就会把新东方带向一个世界的平台。
同学们,你的未来的潜力是无限的。你不要想你现在到底有没有能力。我有一句话,叫做不要用你的现在去判断你的未来,因为你的未来不可判断,你要去努力。我常常听到同学说,俞老师,人是有命运的。他的命就好,没有办法。生在有钱人家里,什么资源都有,大学一毕业的时候就给大把的钱创业,而且天资聪明,一创业就成功。你说我们这些人怎么比?确实是,表面上看是没法比的,短时间也是没法比的。但是,从长时间来说,一个人拥有的资源并不能决定他一辈子必然成功。我们假想有一些人一辈子就可以躺在这个资源上睡大觉,但我们看到更多的是不拥有资源的人,最后走向了拥有资源的道路。像我刚才说的马云,一个普通工人家庭的孩子,他的父亲是拉三轮车的;就像我,普通农民家庭的孩子,我的父母是不认字的。但是今天,毫不夸张地说,我们拥有了一部分中国的社会资源和企业资源。当然,我们尽可能利用这个资源为更多的人服务。
我们刚才讲到一个人的社会资源问题时常常讲到命运,有同学说命运是定的。命运会不会定?有一部分是定的。我刚才说了,你出生在什么样的家庭,长成什么样子,这些是定的。除此之外,其他的是可变的。所以,大家要充分地关注可变的命运,而不是关注定下来的命运。什么叫可变的?我们把人的运气分成两种运气:一种叫偶然的,一种叫必然的。一个人如果寻求偶然的运气,生命常常就会比较悲惨;但一个人寻求必然的运气,生命常常会显得比较光辉灿烂。什么叫偶然的运气?守株待兔这个故事大家都知道了,农民看到一只兔子撞到树桩上,他很高兴地捡起来,他推断的结果是每天都应该有一个兔子撞到这个树桩上。所以从此他不干活了,就等着兔子来撞。等了一辈子,树桩等烂了,头等白了,但是兔子依然没来。他把偶然的运气,当成了必然的运气。什么是必然的运气?如果农夫推断这个地方有动物,就积极把自己变成一个猎人,他可能一辈子不一定只打到兔子,也有可能是打到老虎。大家知道主动出击和被动生存有天壤之别。一个人也许吃苦的命不能改变,但是命的层次可以改变。我怎么后来会站到这个地方?是因为通过自己一辈子的努力,一次一次的失败不罢休,一次一次挫折不罢休。
我常常喜欢讲两个故事,人的心的变化带来命的变化。有一个人考状元,路上碰到一个老和尚,问他要干什么,他说考状元。老和尚看了一下他的面相,说你不要去考了,你一辈子都不会有状元的命,你还是老老实实回去吧。但已经走到半道了,他不甘心,就继续往前走。走到一条河边上,突然发现有一个人落水,他就跳到河里救这个人,衣服湿了,他没办法就又跑回到庙里。老和尚这时候见到他说,奇怪了,你出去了两个小时再回来,你的命变了。你好像脸上已经有了考上状元的脸色了。因为这个人心生了善念。原来这个人很自私,这次一瞬间生了善心,把人救起来了,所以命就改变了。这好像是一个编出来的故事,但是我很相信,原因是什么?原因是你的心变了,你的世界就会改变,所以你的命运改变了。我觉得努力加勤奋和正确的志向和目标,是我们走向未来的唯一道路。
大学期间到底应该做一些什么事情?第一个事情就是要认真学习。在大学的认真学习跟中学认真学习是不一样的,大学是扩展自己的眼光、扩展自己人生的学习。我说的学习就是要重视大学的专业知识,我在北大不学好英语,哪有可能我做今天的新东方,所以专业知识是非常重要的。专业如果不喜欢,要学一个你喜欢的专业。你喜欢的专业是不是真喜欢,要经过反复琢磨。美国大学前两年不让你选专业,是让你用两年时间广泛地培养兴趣。朋友们记住了,如果你一辈子在做自己不喜欢的专业,这是可悲的事情。所以,一定要寻找自己喜欢的专业。如果专业换不了,就找第二个专业学;如果大学允许你换专业,你要想清楚了再换。把最重要的知识学好,你可以在大学的时候争取学两个专业。
我们在大学做过调研,换过专业的同学应该百分之百地喜欢自己的专业,这应该是一个正常的推论。但是,有些同学换过了专业还是不喜欢自己选择的专业,表明有些同学换专业是一个鲁莽的行为没有经过认真的思考。除了专业以外,业余时间还要读大量的书籍,每两天左右就应该读一本书。我在大学的时候读了差不多800本书,我能读完,你就能读完。有的同学说,读过书忘了怎么办?你要记住,读过了忘了和没有读过是两个概念。你看周围的同学读了书,这些书你没读过,你心里马上产生害怕的感觉。所以读书不光是为了智慧,读书不光是为了知识的扩展,读书还有奠定自信的基础。如果我没有在北大建立起读书的自信,我就没有自信出来干新东方。所以读书是奠定自信的基础。
在大学要做的第二件事情就是要把中学的活动拓展过来。人生最重要的是占先机,在大学时候能够参加各种各样的活动是非常重要的,我发现在大学活跃的同学比不活跃的同学未来的发展是有很大差别的。大家在大学里要多交朋友,请朋友们记住,当你跟更厉害的人打交道的时候你进步更快。我从王强老师那儿学到了读书,他一进大学就把自己的生活费一分为二,一半买书、一半当生活费,所以他每个月都要买很多书。我跟他学,他买什么书我就买什么书。大家记住了,在大学交朋友要尽可能交好的。
在大学的另外一件事情就是要照顾所有同学的情绪,尽可能为其他同学服务。我们在大学中发现两种同学:一种同学只关注自己的成绩、自己的利益、自己如何在竞争中取胜,不关注别人的。这种心态养成以后,一般在社会上会被打得落花流水,因为这个社会上不会接纳只为自己争取利益的人。所以,在大学的时候要学会关注别人,把好事尽可能地留给别人,坏事尽可能地留给自己,这样你得到同学的信任,将来你有事情的时候,就会有人帮助你。我在大学的时候,坚持4年打水、宿舍扫地。我在做新东方的时候找大学同学帮忙,他们都愿意帮我。因为他们觉得我在大学是一个不错的人,是一个愿意帮助人的人,所以,这样就形成了一个大学同学的团队一起干新东方。我今天的交往圈已经非常非常广泛了,但是我最好的朋友依然是大学的同学。
在大学,我们要做的另外一个事情就是尽可能地在感情上有所收获。我说的不仅仅是友情,还有男女之间的感情。在大学如果有机会能够谈一次恋爱,那也是非常好的收获。我在大学就没有女孩子跟我谈,你们如果有这样的机会,还是要抓住机会的。当然,不是为了谈恋爱而谈恋爱。一定要真正的、刻骨铭心地爱上对方,这样才能谈。因为,只有真诚才能真正的感受,才能带来真正的成长。如果真的彼此相爱,要爱得一心一意。我说的一心一意不是在大学只能谈一次恋爱,而是谈的时候只能谈一个。因为一个真正有归属的感情是在一段时间内心无旁鹜地、深深地爱着另外一个人的感觉。如果你真正爱上了,你也要爱得大度。我说的大度,不是让你把男朋友或者女朋友送给别人,而是在大学里面人才济济,今天爱上你,明天有可能爱上了别人。有的时候爱情会出现比较特殊的现象,在大学的时候我们班就发生过这样的事情,两个男学生是哥们,其中有一个男生有一个女朋友,大家一起玩儿,结果玩着玩着另外那两个人玩到一起去了,把这个男生搁到一边了。大家知道,爱情最幸福的是两个人同时相爱或者是两个人同时不爱了。爱情最痛苦的是什么?你还深深地爱着对方,对方已经不爱你了,而你爱对方的心怎么也放不下来。去年,某大学里有两个人谈恋爱,后来这个女生不爱这个男生了,这个男生还深深爱着这个女生。这个男生怎么也过不了这关,最后男生跑到女生宿舍里,把女生从窗户推下去,然后自己也跳下去了。这是一个悲惨的爱情故事,但是又是一个卑鄙的爱情故事。这个卑鄙在于这个男生的卑鄙,如果你真心爱着对方的话,就必须一路祝福他们,让他们走好,而不是去伤害他们。所以,如果说当我发现这两个人谈了恋爱的话,那我一定祝福他们,让他们一路走好吧,直到走到离婚为止。你不能说把自己的生命跟别人的生命同时消灭掉,我们在座的同学,一定会碰到这样的爱情和痛苦,也一定要用大度的方式去解决这种痛苦。
如果在大学里面没人爱你怎么办?也就是说,大学不一定每个人都要谈恋爱,也不一定每个人有机会谈恋爱。就算你想谈,但没有任何人跟你谈恋爱。我的第一次恋爱也是最后一次恋爱,是我在大学毕业两年以后25岁的时候,在北大的校园里找到我的女朋友,后来变成了我的老婆、我孩子的妈妈。也就是说,同学们记住了,即使是迟到的爱情,那也是真正的爱情。如果说今天没有爱情,你就等待。就像今天你没有成功,你就等待。在等待中去寻找,在等待中去努力,在等待中去相信自己未来总有一天,你能够走向成功,走向辉煌。今天咱们的题目就叫做“相信未来”。“相信未来”是中国著名诗人食指写的一首诗。请同学们一定相信,不管今天你的环境如何,不管今天你身处何地,只要你心中真正有生命热情,只要你相信你的未来总有一天会变得更加美好,只要你相信努力和奋斗的力量,你一定会有美好的未来。
谢谢大家!
转载自 新东方腾讯博客:http://user.qzone.qq.com/622005005/blog/1315044802
posted @
2011-09-16 14:15 David1228 阅读(424) |
评论 (0) |
编辑 收藏
转载自
http://chorpin.iteye.com/blog/157992 http://www.quartz-scheduler.org/documentation
7.3.2 使用Quartz调度器
Quartz调度器为调度工作提供了更丰富的支持。和Java定时器一样,可以使用Quartz来每隔多少毫秒执行一个工作。但Quartz比Java Timer更先进之处在于它允许你调度一个工作在某个特定的时间或日期执行。
关于Quartz的更多信息,可以访问Quartz位于http://www.opensymphony.com/quartz的主页。
让我们从定义发送报表邮件的工作开始使用Quartz:
创建一个工作
定义Quartz工作的第一步是创建一个类来定义工作。要做到这一点,你需要从Spring的QuartzJobBean中派生子类,如程序清单7.3所示:
程序清单7.3 定义一个Quartz工作
public class EmailReportJob extends QuartzJobBean {
public EmailReportJob() {}
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
courseService.sendCourseEnrollmentReport();
}
private CourseService courseService;
public void setCourseService(CourseService courseService) {
this.courseService = courseService;
}
}
QuartzJobBean是Quartz中与Java的TimerTask等价的类。它实现了org.quartz.Job接口。executeInternal()方法定义了当预定的时刻来临时应该执行哪些动作。在这里,正如EmailReportTask,你只是简单地调用了courseService属性的sendCourseEnrollmentReport()方法。
在Spring配置文件中按以下方式声明这个工作:
<bean id="reportJob"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>com.springinaction.training.
schedule.EmailReportJob</value>
</property>
<property name="jobDataAsMap">
<map>
<entry key="courseService">
<ref bean="courseService"/>
</entry>
</map>
</property>
</bean>
值得注意的是,在这里你并没有直接声明一个EmailReportJob Bean,而是声明了一个JobDetailBean。这是使用Quartz时的一个特点。JobDetailBean是Quartz的org.quartz.JobDetail的子类,它要求通过jobClass属性来设置一个Job对象。
使用Quartz的JobDetail中的另一个特别之处是EmailReportJob的courseService属性是间接设置的。JobDetail的jobDataAsMap属性接受一个java.util.Map,其中包含了需要设置给jobClass的各种属性。在这里,这个map包含了一个指向courseService Bean的引用,它的键值为courseService。当JobDetailBean实例化时,它会将courseService Bean注入到EmailReportJob的courseService属性中。
调度工作
现在工作已经被定义好了,接下来你需要调度这个工作。Quartz的org.quartz.Trigger类描述了何时及以怎样的频度运行一个Quartz工作。Spring提供了两个触发器,SimpleTriggerBean和CronTriggerBean。你应该使用哪个触发器?让我们分别考察一下这两个触发器,首先从SimpleTriggerBean开始。
SimpleTriggerBean与ScheduledTimerTask类似。你可以用它来指定一个工作应该以怎样的频度运行,以及(可选地)在第一次运行工作之前应该等待多久。例如,要调度报表工作每24小时运行一次,第一次在1小时之后开始运行,可以按照以下方式进行声明:
<bean id="simpleReportTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail">
<ref bean="reportJob"/>
</property>
<property name="startDelay">
<value>3600000</value>
</property>
<property name="repeatInterval">
<value>86400000</value>
</property>
</bean>
属性jobDetail装配了将要被调度的工作,在这个例子中是reportJob Bean。属性repeatInterval告诉触发器以怎样的频度运行这个工作(以毫秒作为单位)。这里,我们设置它为86400000,因此每隔24小时它会被触发一次。你也可以选择设置startDelay属性来延迟工作的第一次执行。我们设置它为3600000,因此在第一次触发之前它会等待1小时。
调度一个cron工作
尽管你可能认为SimpleTriggerBean适用于大多数应用,但它仍然不能满足发送注册报表邮件的需求。正如ScheduledTimerTask,你只能指定工作执行的频度,而不能准确指定它于何时运行。因此,你无法使用SimpleTriggerBean在每天早晨6:00给课程主任发送注册报表邮件。
然而,CronTriggerBean允许你更精确地控制任务的运行时间。如果你对Unix的cron工具很熟悉,则会觉得CronTriggerBean很亲切。你不是定义工作的执行频度,而是指定工作的准确运行时间(和日期)。例如,要在每天早上6:00运行报表工作,可以按照以下方式声明一个CronTriggerBean:
<bean id="cronReportTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="reportJob"/>
</property>
<property name="cronExpression">
<value>0 0 6 * * ?</value>
</property>
</bean>
和SimpleTriggerBean一样,jobDetail属性告诉触发器调度哪个工作。这里我们又一次装配了一个reportJob Bean。属性cronExpression告诉触发器何时触发。如果你不熟悉cron,这个属性可能看上去有点神秘,因此让我们进一步考察一下这个属性。
一个cron表达式有至少6个(也可能是7个)由空格分隔的时间元素。从左至右,这些元素的定义如下:
1.秒(0–59)
2.分钟(0–59)
3.小时(0–23)
4.月份中的日期(1–31)
5.月份(1–12或JAN–DEC)
6.星期中的日期(1–7或SUN–SAT)
7.年份(1970–2099)
每一个元素都可以显式地规定一个值(如6),一个区间(如9-12),一个列表(如9,11,13)或一个通配符(如*)。“月份中的日期”和“星期中的日期”这两个元素是互斥的,因此应该通过设置一个问号(?)来表明你不想设置的那个字段。表7.1中显示了一些cron表达式的例子和它们的意义:
表7.1 一些cron表达式的例子
表 达 式
意 义
0 0 10,14,16 * * ?
每天上午10点,下午2点和下午4点
0 0,15,30,45 * 1-10 * ?
每月前10天每隔15分钟
30 0 0 1 1 ? 2012
在2012年1月1日午夜过30秒时
0 0 8-5 ? * MON-FRI
每个工作日的工作时间
对于cronReportTrigger,我们设置cronExpression为0 0 6 * * ?可以把它读作“在任何月份任何日期(不管是星期几)的6时0分0秒执行触发器。”换句话说,这个触发器会在每天早晨6:00执行。
使用CronTriggerBean完全能够满足课程主任的期望了。现在剩下要做的只是启动这个工作了。
启动工作
Spring的SchedulerFactoryBean是Quartz中与TimerFactoryBean等价的类。按照如下方式在Spring配置文件中声明它:
<bean class="org.springframework.scheduling.
quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronReportTrigger"/>
</list>
</property>
</bean>
属性triggers接受一组触发器。由于目前只有一个触发器,因此只需简单地装配一个包含cronReportTrigger Bean的一个引用的列表即可。
现在,你已经实现了调度发送注册报表邮件的需求。但在这个过程中,你做了一些额外的工作。在开始新的话题之前,首先让我们看一下如何通过更简单一些的方式调度报表邮件。
示例配置:
<beans>
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<!--ref local="SocketJobTrigger"/>
<ref local="RouteJobTrigger"/-->
</list>
</property>
</bean>
<!---->
<bean id="SocketJobTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail">
<ref bean="SocketJobDetail"/>
</property>
<property name="startDelay">
<value>10000</value>
</property>
<property name="repeatInterval">
<!-- repeat every 2 minutes -->
<value>120000</value>
</property>
</bean>
<bean id="SocketJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<ref local="quartzManager"/>
</property>
<property name="targetMethod">
<value>useQuartz</value>
</property>
</bean>
<bean id="socketManager" class="com.lxh.bean.quartzManager">
</bean>
<!---->
<bean id="RouteJobTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail">
<ref bean="RouteJobDetail"/>
</property>
<property name="startDelay">
<value>30000</value>
</property>
<property name="repeatInterval">
<value>30000</value>
</property>
</bean>
<bean id="RouteJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<ref local="otherManager"/>
</property>
<property name="targetMethod">
<value>otherQuartz</value>
</property>
</bean>
<bean id="routeManager" class="com.lxh.job.otherManager">
</bean>
</beans>
posted @
2011-09-14 10:19 David1228 阅读(712) |
评论 (0) |
编辑 收藏
==========amazon
亚马逊的弹性计算云
亚马逊是互联网上最大的在线零售商,但是同时也为独立开发人员以及开发商提供云计算服务平台。亚马逊将他们的云计算平台称为弹性计算云(Elastic Compute Cloud,EC2),它是最早提供远程云计算平台服务的公司。
开放的服务
与 Google提供的云计算服务不同,Google仅为自己在互联网上的应用提供云计算平台,独立开发商或者开发人员无法在这个平台上工作,因此只能转而通 过开源的Hadoop软件支持来开发云计算应用。亚马逊的弹性计算云服务也和IBM的云计算服务平台不一样,亚马逊不销售物理的云计算服务平台,没有类似 于“蓝云”一样的计算平台。亚马逊将自己的弹性计算云建立在公司内部的大规模集群计算的平台之上,而用户可以通过弹性计算云的网络界面去操作在云计算平台 上运行的各个实例(Instance),而付费方式则由用户的使用状况决定,即用户仅需要为自己所使用的计算平台实例付费,运行结束后计费也随之结束。
弹 性计算云从沿革上来看,并不是亚马逊公司推出的第一项这种服务,它由名为亚马逊网络服务的现有平台发展而来。早在2006年3月,亚马逊就发布了简单存储 服务(Simple Storage Service,S3),这种存储服务按照每个月类似租金的形式进行服务付费,同时用户还需要为相应的网络流量进行付费。亚马逊网络服务平台使用REST (Representational State Transfer)和简单对象访问协议(SOAP)等标准接口,用户可以通过这些接口访问到相应的存储服务。
2007年7月,亚马逊公司 推出了简单队列服务(Simple Queue Service,SQS),这项服务使托管主机可以存储计算机之间发送的消息。通过这一项服务,应用程序编写人员可以在分布式程序之间进行数据传递,而无 须考虑消息丢失的问题。通过这种服务方式,即使消息的接收方还没有模块启动也没有关系。服务内部会缓存相应的消息,而一旦有消息接收组件被启动运行,则队 列服务将消息提交给相应的运行模块进行处理。同样的,用户必须为这种消息传递服务进行付费使用,计费的规则与存储计费规则类似,依据消息的个数以及消息传 递的大小进行收费。
在亚马逊提供上述服务的时候,并没有从头开始开发相应的网络服务组件,而是对公司已有的平台进行优化和改造,一方面满足了本身网络零售购物应用程序的需求,另一方面也供外部开发人员使用。
在开放了上述的服务接口之后,亚马逊公司进一步在此基础上开发了EC2系统,并且开放给外部开发人员使用。
灵活的工作模式
亚马逊的云计算模式沿袭了简单易用的传统,并且建立在亚马逊公司现有的云计算基础平台之上。弹性计算云用户使用客户端通过 SOAP over HTTPS协议来实现与亚马逊弹性计算云内部的实例进行交互。使用HTTPS协议的原因是为了保证远端连接的安全性,避免用户数据在传输的过程中造成泄 露。因此,从使用模式上来说,弹性计算云平台为用户或者开发人员提供了一个虚拟的集群环境,使得用户的应用具有充分的灵活性,同时也减轻了云计算平台拥有 者(亚马逊公司)的管理负担。
而弹性计算云中的实例是一些真正在运行中的虚拟机服务器,每一个实例代表一个运行中的虚拟机。对于提供给某 一个用户的虚拟机,该用户具有完整的访问权限,包括针对此虚拟机的管理员用户权限。虚拟服务器的收费也是根据虚拟机的能力进行计算的,因此,实际上用户租 用的是虚拟的计算能力,简化了计费方式。在弹性计算云中,提供了三种不同能力的虚拟机实例,具有不同的收费价格。例如,其中默认的也是最小的运行实例是 1.7GB的内存,1个EC2的计算单元(1虚拟的计算核以相关的计算单元),160GB的虚拟机内部存储容量,是一个32位的计算平台,收费标准为每个 小时10美分。在当前的蓝计算平台中,还有两种性能更加强劲的虚拟机实例可供使用,当然价格也更加昂贵一点。
由于用户在部署网络程序的时 候,一般会使用超过一个运行实例,需要很多个实例共同工作。弹性计算云的内部也架设了实例之间的内部网络,使得用户的应用程序在不同的实例之间可以通信。 在弹性计算云中的每一个计算实例都具有一个内部的IP地址,用户程序可以使用内部IP地址进行数据通信,以获得数据通信的最好性能。每一个实例也具有外部 的地址,用户可以将分配给自己的弹性IP地址分配给自己的运行实例,使得建立在弹性计算云上的服务系统能够为外部提供服务。当然,亚马逊公司也对网络上的 服务流量计费,计费规则也按照内部传输以及外部传输进行分开。
总而言之,亚马逊通过提供弹性计算云,减少了小规模软件开发人员对于集群系 统的维护,并且收费方式相对简单明了,用户使用多少资源,只需要为这一部分资源付费即可。这种付费方式与传统的主机托管模式不同。传统的主机托管模式让用 户将主机放入到托管公司,用户一般需要根据最大或者计划的容量进行付费,而不是根据使用情况进行付费,而且,可能还需要保证服务的可靠性、可用性等,付出 的费用更多,而很多时候,服务并没有进行满额资源使用。而根据亚马逊的模式,用户只需要为实际使用情况付费即可。
在用户使用模式上,亚马 逊的弹性计算云要求用户要创建基于亚马逊规格的服务器映像(名为亚马逊机器映像即亚马逊 Machine Image, AMI)。弹性计算云的目标是服务器映像能够拥有用户想要的任何一种操作系统、应用程序、配置、登录和安全机制,但是当前情况下,它只支持Linux内 核。通过创建自己的AMI,或者使用亚马逊预先为用户提供的AMI,用户在完成这一步骤后将AMI上传到弹性计算云平台,然后调用亚马逊的应用编程接口 (API),对AMI进行使用与管理。AMI实际上就是虚拟机的映像,用户可以使用它们来完成任何工作,例如运行数据库服务器,构建快速网络下载的平台, 提供外部搜索服务甚至可以出租自己具有特色的AMI而获得收益。用户所拥有的多个AMI可以通过通信而彼此合作,就像当前的集群计算服务平台一样。
在 弹性计算云的将来发展过程中,亚马逊也规划了如何在云计算平台之上帮助用户开发Web 2.0的应用程序。亚马逊认为除了它所依赖的网络零售业务之外,云计算也是亚马逊公司的核心价值所在。可以预见,在将来的发展过程中,亚马逊必然会在弹性 计算云的平台上添加更多的网络服务组件模块,为用户构建云计算应用提供方便。
========google
Google的云计算平台与应用
Google的云计算技术实际上是针对Google特定的网络应用程序而定制的。针对内部网络数据规模超大的特点,Google提出了一整套基于分布式并行集群方式的基础架构,利用软件的能力来处理集群中经常发生的节点失效问题。
从 2003年开始,Google连续几年在计算机系统研究领域的最顶级会议与杂志上发表论文,揭示其内部的分布式数据处理方法,向外界展示其使用的云计算核 心技术。从其近几年发表的论文来看,Google使用的云计算基础架构模式包括四个相互独立又紧密结合在一起的系统。包括Google建立在集群之上的文 件系统Google File System,针对Google应用程序的特点提出的Map/Reduce编程模式,分布式的锁机制Chubby以及Google开发的模型简化的大规模 分布式数据库BigTable。
Google File System 文件系统
为了满足Google迅速增长的数据处 理需求,Google设计并实现了Google文件系统(GFS,Google File System)。GFS与过去的分布式文件系统拥有许多相同的目标,例如性能、可伸缩性、可靠性以及可用性。然而,它的设计还受到Google应用负载和 技术环境的影响。主要体现在以下四个方面:
1. 集群中的节点失效是一种常态,而不是一种异常。由于参与运算与处理的节点数目非常庞大,通常会使用上千个节点进行共同计算,因此,每时每刻总会有节点处在失效状态。需要通过软件程序模块,监视系统的动态运行状况,侦测错误,并且将容错以及自动恢复系统集成在系统中。
2. Google系统中的文件大小与通常文件系统中的文件大小概念不一样,文件大小通常以G字节计。另外文件系统中的文件含义与通常文件不同,一个大文件可能包含大量数目的通常意义上的小文件。所以,设计预期和参数,例如I/O操作和块尺寸都要重新考虑。
3. Google文件系统中的文件读写模式和传统的文件系统不同。在Google应用(如搜索)中对大部分文件的修改,不是覆盖原有数据,而是在文件尾追加新 数据。对文件的随机写是几乎不存在的。对于这类巨大文件的访问模式,客户端对数据块缓存失去了意义,追加操作成为性能优化和原子性(把一个事务看做是一个 程序。它要么被完整地执行,要么完全不执行)保证的焦点。
4. 文件系统的某些具体操作不再透明,而且需要应用程序的协助完成,应用程序和文件系统API的协同设计提高了整个系统的灵活性。例如,放松了对GFS一致性 模型的要求,这样不用加重应用程序的负担,就大大简化了文件系统的设计。还引入了原子性的追加操作,这样多个客户端同时进行追加的时候,就不需要额外的同 步操作了。
总之,GFS是为Google应用程序本身而设计的。据称,Google已经部署了许多GFS集群。有的集群拥有超过1000个存储节点,超过300T的硬盘空间,被不同机器上的数百个客户端连续不断地频繁访问着。
图 1给出了Google File System的系统架构,一个GFS集群包含一个主服务器和多个块服务器,被多个客户端访问。文件被分割成固定尺寸的块。在每个块创建的时候,服务器分配 给它一个不变的、全球惟一的64位块句柄对它进行标识。块服务器把块作为linux文件保存在本地硬盘上,并根据指定的块句柄和字节范围来读写块数据。为 了保证可靠性,每个块都会复制到多个块服务器上,缺省保存三个备份。主服务器管理文件系统所有的元数据,包括名字空间、访问控制信息和文件到块的映射信 息,以及块当前所在的位置。GFS客户端代码被嵌入到每个程序里,它实现了Google文件系统 API,帮助应用程序与主服务器和块服务器通信,对数据进行读写。客户端跟主服务器交互进行元数据操作,但是所有的数据操作的通信都是直接和块服务器进行 的。客户端提供的访问接口类似于POSIX接口,但有一定的修改,并不完全兼容POSIX标准。通过服务器端和客户端的联合设计,Google File System能够针对它本身的应用获得最大的性能以及可用性效果。
MapReduce分布式编程环境
为了让内部非分布式系统方向背景的员工能够有机会将应用程序建立在大规模的集群基础之上,Google 还设计并实现了一套大规模数据处理的编程规范Map/Reduce系统。这样,非分布式专业的程序编写人员也能够为大规模的集群编写应用程序而不用去顾虑 集群的可靠性、可扩展性等问题。应用程序编写人员只需要将精力放在应用程序本身,而关于集群的处理问题则交由平台来处理。
Map/Reduce通过“Map(映射)”和“Reduce(化简)”这样两个简单的概念来参加运算,用户只需要提供自己的Map函数以及Reduce函数就可以在集群上进行大规模的分布式数据处理。
据称,Google的文本索引方法,即搜索引擎的核心部分,已经通过Map Reduce的方法进行了改写,获得了更加清晰的程序架构。在Google内部,每天有上千个Map Reduce的应用程序在运行。
分布式大规模数据库管理系统BigTable
构 建于上述两项基础之上的第三个云计算平台就是Google关于将数据库系统扩展到分布式平台上的BigTable系统。很多应用程序对于数据的组织还是非 常有规则的。一般来说,数据库对于处理格式化的数据还是非常方便的,但是由于关系数据库很强的一致性要求,很难将其扩展到很大的规模。为了处理 Google内部大量的格式化以及半格式化数据,Google构建了弱一致性要求的大规模数据库系统BigTable。据称,现在有很多Google的应 用程序建立在BigTable之上,例如Search History、Maps、Orkut和RSS阅读器等。
图2给出了在BigTable模型中的数据模型。数据模型包括行列以及相应的时间戳,所有的数据都存放在表格中的单元里。BigTable的内容按照行来划分,将多个行组成一个小表,保存到某一个服务器节点中。这一个小表就被称为Tablet。
以上是Google内部云计算基础平台的三个主要部分,除了这三个部分之外,Google还建立了分布式程序的调度器,分布式的锁服务等一系列相关的云计算服务平台。
Google的云应用
除 了上述的云计算基础设施之外,Google还在其云计算基础设施之上建立了一系列新型网络应用程序。由于借鉴了异步网络数据传输的Web 2.0技术,这些应用程序给予用户全新的界面感受以及更加强大的多用户交互能力。其中典型的Google云计算应用程序就是Google推出的与 Microsoft Office软件进行竞争的Docs网络服务程序。Google Docs是一个基于Web的工具,它有跟Microsoft Office相近的编辑界面,有一套简单易用的文档权限管理,而且它还记录下所有用户对文档所做的修改。Google Docs的这些功能令它非常适用于网上共享与协作编辑文档。Google Docs甚至可以用于监控责任清晰、目标明确的项目进度。当前,Google Docs已经推出了文档编辑、电子表格、幻灯片演示、日程管理等多个功能的编辑模块,能够替代Microsoft Office相应的一部分功能。值得注意的是,通过这种云计算方式形成的应用程序非常适合于多个用户进行共享以及协同编辑,为一个小组的人员进行共同创作 带来很大的方便性。
Google Docs是云计算的一种重要应用,即可以通过浏览器的方式访问远端大规模的存储与计算服务。云计算能够为大规模的新一代网络应用打下良好的基础。
虽 然Google可以说是云计算的最大实践者,但是,Google的云计算平台是私有的环境,特别是Google的云计算基础设施还没有开放出来。除了开放 有限的应用程序接口,例如GWT(Google Web Toolkit)以及Google Map API等,Google并没有将云计算的内部基础设施共享给外部的用户使用,上述的所有基础设施都是私有的。
幸运的是,Google公开 了其内部集群计算环境的一部分技术,使得全球的技术开发人员能够根据这一部分文档构建开源的大规模数据处理云计算基础设施,其中最有名的项目即 Apache旗下的Hadoop项目。而下面的两个云计算的实现则为外部的开发人员以及中小公司提供了云计算的平台环境,使得开发者能够在云计算的基础设 施之上构建自己的新型网络应用。其中IBM的蓝云计算平台是可供销售的计算平台,用户可以基于这些软硬件产品自己构建云计算平台。亚马逊的弹性计算云则是 托管式的云计算平台,用户可以通过远端的操作界面直接使用。
==================IBM
IBM蓝云计算平台
IBM在2007年11月15日推出了蓝云计算平台,为客户带来即买即用的云计算平台。它包括一系列的云计算产品,使得计算不仅仅局限在本地机器或远程服务器农场(即服务器集群),通过架构一个分布式、可全球访问的资源结构,使得数据中心在类似于互联网的环境下运行计算。
通 过IBM的技术白皮书,我们可以一窥蓝云计算平台的内部构造。“蓝云”建立在IBM大规模计算领域的专业技术基础上,基于由IBM软件、系统技术和服务支 持的开放标准和开源软件。简单地说,“蓝云”基于IBM Almaden研究中心(Almaden Research Center)的云基础架构,包括Xen和PowerVM虚拟化、Linux操作系统映像以及Hadoop文件系统与并行构建。“蓝云”由IBM Tivoli软件支持,通过管理服务器来确保基于需求的最佳性能。这包括通过能够跨越多服务器实时分配资源的软件,为客户带来一种无缝体验,加速性能并确 保在最苛刻环境下的稳定性。IBM新近发布的“蓝云(Blue Cloud)”计划,能够帮助用户进行云计算环境的搭建。它通过将Tivoli、DB2、WebSphere与硬件产品(目前是x86刀片服务器)集成, 能够为企业架设一个分布式、可全球访问的资源结构。根据IBM的计划,首款支持Power和x86处理器刀片服务器系统的“蓝云”产品将于2008年正式 推出,并且计划随后推出基于System z“大型主机”的云环境,以及基于高密度机架集群的云环境。
在IBM的云计算白皮书上,我们可以看到如下的蓝云计算平台配置情况。
图 4演示了蓝云计算的高层架构。可以看到,蓝云计算平台由一个数据中心: IBM Tivoli部署管理软件(Tivoli Provisioning Manager)、IBM Tivoli监控软件(IBM Tivoli Monitoring)、IBM WebSphere应用服务器、IBM DB2数据库以及一些虚拟化的组件共同组成。图中的架构主要描述了云计算的后台架构,并没有涉及到前台的用户界面。
蓝云的硬件平台并没有 什么特殊的地方,但是蓝云使用的软件平台相较于以前的分布式平台具有不同的地方,主要体现在对与虚拟机的使用以及对于大规模数据处理软件Apache Hadoop的部署。Hadoop是网络开发人员根据Google公司公开的资料开发出来的类似于Google File System的Hadoop File System以及相应的Map/Reduce编程规范。现在也正在进一步开发类似于Google的Chubby系统以及相应的分布式数据库管理系统 BigTable。由于Hadoop是开源的,因此可以被用户单位直接修改,以适合应用的特殊需求。IBM的蓝云产品则直接将Hadoop软件集成到自己 本身的云计算平台之上。
“蓝云”中的
虚拟化
从蓝云的结构上我们还可以看出,在每一个节点上运行的软件栈 与传统的软件栈一个很大的不同在于蓝云内部使用了虚拟化技术。虚拟化的方式在云计算中可以在两个级别上实现。一个级别是在硬件级别上实现虚拟化。硬件级别 的虚拟化可以使用IBM p系列的服务器,获得硬件的逻辑分区LPAR。逻辑分区的CPU资源能够通过IBM Enterprise Workload Manager来管理。通过这样的方式加上在实际使用过程中的资源分配策略,能够使得相应的资源合理地分配到各个逻辑分区。P系列系统的逻辑分区最小粒度 是1/10颗中央处理器(CPU)。
虚拟化的另外一个级别可以通过软件来获得,在蓝云计算平台中使用了Xen虚拟化软件。Xen也是一个开源的虚拟化软件,能够在现有的Linux基础之上运行另外一个操作系统,并通过虚拟机的方式灵活地进行软件部署和操作。
通 过虚拟机的方式进行云计算资源的管理具有特殊的好处。由于虚拟机是一类特殊的软件,能够完全模拟硬件的执行,因此能够在上面运行操作系统,进而能够保留一 整套运行环境语义。这样,可以将整个执行环境通过打包的方式传输到其他物理节点上,这样就能够使得执行环境与物理环境隔离,方便整个应用程序模块的部署。 总体上来说,通过将虚拟化的技术应用到云计算的平台,可以获得一些良好的特性。
1. 云计算的管理平台能够动态地将计算平台定位到所需要的物理平台上,而无需停止运行在虚拟机平台上的应用程序,这比采用虚拟化技术之前的进程迁移方法更加灵活。
2. 能够更加有效率地使用主机资源,将多个负载不是很重的虚拟机计算节点合并到同一个物理节点上,从而能够关闭空闲的物理节点,达到节约电能的目的。
3. 通过虚拟机在不同物理节点上的动态迁移,能够获得与应用无关的负载平衡性能。由于虚拟机包含了整个虚拟化的操作系统以及应用程序环境,因此在进行迁移的时候带着整个运行环境,达到了与应用无关的目的。
4. 在部署上也更加灵活,即可以将虚拟机直接部署到物理计算平台当中。
总而言之,通过虚拟化的方式,云计算平台能够达到极其灵活的特性,而如果不使用虚拟化的方式则会有很多的局限。
“蓝云”中的
存储结构
蓝云计算平台中的存储体系结构对于云计算来说也是非常重要的,无论是操作系统,服务程序还是用户应 用程序的数据都保存在存储体系中。云计算并不排斥任何一种有用的存储体系结构,而是需要跟应用程序的需求结合起来获得最好的性能提升。总体上来说,云计算 的存储体系结构包含类似于Google File System的集群文件系统以及基于块设备方式的存储区域网络SAN两种方式。
在设计 云计算平台的存储体系结构的时候,不仅仅是需要考虑存储的容量。实际上随着硬盘容量的不断扩充以及硬盘价格的不断下降,使用当前的磁盘技术,可以很容易通 过使用多个磁盘的方式获得很大的磁盘容量。相较于磁盘的容量,在云计算平台的存储中,磁盘数据的读写速度是一个更重要的问题。单个磁盘的速度很有可能限制 应用程序对于数据的访问,因此在实际使用的过程中,需要将数据分布到多个磁盘之上,并且通过对于多个磁盘的同时读写以达到提高速度的目的。在云计算平台 中,数据如何放置是一个非常重要的问题,在实际使用的过程中,需要将数据分配到多个节点的多个磁盘当中。而能够达到这一目的的存储技术趋势当前有两种方 式,一种是使用类似于Google File System的集群文件系统,另外一种是基于块设备的存储区域网络SAN系统。
Google 文件系统在前面已经做过一定的描述。在IBM的蓝云计算平台中使用的是它的开源实现Hadoop HDFS (Hadoop Distributed File System)。这种使用方式将磁盘附着于节点的内部,并且为外部提供一个共享的分布式文件系统空间,并且在文件系统级别做冗余以提高可靠性。在合适的分 布式数据处理模式下,这种方式能够提高总体的数据处理效率。Google文件系统的这种架构与SAN系统有很大的不同。
SAN系统也是云计算平台的另外一种存储体系结构选择,在蓝云平台上也有一定的体现,IBM也提供SAN的平台能够接入到蓝云计算平台中。图5就是一个SAN系统的结构示意图。
从 图5中可以看到,SAN系统是在存储端构建存储的网络,将多个存储设备构成一个存储区域网络。前端的主机可以通过网络的方式访问后端的存储设备。而且,由 于提供了块设备的访问方式,与前端操作系统无关。在SAN连接方式上,可以有多种选择。一种选择是使用光纤网络,能够操作快速的光纤磁盘,适合于对性能与 可靠性要求比较高的场所。另外一种选择是使用以太网,采取iSCSI协议,能够运行在普通的局域网环境下,从而降低了成本。由于存储区域网络中的磁盘设备 并没有与某一台主机绑定在一起,而是采用了非常灵活的结构,因此对于主机来说可以访问多个磁盘设备,从而能够获得性能的提升。在存储区域网络中,使用虚拟 化的引擎来进行逻辑设备到物理设备的映射,管理前端主机到后端数据的读写。因此虚拟化引擎是存储区域网络中非常重要的管理模块。
SAN系 统与分布式文件系统例如Google File System并不是相互对立的系统,而是在构建集群系统的时候可供选择的两种方案。其中,在选择SAN系统的时候,为了应用程序的读写,还需要为应用程序 提供上层的语义接口,此时就需要在SAN之上构建文件系统。而Google File System正好是一个分布式的文件系统,因此能够建立在SAN系统之上。总体来说,SAN与分布式文件系统都可以提供类似的功能,例如对于出错的处理 等。至于如何使用还是需要由建立在云计算平台之上的应用程序来决定。
与Google不同的是,IBM并没有基于云计算提供外部可访问的网 络应用程序。这主要是由于IBM并不是一个网络公司,而是一个IT的服务公司。当然,IBM内部以及IBM未来为客户提供的软件服务会基于云计算的架构。 (注: 本文受国家973计划资助,资助号: 2007CB310900以及国家自然科学基金资助,资助号90718040)
转载自 http://topic.csdn.net/u/20080526/11/D9D28C55-9BE0-46F1-97DD-B6E2F0CDE31D.html
posted @
2011-09-09 11:06 David1228 阅读(1777) |
评论 (0) |
编辑 收藏
Suse Linux 常用命令举例讲解
1.修改 vftpd 配置文件
vi /etc/vsftpd.conf #listen=YES
vi /etc/xinetd.d/vsftpd 将“disable=yes” 改为 “disable=no”使 xinetd 服务启动后接收到 ftp 连接请求时,能够自动启动 vsftpd 服务进程
2. mkdir -p /srv/ftp/linux-10 创建文件夹 -p 如果文件夹不存在自动创建
3. chown -R ftp:ftp /srv/ftp/linux-10 指定 linux-10 目录及其子目录的拥有者为 ftp 用户和 ftp 组
4. chmod -R 755 /srv/ftp/linux-10 指定 linux-10 目录及其子目录的访问权限
5. mount /dev/hdc /srv/ftp/linux-10/disk1 将设备中的内容挂载到 disk1 中
umount /srv/ftp/linux-10/disk1 卸载掉 disk1 中挂载的文件
6. /etc/init.d/xinetd start 启动 FTP 服务
7. df 命令 功能:检查文件系统的磁盘空间占用情况。可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等 信息。
语法:df [选项]
说明:df 命令可显示所有文件系统对 i 节点和磁盘块的使用情况。
该命令各个选项的含义如下:
-a 显示所有文件系统的磁盘使用情况,包括 0 块(block)的文件系统,如/proc 文件系统。
-k 以 k 字节为单位显示。
-i 显示 i 节点信息,而不是磁盘块。
-t 显示各指定类型的文件系统的磁盘空间使用情况。
-x 列出不是某一指定类型文件系统的磁盘空间使用情况(与 t 选项相反)。
-T 显示文件系统类型。
8. free 命令
free命令的功能是查看当前系统内存的使用情况,它显示系统中剩余及已用的物理内存和交换内存,以及共享内存 和被核心使用的缓冲区。
该命令的一般格式为: free [-b | -k | -m] 命令中各选项的含义如下:
-b 以字节为单位显示。
-k 以 K 字节为单位显示。
-m 以兆字节为单位显示。
9. sync 命令 sync 命令是强制把内存中的数据写回硬盘,以免数据的丢失
10. shutdown 命令
shutdown 命令可以安全地关闭或重启 Linux 系统, 它在系统关闭之前给系统上的所有登录用户提示一条警告信息。 该命令还允许用户指定一个时间参数,可以是一个精确的时间,也可以是从现在开始的一个时间段。精确时间的格式 是 hh:mm,表示小时和分钟;时间段由“+”和分钟数表示。系统执行该命令后,会自动进行数据同步的工作。
该命令的一般格式为: shutdown [选项] [时间] [警告信息] 命令中各选项的含义为:
- k 并不真正关机,而只是发出警告信息给所有用户。
- r 关机后立即重新启动。
- h 关机后不重新启动。
- f 快速关机,重启动时跳过 fsck。
- n 快速关机,不经过 init 程序。
- c 取消一个已经运行的 shutdown。 需要特别说明的是,该命令只能由超级用户使用。
11. date 命令
date 命令的功能是显示和设置系统日期和时间。
12. cal 命令
cal 命令的功能是显示某年某月的日历。
该命令的一般格式为: cal [选项] [月 [年]] 命令中各选项的含义为:
- j 显示出给定月中的每一天是一年中的第几天(从 1 月 1 日算起)。
- y 显示出整年的日历。
13. echo 命令
echo 命令的功能是在显示器上显示一段文字,一般起到一个提示的作用。
该命令的一般格式为: echo [ -n ] 字符串
其中选项 n 表示输出文字后不换行;字符串可以加引号,也可以不加引号。用 echo 命令输出加引号的字符串时, 将字符串原样输出;用 echo 命令输出不加引号的字符串时,将字符串中的各个单词作为字符串输出,各字符串之间 用一个空格分割。
14. 从 ftp 安装 linux 系统
install=ftp://ip(服务器 ip 地址)/linux-10/disk1 hostip=ip(新系统 ip)/24 gateway=192.168.0.1(网关)
15. chkconfig --level 235 ntp on 使用系统启动时,自动启动 NTP 服务
16. /etc/init.d/ntp restart 启动 NTP 服务
17. route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0 配置 Linux 多播路由 添加该路由项
18. netstat -nr 查看路由表
19. netstat -an|less 查看服务端口的状态
20. /etc/init.d/novell-tomcat4 restart 重启 Tomcat(在 iManage 中安装插件后)
21. chmod 777 文件名 修改文件权限
22. ndsconfig rm 删除 ED 实例
23. 精确同步时间
先将 ntp 服务停掉 rcxntpd stop 然后执行 ntpdate 命令 (多次执行缩短时间差) 最后启动 rcxntpd start
24. Linux 更改 MAC 地址:
1.> 临时更改:
# ifdown eth0
# ifconfig eth0 hw ether 0029340830249(MAC 地址)
# ifup eth0
2.> 永久生效:(对于 suse 不起作用)
# vi /etc/rc.d/rc.local
ifdown eth0
ifconfig eth0 hw ether 002934083024(MAC 地址)
ifup eth0
# service network restart(suse 9:rcnetwork restart)
3.> 添加新网卡:
a. VM --> 添加网卡
b. 启动时按 '<-' , 确定相关默认配置
c. 在/etc/sysconfig/network-s/创建新网卡文件
d. 配置新网卡文件
25. Linux 更改 MAC 地址:
1.1 redhat:
a. $ cd /etc/sysconfig/network-s
b. Edit file "ifcfg-eth0", change to your real MAC address
(Use "ifconfig -a" to display real MAC address.)
c. $ /etc/init.d/network start (to restart network.)
1.2 SuSE:
a. $ cd /etc/sysconfig/network
b. $ mv ifcfg-eth-id-00:0c:29:ba:b2:ad ifcfg-eth0
c. $ vi /ifcfg-eth0
d. $ 添加 LLADDR='real MAC address'
e. $ 到 YAST 里面配置静态 IP
(Use "ifconfig -a" to display real MAC address.)
f. $ reboot(重启系统)
2.修改 redhat locale:
cd /etc/sysconfig/
编辑 i18n 文件,指定自己所需的 locale
3.修改 SuSE hostname:编辑/etc/HOSTNAME
26. 增加反向代理名称 192.168.10.in-addr-arpa
27. suse 配置 ftp 服务
a. vi /etc/vsftpd.conf
b. 将 listen=yes 注释掉
c. vi /etc/xinetd.d/vsftpd
d. 将 disable=yes 改为 disable=no
e. /etc/init.d/xinetd start 启动 FTP 服务
(suse9 只需执行 c,d,e suse10 都需要执行)
28. 查找文件 find 路径 -name(-size,-type) file
29. 查找字符 grep 参数(-l 显示匹配行号,-I 忽略大小写,-r 递归查找) 'str' fielist
30. 比较文件 diff 参数(-w 忽略空格 ,-I 忽略大小写 ) file file
31.kill
1.作用
kill 命令用来中止一个进程。
2.格式
kill [ -s signal | -p ] [ -a ] pid ...
kill -l [ signal ]
3.参数
-s:指定发送的信号。
-p:模拟发送信号。
-l:指定信号的名称列表。
pid:要中止进程的 ID 号。
Signal:表示信号。
4.说明
进程是 Linux 系统中一个非常重要的概念。Linux 是一个多任务的操作系统,系统上经常同时运行着多个进程。我们不 关心这些进程究竟是如何分配的,或者是内核如何管理分配时间片的,所关心的是如何去控制这些进程,让它们能够 很好地为用户服务。
Linux 操作系统包括三种不同类型的进程,每种进程都有自己的特点和属性。交互进程是由一个 Shell 启动的进程。交 互进程既可以在前台运行,也可以在后台运行。批处理进程和终端没有联系,是一个进程序列。监控进程(也称系统 守护进程)时 Linux 系统启动时启动的进程,并在后台运行。例如,httpd 是著名的 Apache 服务器的监控进程。
kill 命令的工作原理是,向 Linux 系统的内核发送一个系统操作信号和某个程序的进程标识号,然后系统内核就可以对 进程标识号指定的进程进行操作。比如在 top 命令中,我们看到系统运行许多进程,有时就需要使用 kill 中止某些进 程来提高系统资源。 在讲解安装和登陆命令时, 曾提到系统多个虚拟控制台的作用是当一个程序出错造成系统死锁时, 可以切换到其它虚拟控制台工作关闭这个程序。此时使用的命令就是 kill,因为 kill 是大多数 Shell 内部命令可以直接 调用的。
5.应用实例
(1)强行中止(经常使用杀掉)一个进程标识号为 324 的进程:
#kill -9 324
(2)解除 Linux 系统的死锁
在 Linux 中有时会发生这样一种情况:一个程序崩溃,并且处于死锁的状态。此时一般不用重新启动计算机,只需要 中止(或者说是关闭)这个有问题的程序即可。 kill 处于 X-Window 界面时, 当 主要的程序(除了崩溃的程序之外)一般都 已经正常启动了。此时打开一个终端,在那里中止有问题的程序。比如,如果 Mozilla 浏览器程序出现了锁死的情况, 可以使用 kill 命令来中止所有包含有 Mozolla 浏览器的程序。首先用 top 命令查处该程序的 PID,然后使用 kill 命令停 止这个程序:
#kill -SIGKILL XXX
其中,XXX 是包含有 Mozolla 浏览器的程序的进程标识号。
(3)使用命令回收内存 我们知道内存对于系统是非常重要的,回收内存可以提高系统资源。kill 命令可以及时地中止一些“越轨”的程序或很长 时间没有相应的程序。例如,使用 top 命令发现一个无用 (Zombie) 的进程,此时可以使用下面命令:
#kill -9 XXX
其中,XXX 是无用的进程标识号。
然后使用下面命令:
#free
此时会发现可用内存容量增加了。
(4)killall 命令
Linux 下还提供了一个 killall 命令,可以直接使用进程的名字而不是进程标识号,例如:
# killall -HUP inetd
32.rm 删除命令
rm -r 删除目录,不管目录中有没有文件
rm -rf 强制删除,没有提示
33.ln 命令
ln -s 源文件(绝对路径) 目标文件 (软连接)
34.查看本机开放的端口
1、netstat 查看端口和连接
netstat 列出目前已经连接的服务名
netstat -a 列出目前已经连接的和正在监听的服务名
netstat -an 列出目前已经连接的和正在监听的端口号(与上面的命令功能一样, 只是不解释端口号对应的服务名)
netstat -ap 在上面命令的基础上列出连接的 PID(进程号),用这个 PID,可以使用 KILL 来杀死连接
例如:某个连接的 PID=111,想踢出去就使用 KILL -9 111。ok!
netstat -rn 输出路由表
2、nmap
nmap 127.0.0.1查看本机开放的端口,会扫描所有端口
nmap -p 1024 65535 127.0.0.1 扫描指定端口范围
nmap -PT 192.168.1.1-111 扫描一组范围的电脑
35. 交互方式管理 identity manager 对象
dxcmd -host 192.168.37.133 -port 524
36. ps -A 产看进程
37. ssh -X (ip address) 远程连接另一系统
38. pkill firefox-bin(进程名) 以进程名杀进程
39. . /opt/novell/eDirectory/bin/ndspath 设置 ed 的环境变量
======================================================================
1.cd /home 查看根目录
2.cd oracle 查看某个文件夹
3.ls 查看目录下的文件
4.cp jdk(.按tab)显示-6u18-linux-i586.bin ../ 复制到上一层文件夹
5.sudo cp jdk(.按tab)显示-6u18-linux-i586.bin ../ 以root身份复制到上一层文件夹
6./sbin/ifconfig 查看IP
7.netstat -anp | grep oracle
netstat anp | grep oracle
netstat -anp | grep 1521
netstat anp | grep 1521
8.cat 查看文件
vi 编辑文件
9.startx 启动桌面
10.who 查看当前用户
11.vi /etc/inittab 修改启动方式
12.ls -a 查看隐藏文件
13.reboot 重启系统
--------------------------------------------------------------------------------------------------------------------------------
1.tar用来解压文件,都是自己的话来描述,用法实例:
#tar -zxvf SOFTNAME.tar.gz
中间的-zxvf你可以不要管它,基本上我就是这样用的都不怎么知道它上面意思呵呵,后面是要解压的文件名;
2.cd进入文件夹,用法实例:
#cd /usr
进入usr文件夹中;
3.top显示现在运行的程序,就像windows的任务管理器吧,不知道可不可以这样理解;用法实例:
#top
显示出所有正在运行的程序;
4.chown(change owner)变更文件或目录的拥有者或所属群组,用法实例:
# chown -R root .
-R或--recursive 递归处理,将指定目录下的所有文件及子目录一并处理;
5.chmod(change mode)变更文件或目录的权限,用法实例:
#chmod a+x 文件名
a+x是参数,a是all的意思就是所有用户;x是执行或切换权限,把这个文件设置为可执行的并且是所有用户都可以;
6.cp(copy)复制文件或目录,用法实例
#cp 源文件 目的文件
不用说了就是拷贝的;
7.ls(list)列出目录内容,用法实例:
#ls -l
-l是参数,是说使用详细格式列表;
8.reboot重新开机,用法实例:
#reboot
执行reboot指令可让系统停止运作,并重新开机;
9.useradd建立用户帐号,用法实例:
# useradd mysql
建立一个mysql用户账号;
10.su(super user)变更用户身份,用法实例:
#su 用户名
不带参数的话默认为切换到root用户下,然后一般会让你输入密码;
11.exit退出目前的shell,用法实例:
#exit
退出shell;
12.chgrp(change group)变更文件或目录的所属群组,用法实例:
#chgrp -R mysql .
让mysql用户和root拥有一样的权限;
13.ifconfig显示网络状态,用法实例:
#ifconfig
ifconfig可设置网络设备的状态,或是显示目前的设置
14.export显示或设置环境变量,用法实例:
#export JAVA_HOME=/usr/java/jdk1.6.0_17
设置jdk环境变量时,的java_home;
=================================================================================
1.修改vftpd配置文件
vi /etc/vsftpd .conf #listen=YES
vi /etc/xinetd.d/vsftpd 将“disable=yes” 改为 “disable=no”使xinetd服
务启动后接收到ftp连接请求时,能够自动启动vsftpd服务进程
2. mkdir -p /srv/ftp/linux-10 创建文件夹 -p 如果文件夹不存在自动创
建
3. chown -R ftp:ftp /srv/ftp/linux-10 指定linux-10目录及其子目录的拥有者为ftp用户和ftp
组
4. chmod -R 755 /srv/ftp/linux-10 指定linux-10目录及其子目录的访问权限
5. mount /dev/hdc /srv/ftp/linux-10/disk1 将设备中的内容挂载到disk1中
umount /srv/ftp/linux-10/disk1 卸载掉disk1中挂载的文件
6. /etc/init.d/xinetd start 启动FTP服务
7. df命令
功能:检查文件系统的磁盘空间占用情况。可以利用该命令来获取硬盘被占用了多少空间,目前还剩
下多少空间等信息。
语法:df [选项]
说明:df命令可显示所有文件系统对i节点和磁盘块的使用情况。
该命令各个选项的含义如下:
-a 显示所有文件系统的磁盘使用情况,包括0块(block)的文件系统,如/proc文件系统。
-k 以k字节为单位显示。
-i 显示i节点信息,而不是磁盘块。
-t 显示各指定类型的文件系统的磁盘空间使用情况。
-x 列出不是某一指定类型文件系统的磁盘空间使用情况(与t选项相反)。
-T 显示文件系统类型。
8. free命令
free命令的功能是查看当前系统内存的使用情况,它显示系统中剩余及已用的物理内存和交换内存,
以及共享内存和被核心使用的缓冲区。
该命令的一般格式为: free [-b | -k | -m] 命令中各选项的含义如下:
-b 以字节为单位显示。
-k 以K字节为单位显示。
-m 以兆字节为单位显示。
9. sync命令
sync命令是强制把内存中的数据写回硬盘,以免数据的丢失
10. shutdown命令
shutdown 命令可以安全地关闭或重启Linux系统,它在系统关闭之前给系统上的所有登录用户提示一
条警告信息。该命令还允许用户指定一个时间参数,可以是一个精确的时间,也可以是从现在开始的一个
时间段。精确时间的格式是hh:mm,表示小时和分钟;时间段由“+”和分钟数表示。系统执行该命令后,
会自动进行数据同步的工作。
该命令的一般格式为: shutdown [选项] [时间] [警告信息] 命令中各选项的含义为:
- k 并不真正关机,而只是发出警告信息给所有用户。
- r 关机后立即重新启动。
- h 关机后不重新启动。
- f 快速关机,重启动时跳过fsck。
- n 快速关机,不经过init程序。
- c 取消一个已经运行的shutdown。
需要特别说明的是,该命令只能由超级用户使用。
11. date命令
date命令的功能是显示和设置系统日期和时间。
12. cal命令
cal命令的功能是显示某年某月的日历。
该命令的一般格式为: cal [选项] [月 [年]] 命令中各选项的含义为:
- j 显示出给定月中的每一天是一年中的第几天(从1月1日算起)。
- y 显示出整年的日历。
13. echo命令
echo命令的功能是在显示器上显示一段文字,一般起到一个提示的作用。
该命令的一般格式为: echo [ -n ] 字符串
其中选项n表示输出文字后不换行;字符串可以加引号,也可以不加引号。用echo命令输出加引号的字
符串时,将字符串原样输出;用echo命令输出不加引号的字符串时,将字符串中的各个单词作为字符串输
出,各字符串之间用一个空格分割。
14. 从ftp安装linux系统
install=ftp://ip(服务器ip地址)/linux-10/disk1 hostip=ip(新系统ip)/24 gateway=192.168.0.1(
网关)
15. chkconfig --level 235 ntp on 使用系统启动时,自动启动NTP服务
16. /etc/init.d/ntp restart 启动NTP服务
17. route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0 配置Linux多播路由 添加
该路由项
18. netstat -nr 查看路由表
19. netstat -an|less 查看服务端口的状态
20. /etc/init.d/novell-tomcat4 restart 重启Tomcat(在iManage中安装插件后)
21. chmod 777 文件名 修改文件权限
22. ndsconfig rm 删除ED实例
23. 精确同步时间
先将ntp服务停掉 rcxntpd stop 然后执行 ntpdate 命令 (多次执行缩短时间差) 最后启动
rcxntpd start
24. Linux 更改MAC地址:
1.> 临时更改:
# ifdown eth0
# ifconfig eth0 hw ether 0029340830249(MAC地址)
# ifup eth0
2.> 永久生效:(对于suse不起作用)
# vi /etc/rc.d/rc.local
ifdown eth0
ifconfig eth0 hw ether 002934083024(MAC地址)
ifup eth0
# service network restart(suse 9:rcnetwork restart)
3.> 添加新网卡:
a. VM --> 添加网卡
b. 启动时按 '<-' , 确定相关默认配置
c. 在/etc/sysconfig/network-s/创建新网卡文件
d. 配置新网卡文件
25. Linux 更改MAC地址:
1.1 redhat:
a. $ cd /etc/sysconfig/network-s
b. Edit file "ifcfg-eth0", change to your real MAC address
(Use "ifconfig -a" to display real MAC address.)
c. $ /etc/init.d/network start (to restart network.)
1.2 SuSE:
a. $ cd /etc/sysconfig/network
b. $ mv ifcfg-eth-id-00:0c:29:ba:b2:ad ifcfg-eth0
c. $ vi /ifcfg-eth0
d. $ 添加 LLADDR='real MAC address'
e. $ 到YAST里面配置静态IP
(Use "ifconfig -a" to display real MAC address.)
f. $ reboot(重启系统)
2.修改redhat locale:
cd /etc/sysconfig/
编辑i18n文件,指定自己所需的locale
3.修改SuSE hostname:编辑/etc/HOSTNAME
26. 增加反向代理名称 192.168.10.in-addr-arpa
27. suse 配置ftp服务
a. vi /etc/vsftpd.conf
b. 将listen=yes 注释掉
c. vi /etc/xinetd.d/vsftpd
d. 将 disable=yes 改为 disable=no
e. /etc/init.d/xinetd start 启动FTP服务
(suse9只需执行c,d,e suse10都需要执行)
28. 查找文件 find 路径 -name(-size,-type) file
29. 查找字符 grep 参数(-l 显示匹配行号,-I 忽略大小写,-r 递归查找) 'str' fielist
30. 比较文件 diff 参数(-w忽略空格 ,-I忽略大小写 ) file file
31.kill
1.作用
kill命令用来中止一个进程。
2.格式
kill [ -s signal | -p ] [ -a ] pid ...
kill -l [ signal ]
3.参数
-s:指定发送的信号。
-p:模拟发送信号。
-l:指定信号的名称列表。
pid:要中止进程的ID号。
Signal:表示信号。
4.说明
进程是Linux系统中一个非常重要的概念。Linux是一个多任务的操作系统,系统上经常同时运行着多个进
程。我们不关心这些进程究竟是如何分配的,或者是内核如何管理分配时间片的,所关心的是如何去控制
这些进程,让它们能够很好地为用户服务。
Linux 操作系统包括三种不同类型的进程,每种进程都有自己的特点和属性。交互进程是由一个Shell启
动的进程。交互进程既可以在前台运行,也可以在后台运行。批处理进程和终端没有联系,是一个进程序
列。监控进程(也称系统守护进程)时Linux系统启动时启动的进程,并在后台运行。例如,httpd是著名
的 Apache服务器的监控进程。
kill命令的工作原理是,向Linux系统的内核发送一个系统操作信号和某个程序的进程标识号,然后系统
内核就可以对进程标识号指定的进程进行操作。比如在top命令中,我们看到系统运行许多进程,有时就
需要使用kill中止某些进程来提高系统资源。在讲解安装和登陆命令时,曾提到系统多个虚拟控制台的作
用是当一个程序出错造成系统死锁时,可以切换到其它虚拟控制台工作关闭这个程序。此时使用的命令就
是kill,因为kill是大多数Shell内部命令可以直接调用的。
5.应用实例
(1)强行中止(经常使用杀掉)一个进程标识号为324的进程:
#kill -9 324
(2)解除Linux系统的死锁
在Linux 中有时会发生这样一种情况:一个程序崩溃,并且处于死锁的状态。此时一般不用重新启动计算
机,只需要中止(或者说是关闭)这个有问题的程序即可。当 kill处于X-Window界面时,主要的程序(除了
崩溃的程序之外)一般都已经正常启动了。此时打开一个终端,在那里中止有问题的程序。比如,如果
Mozilla浏览器程序出现了锁死的情况,可以使用kill命令来中止所有包含有Mozolla浏览器的程序。首先
用top命令查处该程序的PID,然后使用kill命令停止这个程序:
#kill -SIGKILL XXX
其中,XXX是包含有Mozolla浏览器的程序的进程标识号。
(3)使用命令回收内存
我们知道内存对于系统是非常重要的,回收内存可以提高系统资源。kill命令可以及时地中止一些“越轨
”的程序或很长时间没有相应的程序。例如,使用top命令发现一个无用 (Zombie) 的进程,此时可以使
用下面命令:
#kill -9 XXX
其中,XXX是无用的进程标识号。
然后使用下面命令:
#free
此时会发现可用内存容量增加了。
(4)killall命令
Linux下还提供了一个killall命令,可以直接使用进程的名字而不是进程标识号,例如:
# killall -HUP inetd
32.rm 删除命令
rm -r 删除目录,不管目录中有没有文件
rm -rf 强制删除,没有提示
33.ln命令
ln -s 源文件(绝对路径) 目标文件 (软连接)
34.查看本机开放的端口
1、netstat 查看端口和连接
netstat 列出目前已经连接的服务名
netstat -a 列出目前已经连接的和正在监听的服务名
netstat -an 列出目前已经连接的和正在监听的端口号(与上面的命令功能一样,只是不解释端口
号对应的服务名)
netstat -ap 在上面命令的基础上列出连接的PID(进程号),用这个PID,可以使用KILL 来杀死连接
例如:某个连接的PID=111,想踢出去就使用 KILL -9 111。ok!
netstat -rn 输出路由表
2、nmap
nmap 127.0.0.1 查看本机开放的端口,会扫描所有端口
nmap -p 1024 65535 127.0.0.1 扫描指定端口范围
nmap -PT 192.168.1.1-111 扫描一组范围的电脑
35. 交互方式管理identity manager 对象
dxcmd -host 192.168.37.133 -port 524
36. ps -A 产看进程
37. ssh -X (ip address) 远程连接另一系统
38. pkill firefox-bin(进程名) 以进程名杀进程
39. . /opt/novell/eDirectory/bin/ndspath 设置ed的环境变量
=============================================================================
SUSE 10.0 快捷键大全
2007-09-07 10:25:54| 分类: Linux |字号 订阅
快捷键
ctrl+shift+f (窗口全屏)
ctrl+shift+n (新建konsole窗口)
ctrl+shift++ (调整窗口字体大)
ctrl+shift+- (调整窗口字体小)
ctrl+shift+0 (调整窗口字体正常)
ctrl+alt+f1 (终端1)
ctrl+alt+f2 (终端2)
ctrl+alt+f3 (终端3)
ctrl+alt+f4 (终端4)
ctrl+alt+f5 (终端5)
ctrl+alt+f6 (终端6)
ctrl+alt+f7 (X-window界面)
ctrl+alt+s (重命名会话 在konsole窗口)
ctrl+alt+d (显示桌面)
ctrl+alt+l (锁定屏幕)
ctrl+alt+方向上下(切换输入法)
ctrl+alt+del (结束会话)
ctrl+alt+Ins (结束或锁定当前会话 开始新的会话 有的可尝试+FN键)
Ctrl+Alt+BackSpace (强行退出X-WINDOW)
ctrl+alt+FN+p (调整窗口大小)
ctrl+F1 (显示窗口)
ctrl+f2 (显示桌面)
ctrl+prtscr (截屏)
ctrl+Home (显示到窗口页首)
ctrl+End (显示到窗口页尾)
ctrl+space (切换输入法)
ctrl+shift (切换输入法)
ctrl+l (=clear)
ctrl+n (新建窗口)
ctrl+S (保存文件)
ctrl+q (退出)
ctrl+d (关闭konsole)
ctrl+ESC (KDE卫士)
shift+方向键 (在konsole下切换)
alt+f1 (显示程序菜单)
alt+f2 (运行命令)
alt+f3 (显示当前窗口菜单)
alt+f4 (关闭当前窗口)
alt+f5 (窗口选项)
alt+方向左 (后退网页)
alt+方向右 (向前网页)
.......
非常有用的3D 桌面快捷键,希望对大家有用!
Alt + 鼠标滚轮 上/下使窗口 透明/不透明
程序切换:
Alt + Tab:在当前工作台中切换窗口
Ctrl + Alt + Tab:在所有工作台中切换窗口
立方体旋转:
Ctrl + Alt + 左/右方向键:立体地切换桌面
Ctrl + Shift + Alt + 左/右方向键:把活动窗口移到左/右工作台
Ctrl + Alt + 鼠标左键并拖曳:手动旋转立方体
缩放:
Win + 鼠标右键:缩放一次
Win + 鼠标滚轮 上/下:手动缩放大/小
调整窗口大小:
Alt + 鼠标中键
水波效果:
Ctrl + Win + 移动鼠标:光标在水上移动(默认无效)
Shift + F9:雨点降落在你的屏幕上 (无法停止)
屏幕截图:
Win + 鼠标左键并拖曳:将所选区域截图(图片保存在桌面)
亮度和饱和度:
Ctrl + 鼠标滚轮 上/下:增加/减少 饱和度(对桌面也有效)
Shfit + 鼠标滚轮 上/下:增加/减少 亮度(对桌面也有效)
Trackback: http://www.linuxdby.com/html/linux/other/20070508/28630.html
posted @
2011-09-05 09:34 David1228 阅读(5650) |
评论 (1) |
编辑 收藏
DECLARE
V_FILENAME VARCHAR2(200);
BEGIN
select SUBSTR(FILE_NAME,
1,
LENGTH(FILE_NAME) - INSTR(REVERSE(FILE_NAME), '/') + 1)
INTO V_FILENAME
from dba_data_files
where tablespace_name = 'ZSDATA'
AND ROWNUM = 1;
EXECUTE IMMEDIATE 'CREATE SMALLFILE
TABLESPACE ZSMEMBER_DATA
LOGGING
DATAFILE ''' || V_FILENAME ||
'zsmember_data.dbf'' SIZE 5M REUSE
AUTOEXTEND
ON NEXT 5120K MAXSIZE 32767M EXTENT MANAGEMENT LOCAL
SEGMENT SPACE MANAGEMENT AUTO ';
EXECUTE IMMEDIATE 'CREATE SMALLFILE
TABLESPACE ZSMEMBER_IDX
LOGGING
DATAFILE ''' || V_FILENAME ||
'zsmember_idx.dbf'' SIZE 5M REUSE
AUTOEXTEND
posted @
2011-08-22 17:57 David1228 阅读(393) |
评论 (0) |
编辑 收藏
摘要: 本文会给你们展示50个jquery代码片段,这些代码能够给你的javascript项目提供帮助。其中的一些代码段是从jQuery1.4.2才开始支持的做法,另一些则是真正有用的函数或方法,他们能够帮助你又快又好地把事情完成。这些都是我尽量记住的有着最佳性能的代码段,因此如果你发现你任何可以做得更好的地方的话,欢迎把你的版本粘贴在评论中!我希望你在这一文章中能找到有帮助的东西。1. 如何创建嵌套的过...
阅读全文
posted @
2011-08-22 16:41 David1228 阅读(388) |
评论 (0) |
编辑 收藏
VMware斥资4.2亿美元收购SpringSource(3.6亿现金外加5800万股份),目的在于从虚拟化厂商升级为云计算的重要参与者。
VMware的CTOSteve Herrod称VMware的vSphere云管理平台与Spring Java应用框架等工具的结合将会大大节省开发者编写部署应用所花费的时间精力。此举将提升VMware在PaaS上的竞争能力。PaaS上的几大竞争者包括Salesforce.com的Force.com,以及Google App Engine。
Rod Johnson在SpringSource官方博客上公布这一消息时声称收购将于今年第三季度完成,届时SpringSource将成为VMware下属的一个部门,而他将仍是SpringSource的领导者。以下是Rod Johnson对此次收购的展望:
“此次决定是很自然而符合逻辑的:这将带来更多的新技术,并且对Spring框架以及Spring社区都有好处。
我很兴奋。希望你也是。这将极其有趣。
……Spring框架将继续提供优质的企业级Java支持。我们从关注开发者如何创建和使用应用,到关注他们如何部署和运行企业级应用;为此我们创建了dm Server和tc Server。我们收购Hyperic也是为了改善开发者管理企业级应用的方法。
然而IT的发展要远远超过Java框架,工具以及运行时基础设施。人们对于软件堆栈的想法正在改变。虚拟化改变了数据中心,而云计算又将走的更远。云计算将开发与操作的界限模糊化,并赋予开发者更多的力量(与责任)。
现在的问题就是,如何将SpringSource在数据中心和云计算中的潜力:它的简单,强大和实用这些好处最大化?我们今年早些时候曾尝试过在VMware的Lab Manager下的虚拟机中运行SpringSource Tool Suite中的Spring应用。这次范例的反响很好。而VMware的vApp concept又能够将不同的机器映像,中间件以及管理控件结合到一起——点击一下,就能在数据中心和云端运行,这都是很好的蓝图。
与VMware的合作中,我们计划创建一个简单,集成,创建-运行-管理合一的数据中心、私有云和公共云的解决方案。这个方案将融合应用架构的知识,连带中间件以及管理控件,确保一个虚拟环境在部署过程中以及运行时的最大效率及弹性。这是一个PaaS,建立在你已知的技术之上,从而最大的减少花费与复杂度。这是一个围绕开源、可移植的中间件技术的解决方案,既可以在传统数据中心的Java EE应用服务器上运行,又可以在如Amazon EC2之类的弹性云上运行,也可以在VMware平台上运行。
……与VMware的vSphere以及其他云技术一起,我们将在框架和基础设施上带来一个全新的体验。SpringSource的应用框架、服务器及管理软件将成为VMware平台的眼睛和耳朵。
……SpringSource的下一步工作将是这些新的挑战:基于我们的Build/Run/Manage(创建运行管理)系统,提供从桌面端到云端的最佳解决方案。让百万Java开发者都能享受到云计算带来的好处。”
posted @
2011-08-22 15:09 David1228 阅读(411) |
评论 (0) |
编辑 收藏
Linux下mysql安装配置总计:
MySQL安装配置
本例以root权限安装mysql数据库,mysql-5.1.37-linux-x86_64-glibc23.tar.gz安装包在/root/Nagios/ 目录下(根据实际情况)。
ü 在mysql-5.1.37-linux-x86_64-glibc23.tar.gz安装包所在目录,解压软件包
cd /root/Nagios/
tar -zvxf mysql-5.1.37-linux-x86_64-glibc23.tar.gz
ü 将解压的mysql文件夹,移到/usr/local/目录下
mv mysql-5.1.37-linux-x86_64-glibc23 /usr/local/mysql
ü 将mysql配置文件拷贝到/etc/目录下,并改名my.cnf
cp /usr/local/mysql/support-files/my-medium.cnf /etc/my.cnf
ü 添加mysql用户及用户组,用来运行mysql数据库
groupadd mysql
useradd -g mysql mysql
ü 修改mysql目录权限
// 设定root能访问/usr/local/mysql
chown -R root /usr/local/mysql
// 设定mysql组能访问/usr/local/mysql
chgrp -R mysql /usr/local/mysql
// 设定mysql用户能够访问/var/lib/mysql
chown -R mysql /usr/local/mysql/data
ü 在mysql解压目录下,生成mysql系统数据库,本例安装在/usr/local/mysql目录下
cd /usr/local/mysql
./scripts/mysql_install_db --user=mysql&
ü 以mysql用户启动mysql服务
/usr/local/mysql/bin/mysqld_safe -user=mysql&
ü 修改mysql的root密码,密码假定为:123456
/usr/local/mysql/bin/mysqladmin -u root password 123456
ü 进入MYSQL安装路径下的bin目录,以root用户登录mysql:
cd /usr/local/mysql/bin
./mysql -u root -p
输入密码:123456
ü 开启 mysql 本地和远程访问
grant all on *.* to root@本机IP
grant all privileges on *.* to root @"%" identified by "123456";
flush privileges;
说明:
grant all privileges on *.* to username @"%" identified by "password";
all指定相关操作
*.*说明数据库和表名
username表示用户名
%这里是Host名称,允许所有的就用%
Password表示密码
设置MySQL服务及命令
拷贝mysql安装目录下bin/目录中的文件到/usr/bin目录,使mysq等命令可以在任一路径执行:
cp /usr/local/mysql/bin /usr/bin
设置mysql启动命令,打开/usr/local/mysql/support-files/mysql.server文件,将以下内容:
$bindir/safe_mysqld --datadir=$datadir --pid-file=$pid_file &
改为:
$bindir/safe_mysqld --datadir=$datadir --user=root --pid-file=$pid_file &
拷贝到/etc/init.d目录,并赋可执行权限
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql
chmod +x /etc/init.d/mysql
以root用户调用以下命令启动mysql服务
service mysql start
设置mysql自启动
在文件/etc/rc.d/rc.local中添加
service mysql start
数据库初始化
登陆MySQL,并创建数据库ccms02及表
ü 登陆MySQL
cd /usr/local/mysql/bin
./mysql -u root -p
ü 创建名称为test02的数据库
create database test02 default character set utf8;
ü 退出MySQL,导入建表脚本test02.sql
/usr/local/mysql/bin/mysql -u root -p -D
test02< /home/cloudsync/db/test02.sql ü 导入完成后,重新登陆MySQL,依次执行以下语句,可以查看建表结果
ü ./mysql -u root –p
use test02;
show tables;
posted @
2011-08-22 14:37 David1228 阅读(6479) |
评论 (0) |
编辑 收藏
posted @
2011-08-10 17:10 David1228 阅读(594) |
评论 (0) |
编辑 收藏
一般linux redhat ubuntu centos...防火墙设置是在配置文件
/etc/sysconfig/iptables中。
然后重启iptables service iptables restart.
或通过命令行
iptables -I INPUT -p tcp -dport 3306 -j ACCEPT
添加完成后以iptables-save的方式保存成防火墙的配置文件
和其他linux系统不太相同,opensuse有其自身的防火墙管理策略
有以下两种方式可以对系统的防火墙进行配置
打开配置文件 /etc/sysconfig/SuSEfirewall2
在 FW_SERVICES_EXT_TCP
或 FW_SERVICES_EXT_UDP
后加入端口号,端口:端口 或者服务名称, 单个端口号之间空格隔开
例如:
FW_SERVICES_EXT_TCP="3306 12345 52122 55555"
opensuse中的没有/etc/rc.d/rc.local文件,有
有/etc/init.d/boot.local,自启动程序可以在这里配置。
最新发布的opensuse11.4帮助文档
http://lug.ustc.edu.cn/sites/opensuse-guide/command.php
posted @
2011-07-26 10:15 David1228 阅读(1613) |
评论 (0) |
编辑 收藏
=============================================================================================
=============================================================================================
2011-07-05
一步、CentOs5.4下首先对xen的升级
# cd /etc/yum.repos.d/
# wget http://www.gitco.de/repo/GITCO-XEN3.4.3_x86_64.repo
# yum groupupdate xen 关联xen的相关包kernel-xen virt-manager0.7 python-virtinst等
# reboot
删除xen及关联包如下命令
yum groupupdate xen
在重启之前最好检查一下 grub 是否配置正确、默认启动是否是 xen.gz-3.4.3:
# vi /boot/grub/menu.lst
...
title CentOS (2.6.18-194.26.1.el5xen)
root (hd0,0)
kernel /xen.gz-3.4.3
module /vmlinuz-2.6.18-194.26.1.el5xen ro root=LABEL=/
module /initrd-2.6.18-194.26.1.el5xen.img
...
以上测试过程同时咱考如下说明:
http://www.vpsee.com/2010/11/upgrade-xen-on-centos-5-5-to-xen-3-4-3/
=============================================================================================
=============================================================================================
记录下:
升级linux kernel
以下前提是编译好的kernel文件包。
2011-07-05
将如下进行配置:
1、要添加两行modprobe到xend、
详见/etc/init.d/xend里的modprobe xen-evtchn、modprobe xen-gntdev
2、添加xenfs到/etc/fstab文件
执行如下命令:
/sbin/new-kernel-pkg --package kernel-xen --mkinitrd --depmod --install --multiboot=/boot/xen.gz-3.4.3 2.6.18-164.el5
修改/etc/grub.conf文件内核启动title CentOS (2.6.32.33-gwx-xen-2)
root (hd0,0)
kernel /xen.gz-4.0.1 crashkernel=128M@32M
module /vmlinuz-2.6.32.33-gwx-xen-2 ro root=/dev/VolGroup01/LogVol00 rhgb quiet
module /initrd-2.6.32.33-gwx-xen-2.img
=============================================================================================
=============================================================================================
转载
posted @
2011-07-22 16:40 David1228 阅读(554) |
评论 (0) |
编辑 收藏
select CREATED from ALL_OBJECTS
where OBJECT_TYPE='TABLE'
and OBJECT_NAME=your_table_name
如果是你自己建的表,也可以在USER_OBJECTS中查詢
select CREATED from USER_OBJECTS
where OBJECT_TYPE='TABLE'
and OBJECT_NAME=your_table_name
posted @
2011-07-12 09:48 David1228 阅读(713) |
评论 (0) |
编辑 收藏
来自http://www.novell.com/
XEN迁移/保存/挂起都要保存虚拟机状态快照,只要对于该虚拟机的memory、deviceI/O states、network connecitions and the contents of the virtual CPU registers.XEN有能力来保存所有这些信息到一个磁盘中,然后再所迁移的节点上重启该虚拟机。
1、 SAVE & RESTORE MIGRATION
当你保存或挂起虚拟机时,对应的虚拟机资源不会再分配着,会返回给domain0(host server)。这些资源会被节点上运行着的虚拟机所使用。也就意味着保存或挂起的虚拟机的网络连接同样也丢失了。
虚拟机保存和恢复功能可以被用于很多用途包括测试、调试、迁移虚拟机、系统崩溃快速恢复。例如如果一个虚拟机宕机了,可以快速恢复到一个已知的工作状态。
热迁移:xm migrate
1、 首先检查目的服务器上是否有足够的资源来运行指定的虚拟机。
2、 执行虚拟机内存的初始拷贝,并将其传输到目的地服务器。
3、 每次连续迭代,初始拷贝之后,只有内存在内传输到目的地服务器过度中是变化的。
4、 当内存页变化足够低时或者剩余的页数传输并没有渐减当随着虚拟机被传输到目的地服务器最终的状态时。
5、 虚拟机控制器被传输到指定的主机服务器上。
你的环境中实现热迁移需检查如下:
1、 对于迁移两个XEN主机服务器的之间需正确的被配置。
2、 两个主机之间要有一个快速稳定的网络连接,两个服务器都必须在相同的第2层网络和IP子网,这样准许网络连接迁移到虚拟机。
3、 两个主机服务器通过共享存储方式来访问,强烈推荐指定虚拟机的磁盘镜像和配置文件要放到共享存储。
4、 在两台主机之间XEN版本相同。
对于迁移工作,现在执行一些初始设置。
1、 Edit xend the configuration file
Xend-config.sxp是主要的配置文件对于XEN daemon(XEN守护进程)
Using a text editor such as vi or gedit open /etc/xen/xend-config.sxp.
详细检查该文件,确认下面这行没有被注释掉。
设置如下所示的值
(xend-relocation-server yes)
(xend-relocation-port 8002)
(xend-relocation-address ‘’)
(xend-relocation-hosts-allow ‘’)
The xend-relocation-address操作允许你指定IP地址,XEN daemon监听迁移请求,保留空白设置表示让该服务器监听所有端口,The xend-relocation-hosts-allow 允许选项,限制哪些主机可以联系迁移请求的服务器,理想情况下你应该限制对服务器的访问,使用该选项,以提供更好的安全性。
如果你的运行的服务器开放了防火墙,则你要确保你网卡指定IP上的8002端口被打开。
2、 Migrate a virtual machine
迁移虚拟机格式是非常简单的,xm migrate DomainId destHostID
Eg: xm migrate 1 10.0.0.56
可以在目的地服务器上执行xm list确认主机是否成功被迁移。
正规执行迁移命令是不带任何参数的,xm migrate
我们可以添加-live 选项执行迁移操作,xm migrate –live 1 10.0.0.56,此时是用的热方法,很好的测试方式是通过ping 虚拟机的IP地址,看看有多少包丢失了。
posted @
2011-07-07 17:27 David1228 阅读(570) |
评论 (0) |
编辑 收藏
http://fosschef.com/2011/06/xen-the-road-of-the-life/
在 Linus 明确表示 Linux Kernel 3.0 只是一个版本号的改变,而非里程碑式的飞跃后,许多人对此表达了失望,一个没有重量级功能的新版本似乎配不上这个新的版本号。不过对有些人来说,其中的一 个新功能或许可以担的上这个重任,那就是 Xen 的 block backend driver。这个功能加上之前在 2.6.37,2.6.38,2.6.39 添加的几个 Xen 相关的功能,使得即将发布的 Kernel 3.0 包含了所有成为 Xen 的 Domain0 所必须的功能,从此为 Xen 漫长的 Kernel 之路划上了一个句号,也标志着 Xen 的发展掀开了崭新的一页。
。。。。。。。
顺便这个博客文章也不错,有兴趣请看:
http://hi.baidu.com/chenshake/home
posted @
2011-07-06 16:39 David1228 阅读(337) |
评论 (0) |
编辑 收藏
1. 什么是寻址空间
寻址空间一般指的是CPU对于内存寻址的能力。通俗地说,就是能最多用到多少内存的一个问题
2. 我们经常听说32位操作系统最多能用4G内存。大部分情况下,这个上限都达不到。例如我的机器,虽然是4G物理内存,但实际上识别的只有3G。有的朋友说是可以识别到3.2G或者3.5G不等,我想这跟人品是没有什么关系的
那么,这剩下的1个G左右的内存不是浪费了吗?可不是嘛,太心痛了。所有很多朋友都用一个软件将这部分内存转换为硬盘用
http://blog.miniasp.com/post/2008/04/Useful-tools-Gavotte-Ramdisk.aspx
【备注】我自己还没有这么用,要想试用该功能的同学,自己需要慎重。如果你用的好,记得反馈一下给我,呵呵
3. 为什么说只能寻址到这个大小呢?我今天是要从程序的角度来解说一下
首先说什么是32位?32位是针对CPU的一个术语
对于程序员来说,这表示了我们在与计算机打交道的时候,能够使用的最大数字是2的32次方。这等于多少呢?
那么这个数字是什么为单位呢?bit ,也可以称为比特,或者位。这是计算机可以理解的东西。这个bit里面包含的值,只有两个,就是0和1
好了,那么这个bit怎么样能转换为GB呢,很简单:将它连续除以3次1024.
4294967296/1024/1024/1024
结果等于多少呢?
为什么除3次?第一次转换为KB,第二次转换为MB,第三次就转换为GB了
4. 那么64位的CPU的寻址空间可以到多大呢?
我算一算,可以到多少GB呢?
额的神啊,根据摩尔定律的计算,我想我的有生之年是不需要担心内存不够用的问题的
posted @
2011-07-05 12:16 David1228 阅读(601) |
评论 (0) |
编辑 收藏
Iptables
感觉防火墙可能不能完美的保护主机,比如ping措施,这时,就需要使用iptables来进行配置。
使用Iptables的内置firewall机制,是通过kernel中的netfilter 模块实现的,Linux kernel使用netfilter对进出数据包进行过滤,netfilter由三个规则表组成,每个表又有许多内建的链组成。使用iptables命令可以对这些表链进行操作,如添加、删除、列出规则等。
Netfilter 规则表 --- filter nat managle
filter用于路由网络数据包。是默认的,也就是说如果没有指定-t参数,当创建一条新规则时,他默认存放到该表内。
INPUT 网络数据包流向服务器
OUTPUT 网络数据包从服务器流出
FORWARD 网络数据包经服务器路由
nat 用于NAT表 Net Address Translation 是一种IP地址转换方法
PREROUTING 网络数据包到达服务器时可以被修改
POSTROUTING 网络数据包在即将从服务器发出时可以被修改
managle 用于修改网络数据包的表
配置iptables
当数据包进入服务器时,Linux kernel会查找对应的链,直到找到一条规则与数据包匹配。如果该规则的target是ACCEPT,就会跳过剩下的规则,数据包会继续被传送。如果该规则target是DROP,该数据包会被拦截掉,kernel不会在参考其他规则。
Note:如果从始至终都没有一条规则与数据包匹配,而且表末尾有没有drop all规则,那么该数据包会被accept。Cisco则相反,在表末尾会因含deny all的规则。
1) iptables命令选项
iptables [-t iptables ] command option parameter target
-A 在链尾添加一条规则
-C 将规则添加到用户定义链之前对其进行检查
-D 从链中删除一条规则
-E重命名用户定义的链,不改变链本身
-F 清空链,删除链上的所有规则
-I在链中插入一条规则
-L 列出某个链上的规则,如:iptables –L INPUT 列出INPUT链上的规则
-N 创建一个新链
-P 定义某个链的默认策略
-R替换链上的某条规则
-X 删除某个用户相关的链
-Z 将所有表的所有链的字节和数据包统计数器清零
2) Iptables的命令参数
-p protocol
应用于数据包的协议类型,可以是TCP UDP ICMP 或 ALL ! 也可以
当使用-p tcp时,还可使用其他可选项,一边允许进一步定义规则,选项如下:
-sport 允许指定匹配数据包源端口 port1:port2表示port1和port2之间的所有端口
-dport目的端口,和sport雷同
当使用-p !udp 时,也有特殊的选项供使用
-sport和-dport与-p tcp相同,只不过用于UDP包
使用-p icmp参数时,只有一个选项可用
-icmp-type 允许在过滤规则中指定icmp类型
-s source 指定数据包包的源地址,该参数后跟一个IP地址,一个带有sub-net mask的网络地址,或者一个主机名(不建议使用主机名)
-d destination 数据包的目的地址 同-s
-j jump 用于指定一个target,告诉规则将该匹配的数据包发送到该target。Target可以是ACCEPT,DROP,QUEIE,PETURN。如果没有-j,那么不会对数据包进行任何操作,只是将计数器加1
-I in-interface 对于INPUT FOREARD PREROUTING链,指定数据包到达服务器时所使用的端口
-o out-interface 对于OUTPUT FORWARD POSTROUTING链,该参数指定数据包离开服务器时使用的端口
3)Iptables的命令target
创建规则最后一步是指定iptables对数据包的操作。只要某一规则匹配该数据包,就不会再有别的规则的操作。内建的target有:ACCEPT 允许数据包通过 ,到达目的地
DROP 拒绝数据包通过,丢弃该包
QUEUE 将数据包发送回到用户应用程序处理
RETURN 不再根据当前链的其他规则来检查数据包,而是直接返回,继续被发送到其目的地址,或下一个链。
2、示例:
允许www
Iptables –A INPUT –p tcp –dport 80 –j ACCEPT
该规则被调价到filter表的INPUT链,允许目的端口为80的数据包通过
在内部接口上允许DHCP
Iptables –A INPUT –I eth0 –p tcp - - sport - - dport 67 ACCEPT
Iptables –A INPUT –I eth0 –p udp - - sport - - dport 67 ACCEPT
同时允许tcp和udp协议
3、保存和修改iptables
使用iptables-save 可将现行的iptables规则保存
恢复iptables
使用iptables-restore可从配置文档恢复iptables表到现行iptables表。
posted @
2011-06-30 18:59 David1228 阅读(383) |
评论 (0) |
编辑 收藏
我在本地将10G文件打包为zip,上传到linux下。之前所用的unzip解压不了这么大的文件。
[root@node30 images]# unzip ubuntu-8.04.4.zip Archive: ubuntu-8.04.4.zip skipping: ubuntu-8.04.4.img need PK compat. v4.5 (can do v2.1)网上找到解决方案通过p7zip工具能够实现大文件的解压缩。p7zip简介看最下面。
然后再官方网站:http://p7zip.sourceforge.net/ 中下载了针对linux的p7zip
下载之后后缀名是
p7zip_9.20.1_src_all.tar.bz2,
通过命令
tar -jxvf p7zip_9.20.1_src_all.tar.bz2 解压该文件,
然后执行
make 编译
在执行
make install 安装p7zip
OK!!!!
执行如下命令即可完成我这10G文件的解压缩。如下:
[root@node30 images]# 7za x ubuntu-8.04.4.zip 7-Zip (A) [64] 9.20 Copyright (c) 1999-2010 Igor Pavlov 2010-11-18p7zip Version 9.20 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,4 CPUs)Processing archive: ubuntu-8.04.4.zipExtracting ubuntu-8.04.4.imgEverything is OkSize: 10737418240Compressed: 117455645以下为网上转载回顾之用。
转载自:
http://www.cnblogs.com/fangbo/archive/2009/12/01/1614538.html
这么多年来,数据压缩对我们来说是非常有用的。无论是在邮件中发送的图片用的zip文件 还是在服务器压缩数据文件,我们都可以让下载更容易或者有效的节约磁盘空间。某些压缩格式有时允许我们以60%的比率(甚至更高)压缩文件。下面我将会给 大家演示如何用这些命令在Linux下面去压缩文件或者目录。我们将学习zip, tar, tar.gz和tar.bz2等压缩格式的基本用法。这几个是在Linux里面常用的压缩格式。
在我们探究这些用法之前,我想先跟大家分享一下使用不同压缩格式的经验。当然,我这里讲到的只是其中的一些用法,除我讲到的之外,他们还有更多的地 方值得我们探讨。我已经意识到我需要了解两到三种压缩格式,才能更好的使用他们。zip格式是第一个需要了解的格式。因为它实际上已成为压缩文件的标准选 择,而且它在windows上也能使用。我经常用zip格式压缩那些需要共享给windows用户的文件。如果只是共享给linux用户或者Mac用户, 那我偏向于选择tar.gz格式。
ZIP
zip可能是目前使用得最多的文档压缩格式。它最大的优点就是在不同的操作系统平台,比如Linux, Windows以及Mac OS,上使用。缺点就是支持的压缩率不是很高,而tar.gz和tar.gz2在压缩率方面做得非常好。闲话少说,我们步入正题吧:
我们可以使用下列的命令压缩一个目录:
# zip -r archive_name.zip directory_to_compress
下面是如果解压一个zip文档:
TAR
Tar是在Linux中使用得非常广泛的文档打包格式。它的好处就是它只消耗非常少的CPU以及时间去打包文件,他仅仅只是一个打包工具,并不负责压缩。下面是如何打包一个目录:
# tar -cvf archive_name.tar directory_to_compress
如何解包:
# tar -xvf archive_name.tar.gz
上面这个解包命令将会将文档解开在当前目录下面。当然,你也可以用这个命令来捏住解包的路径:
# tar -xvf archive_name.tar -C /tmp/extract_here/
TAR.GZ
这种格式是我使用得最多的压缩格式。它在压缩时不会占用太多CPU的,而且可以得到一个非常理想的压缩率。使用下面这种格式去压缩一个目录:
# tar -zcvf archive_name.tar.gz directory_to_compress
解压缩:
# tar -zxvf archive_name.tar.gz
上面这个解包命令将会将文档解开在当前目录下面。当然,你也可以用这个命令来捏住解包的路径:
# tar -zxvf archive_name.tar.gz -C /tmp/extract_here/
TAR.BZ2
这种压缩格式是我们提到的所有方式中压缩率最好的。当然,这也就意味着,它比前面的方式要占用更多的CPU与时间。这个就是你如何使用tar.bz2进行压缩。
# tar -jcvf archive_name.tar.bz2 directory_to_compress
上面这个解包命令将会将文档解开在当前目录下面。当然,你也可以用这个命令来捏住解包的路径:
# tar -jxvf archive_name.tar.bz2 -C /tmp/extract_here/
数据压缩是非常有用的,尤其是对于备份来说。所以,你现在应该考虑在你的备份脚本中使用你在这里学到的压缩方式备份你基本的规则文件以减小你备份文件的大小。
过段时间之后,你就会意识到,在压缩率与CPU占用时间上会有一个平衡,你也要学会如何去权衡什么时候你需要一个快但是压缩率低,什么时候需要一个压缩率高但是CPU点用高的压缩方式,然后你才能避免无谓的空间与时间。
-Zip 是一种高压缩比的存档格式 7z 的管理器,可惜只能用于 Windows 平台。其实7-zip也有linux版本的,只不过它不叫7-zip了,而是P7ZIP。
P7ZIP 的安装
在 Debian/Ubuntu 系统,可通过 sudo apt-get install p7zip 进行安装。
也可以从这里下载:http://p7zip.sourceforge.net/
P7ZIP 的使用
创建压缩包:7za a -t7z test.7z *,此命令将目录中的所有文件压缩到 test.7z 中。
解开压缩包:7za X test.7z,此命令用于将 test.7z 中的文件提取出来。可使用 -t 来指明压缩格式。
更多信息,执行命令:
7za –help
另外,解压文件建议用 X 而不是 e
7za X test.7z
用 e 会丢失目录结构的。
相关链接:
官方网站:http://p7zip.sourceforge.net/
论坛支持:http://sourceforge.net/forum/?group_id=111810
posted @
2011-06-22 12:15 David1228 阅读(1564) |
评论 (0) |
编辑 收藏
摘要: 最近通过做的项目中修改个bug,在jsp页面中潜入applet,通过applet来上传5-10G之间的文件。修改过程记录如下:JSP页面中 <div id="appletTemp"> &nb...
阅读全文
posted @
2011-06-21 15:07 David1228 阅读(2246) |
评论 (0) |
编辑 收藏
HTML5高级程序设计思想,欢迎学习哦!
/Files/ldwblog/解读_HTML5.pdf
posted @
2011-06-02 14:26 David1228 阅读(271) |
评论 (0) |
编辑 收藏
lsof -i:3306
查看3306端口被谁占用
lsof简介
lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接 和硬件。所以如传输控制协议 (tcp) 和用户数据报协议 (udp) 套接字等,系统在后台都为该应用程序分配了一个文件描述符,无论这个文件的本质如何,该文件描述符为应用程序与基础操作系统之间的交互提供了通用接口。因 为应用程序打开文件的描述符列表提供了大量关于这个应用程序本身的信息,因此通过lsof工具能够查看这个列表对系统监测以及排错将是很有帮助的。
lsof使用
lsof输出信息含义
在终端下输入lsof即可显示系统打开的文件,因为 lsof 需要访问核心内存和各种文件,所以必须以 root 用户的身份运行它才能够充分地发挥其功能。
command pid user fd type device size node name
init 1 root cwd dir 3,3 1024 2 /
init 1 root rtd dir 3,3 1024 2 /
init 1 root txt reg 3,3 38432 1763452 /sbin/init
init 1 root mem reg 3,3 106114 1091620 /lib/libdl-2.6.so
init 1 root mem reg 3,3 7560696 1091614 /lib/libc-2.6.so
init 1 root mem reg 3,3 79460 1091669 /lib/libselinux.so.1
init 1 root mem reg 3,3 223280 1091668 /lib/libsepol.so.1
init 1 root mem reg 3,3 564136 1091607 /lib/ld-2.6.so
init 1 root 10u fifo 0,15 1309 /dev/initctl
每行显示一个打开的文件,若不指定条件默认将显示所有进程打开的所有文件。lsof输出各列信息的意义如下:
command:进程的名称
pid:进程标识符
user:进程所有者
fd:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等
type:文件类型,如dir、reg等
device:指定磁盘的名称
size:文件的大小
node:索引节点(文件在磁盘上的标识)
name:打开文件的确切名称
其中fd 列中的文件描述符cwd 值表示应用程序的当前工作目录,这是该应用程序启动的目录,除非它本身对这个目录进行更改。
txt 类型的文件是程序代码,如应用程序二进制文件本身或共享库,如上列表中显示的 /sbin/init 程序。其次数值表示应用
程序的文件描述符,这是打开该文件时返回的一个整数。如上的最后一行文件/dev/initctl,其文件描述符为 10。u 表示该
文件被打开并处于读取/写入模式,而不是只读 ? 或只写 (w) 模式。同时还有大写 的w 表示该应用程序具有对整个文件的写
锁。该文件描述符用于确保每次只能打开一个应用程序实例。初始打开每个应用程序时,都具有三个文件描述符,从 0 到 2,
分别表示标准输入、输出和错误流。所以大多数应用程序所打开的文件的 fd 都是从 3 开始。
与 fd 列相比,type 列则比较直观。文件和目录分别称为 reg 和 dir。而chr 和 blk,分别表示字符和块设备;
或者 unix、fifo 和 ipv4,分别表示 unix 域套接字、先进先出 (fifo) 队列和网际协议 (ip) 套接字。
posted @
2011-06-02 11:12 David1228 阅读(313) |
评论 (0) |
编辑 收藏
/Files/ldwblog/Xen管理手册.pdf 1. XEN Virtual Machine Migration
来自http://www.novell.com/
XEN迁移/保存/挂起都要保存虚拟机状态快照,只要对于该虚拟机的memory、deviceI/O states、network connecitions and the contents of the virtual CPU registers.XEN有能力来保存所有这些信息到一个磁盘中,然后再所迁移的节点上重启该虚拟机。
1、 SAVE & RESTORE MIGRATION
当你保存或挂起虚拟机时,对应的虚拟机资源不会再分配着,会返回给domain0(host server)。这些资源会被节点上运行着的虚拟机所使用。也就意味着保存或挂起的虚拟机的网络连接同样也丢失了。
虚拟机保存和恢复功能可以被用于很多用途包括测试、调试、迁移虚拟机、系统崩溃快速恢复。例如如果一个虚拟机宕机了,可以快速恢复到一个已知的工作状态。
热迁移:xm migrate
1、 首先检查目的服务器上是否有足够的资源来运行指定的虚拟机。
2、 执行虚拟机内存的初始拷贝,并将其传输到目的地服务器。
3、 每次连续迭代,初始拷贝之后,只有内存在内传输到目的地服务器过度中是变化的。
4、 当内存页变化足够低时或者剩余的页数传输并没有渐减当随着虚拟机被传输到目的地服务器最终的状态时。
5、 虚拟机控制器被传输到指定的主机服务器上。
你的环境中实现热迁移需检查如下:
1、 对于迁移两个XEN主机服务器的之间需正确的被配置。
2、 两个主机之间要有一个快速稳定的网络连接,两个服务器都必须在相同的第2层网络和IP子网,这样准许网络连接迁移到虚拟机。
3、 两个主机服务器通过共享存储方式来访问,强烈推荐指定虚拟机的磁盘镜像和配置文件要放到共享存储。
4、 在两台主机之间XEN版本相同。
对于迁移工作,现在执行一些初始设置。
1、 Edit xend the configuration file
Xend-config.sxp是主要的配置文件对于XEN daemon(XEN守护进程)
Using a text editor such as vi or gedit open /etc/xen/xend-config.sxp.
详细检查该文件,确认下面这行没有被注释掉。
设置如下所示的值
(xend-relocation-server yes)
(xend-relocation-port 8002)
(xend-relocation-address ‘’)
(xend-relocation-hosts-allow ‘’)
The xend-relocation-address操作允许你指定IP地址,XEN daemon监听迁移请求,保留空白设置表示让该服务器监听所有端口,The xend-relocation-hosts-allow 允许选项,限制哪些主机可以联系迁移请求的服务器,理想情况下你应该限制对服务器的访问,使用该选项,以提供更好的安全性。
如果你的运行的服务器开放了防火墙,则你要确保你网卡指定IP上的8002端口被打开。
2、 Migrate a virtual machine
迁移虚拟机格式是非常简单的,xm migrate DomainId destHostID
Eg: xm migrate 1 10.0.0.56
可以在目的地服务器上执行xm list确认主机是否成功被迁移。
正规执行迁移命令是不带任何参数的,xm migrate
我们可以添加-live 选项执行迁移操作,xm migrate –live 1 10.0.0.56,此时是用的热方法,很好的测试方式是通过ping 虚拟机的IP地址,看看有多少包丢失了。
posted @
2011-05-19 11:14 David1228 阅读(1402) |
评论 (0) |
编辑 收藏
下载
附录常用shell命令
本附录中列举了一些有用的s h e l l命令。这里并没有完全列出每个命令的各种选项,不过
对于理解该命令是足够了。
这些命令的其他一些例子散布于本书的各个部分。
basename
格式:
basename path
b a s e n a m e命令能够从路径中分离出文件名。通常用于s h e l l脚本中,请看下面的例子:
如果上面的语句是脚本m y s c r i p t中的一部分,那么它的输出应为:
myscript: give me a file
其中,$ 0是一个包含当前脚本全路径的特殊变量。
cat
格式:
cat options files
选项:
- v:显示控制字符。
c a t是最常用的文本文件显示命令。
$ cat myfile
上面的命令用于显示m y f i l e文件。
$ cat myfile myfile2 >>hold_file
上面的命令把两个文件( m y f i l e和m y f i l e 2 )合并到h o l d f i l e中。
在脚本中c a t命令还可以用于读入文件。
compress
格式:
compress options files
选项:
- v:显示压缩结果。
c o m p r e s s命令可以用来压缩文件。压缩后的文件名具有‘ . Z’后缀。还可以使用该命令解
压文件。
cp
格式:
cp options file1 file2
选项:
- i:在覆盖文件之前提示用户,由用户确认。
- p:保留权限模式和更改时间。
- r:拷贝相应的目录及其子目录。
要将文件m y f i l e拷贝到m y f i l e 1 . b a k,使用:
$ cp myfile1 myfile1.bak
要将文件g e t . p r d从/ u s r / l o c a l / s y b i n目录拷贝到/ u s r / l o c a l / b i n目录,使用:
要将/ l o g s目录下的所有文件及子目录拷贝到/ h o l d / l o g s目录中,使用:
$ cp -r /logs /hold/logs
diff
格式:
diff options file1 file2
选项:
- c:按照标准格式输出(见下面的例子)。
- I:忽略大小写。
我们使用c o m m命令中的例子,d i ff命令将显示两个文件中不一致的行。
d i ff命令显示出两个文件中的第2行和第3行,它们的第3列不一致。
dircmp
格式:
附录常用s h e l l命令351
下载
dircmp options directory1 directory2
选项:
- s:不显示相同的文件。
d i r c m p命令与d i ff命令十分相似—它比较并显示两个目录中的不同。
dirname
格式:
dirname pathname
该目录正好和b a s e n a m e相反,它返回路径部分:
du
格式:
du options directory
选项:
- a:显示每个文件的大小,不仅是整个目录所占用的空间。
- s:只显示总计。
d u显示的磁盘空间占用是以5 1 2字节的块来表示的。它主要用于显示目录所占用的空间。
在本例中, / v a r目录所占用的空间为1 4 9 2 9块(每块5 1 2字节)。
file
格式:
file filename
该命令用来确定文件的类型。
fuser
格式:
fuser options file
选项:
- k:杀死所有访问该文件或文件系统的进程。
352 附录常用s h e l l命令
下载
- u:显示访问该文件或文件系统的所有进程。
f u s e r命令可以显示访问某个文件或文件系统的所有进程。在有些系统上- u和- m选项可以
互换。还可以在i f语句中使用f u s e r命令。
要列出设备/ d e v / h d a 5上的所有活动进程,使用:
要杀死设备/ d e v / h d a 5上的所有进程,使用:
$ fuser -k /dev/hda5
要查看d o c p a r t文件是否被打开,有哪些进程在使用,可用:
有些系统上的f u s e r命令能够在列表中显示用户登录I D。如果你的系统不具有这样的功能,
可以按照f u s e r命令输出中末尾含有‘ e’的数字在ps -ef或ps xa命令的输出中用g r e p命令查找
相应的用户登录I D。
head
格式:
head -number files
h e a d命令可以显示相应文件的前1 0行。如果希望指定显示的行数,可以使用- n u m b e r选项。
例如:
$ head -1 myfile
只显示文件的第一行,而
$ head -30 logfile |more
则显示l o g f i l e文件的前3 0行。
logname
格式:
l o g n a m e
该命令可以显示当前所使用的登录用户名:
mkdir
格式:
mkdir options directory
选项:
附录常用s h e l l命令353
下载
- m:在创建目录时按照该选项的值设置访问权限。
上述命令创建了一个名为H O L D A R E A的目录。
more
格式:
more options files
该命令和p a g e及p g命令的功能相似,都能够分屏显示文件内容。
选项:
- c:不滚屏,而是通过覆盖来换页。
- d:在分页处显示提示。
- n:每屏显示n行。
$ more /etc/passwd
上面的命令显示p a s s w d文件
$ cat logfile |more
上面的命令显示l o g f i l e文件。
nl
格式:
nl options file
选项:
- I:行号每次增加n;缺省为1。
- p:在新的一页不重新计数。
n l命令可用于在文件中列行号,在打印源代码或列日志文件时很有用。
$ nl myscript
上面的命令将列出m y s c r i p t文件的行号。
$ nl myscript >hold_file
则将上面命令的输出重定向到h o l d f i l e文件中。
$ nl myscript | lpr
将上面命令的结果重定向到打印机。
printf
格式:
printf format arguments
该命令有点类似于a w k命令的p r i n t f函数,它将格式化文本送至标准输出。
其中,格式符f o r m a t包含三种类型的项,这里我们只讨论格式符:
%[- +]m.nx
354 附录常用s h e l l命令
下载
其中横杠-为从行首算起的起始位置。一般说来m表示域的宽度而n表示域的最大宽度。
‘%’后面可跟下列格式字符:
s:字符串。
c:字符。
d:数字。
x:1 6进制数。
o:1 0进制数。
p r i n t f命令本身并不会产生换行符,必须使用转义字符来实现这样的功能。下面是最常用
的转义字符:
\ a:响铃。
\ b:退格。
\ r:回车。
\ f:换页。
\ n:换行。
\ t:跳格。
$ printf "Howzat!\n"
H o w z a t !
上面的命令输出了一个字符串,使用\ n来换行。
上面的命令把1 6进制值转换为A S C I I字符+。
上面的命令从左起第1 0个字符的位置开始显示字符串。
pwd
格式:
p w d
显示当前的工作目录,可以用:
在上面的脚本中,使用了命令置换来获得当前目录。
rm
格式:
rm options files
选项:
附录常用s h e l l命令355
下载
- i:在删除文件之前给出提示(安全模式)。
- r:删除目录。
r m命令能够删除文件或目录。
上面的第二条命令能够删除/ v a r / s p o o l / t m p目录下的所有文件及子目录。
rmdir
格式:
rmdir options directory
选项:
- p:如果相应的目录为空目录,则删除该目录。
$ rmdir /var/spool/tmp/lp_HP
上面的命令将删除/ v a r / s p o o l / t m p目录下的l p H P目录。
script
格式:
script option file
- a:将输出附加在文件末尾。
可以使用s c r i p t命令记录当前会话。只要在命令行键入该命令即可。该命令在你退出当前
会话时结束。它可以将你的输入记录下来并附加到一个文件末尾。
$ script mylogin
将会启动s c r i p t命令并将所有会话内容记录在m y l o g i n文件中。
shutdown
格式:
s h u t d o w n
该命令将关闭系统。很多系统供应商都有自己特定的命令变体。
$ shutdown now
上面的命令将会立即关机。
$ shutdown -g60 -I6 -y
上面的命令将会在6 0秒之后关机,然后重新启动系统。
sleep
格式:
sleep number
该命令使系统等待相应的秒数。例如:
356 附录常用s h e l l命令
下载
$ sleep 10
意味着系统在1 0秒钟之内不进行任何操作。
strings
格式:
strings filename
该命令可以看二进制文件中所包含的文本。
touch
格式:
touch options filename
选项:
-t MMDDhhmm 创建一个具有相应月、日、时分时间戳的文件。
下面的命令能够以当前时间创建文件或更新已有文件的时间戳。
上面的命令以当前时间创建了一个名为m y f i l e的文件。
上面的命令以时间戳6月1 0日上午9 : 3 0创建了一个名为m y f i l e 2的空文件。
tty
格式:
t t y
可以使用t t y来报告所连接的设备或终端。
可以使用tty -s命令来确定脚本的标准输入。返回码为:
0:终端。
1:非终端。
uname
格式:
uname options
选项:
- a:显示所有信息。
- s:系统名。
- v:只显示操作系统版本或其发布日期。
附录常用s h e l l命令357
下载
要显示当前操作系统名及其他相关信息,可以用:
uncompress
格式:
uncompress files
可以使用该命令来恢复压缩文件。
$ uncompress myfile
上面的命令解压缩先前压缩的m y f i l e文件。注意,在解压缩时不必给出. Z后缀。
wait
格式:
wait process ID
该命令可以用来等待进程号为process ID的进程或所有的后台进程结束后,再执行当前脚
本。
下面的命令等待进程号为1 2 9 9的进程结束后再执行当前脚本:
$ wait 1299
下面的命令等待所有的后台进程结束后再执行当前脚本:
$ wait
wc
格式:
wc options file。s
选项:
- c:显示字符数。
- l:显示行数。
- w:显示单词数。
该命令能够统计文件中的字符数、单词数和行数。
在上面第一个例子中, w h o命令的输出通过管道传递给w c命令,该命令显示出如下的几
列:
行数、单词数、字符数
在上面的第二个例子中, w c命令只显示文件中所包含的行数。
358 附录常用s h e l l命令
下载
上面的脚本显示出变量VA R中所包含的字符串的长度。
whereis
格式:
whereis command_name
w h e r e i s命令能够给出系统命令的二进制文件及其在线手册的路径。
注意,在下面的例子中, w h e r e i s命令没有显示出相应命令的二进制文件路径,因为它们
是内建的s h e l l脚本,但是该命令给出了其在线手册的路径。
who
格式:
who options
选项:
- a:显示所有的结果。
- r:显示当前的运行级别(在L I N U X系统中应当使用r u n l e v e l命令)。
- s:列出用户名及时间域。
whoami 显示执行该命令的用户名。这不是w h o命令的一个选项,可以单独应用。
w h o命令可以显示当前有哪些用户登录到系统上。要显示当前登录的用户,可以用:
要显示自己的用户名,可以用:
附录常用s h e l l命令359
下载
posted @
2011-05-17 10:11 David1228 阅读(312) |
评论 (0) |
编辑 收藏
软件系统的并发控制一般是通过加锁(有乐观锁和悲观锁两种)来实现,乐观锁是一种事后补救措施,是通过程序的逻辑控制版本来实现的,而悲观锁是事前的一种预防措施,它利用数据库的锁机制来实现。
虽然乐观锁能够提高系统的性能,但它是对发生冲突的访问进行事后的补救,应用在用户输入数据量很少的场合比较适合,但如果在企业ERP,用户与系统交互涉及大量数据在页面表单上录入,如果事后提交失败后才提示用户要重新录入是很不现实的,所以有必要进行事前控制,这就要采用悲观锁。
在多个客户端可能读取同一笔数据或同时更新一笔数据的情况下,防止同一个数据被修改而造成混乱,最简单的手段就是在读取时对数据进行锁定,其它客户端不能对同一笔数据进行更新的读取动作。
一个典型的倚赖数据库的悲观锁调用:
select * from account where name=”John” for update
这条 sql 语句锁定了 account 表中所有符合检索条件(name=”Erica”)的记录。本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。Hibernate 的悲观锁,也是基于数据库的锁机制实现。
下面的代码实现了对查询记录的加锁:
String hqlStr ="from TUser as user where user.name='John'";
Query query = session.createQuery(hqlStr);
query.setLockMode("user",LockMode.UPGRADE); // 加锁
List userList = query.list();// 执行查询,获取数据
query.setLockMode 对查询语句中,特定别名所对应的记录进行加锁(我们为TUser 类指定了一个别名 “user” ),这里也就是对返回的所有 user 记录进行加锁。
观察运行期 Hibernate 生成的 SQL 语句:
select tuser0_.id as id, tuser0_.name as name, tuser0_.group_id
as group_id, tuser0_.user_type as user_type, tuser0_.sex as sex
from t_user tuser0_ where (tuser0_.name='John' ) for update
这里 Hibernate 通过使用数据库的 for update 子句实现了悲观锁机制。
Hibernate 的加锁模式有:
LockMode.NONE : 无锁机制。
LockMode.WRITE : Hibernate 在 Insert 和 Update 记录的时候会自动获取。
LockMode.READ : Hibernate 在读取记录的时候会自动获取。
以上这三种锁机制一般由 Hibernate 内部使用,如 Hibernate 为了保证 Update过程中对象不会被外界修改,会在 save 方法实现中自动为目标对象加上 WRITE 锁。
LockMode.UPGRADE :利用数据库的 for update 子句加锁。
LockMode. UPGRADE_NOWAIT : Oracle 的特定实现,利用 Oracle 的 for update nowait 子句实现加锁。
上面这两种锁机制是我们在应用层较为常用的,加锁一般通过以下方法实现:
Criteria.setLockMode
Query.setLockMode
Session.lock
注意,只有在查询开始之前(也就是 Hiberate 生成 SQL 之前)设定加锁,才会真正通过数据库的锁机制进行加锁处理,否则,数据已经通过不包含 for update 子句的 Select SQL 加载进来,所谓数据库加锁也就无从谈起。
posted @
2011-03-17 16:03 David1228 阅读(489) |
评论 (0) |
编辑 收藏
package com.sinovatech.unicom.efb.common;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
/**
*
* 目的:FTP文件类
* <br/>
*
* FTP上传文件、下载文件
*
* *
*/
public class FTPUtil {
private static final Log log = LogFactory.getLog(FTPUtil.class);
public static int download(String ip,int port,String userName,String password,FileFilter filter,String localFilePath) throws SocketException, IOException{
return download(ip, port, userName, password, null,filter, localFilePath);
}
public static int download(String ip,int port,String userName,String password,String ftpPath,FileFilter filter,String localFilePath) throws SocketException, IOException{
FTPClient ftp = new FTPClient();
int i=0;
try {
// 不为空连接 通过IP 和端口
ftp.connect(ip, port);
// 登陆
if (ftp.login(userName, password)) {
ftp.enterLocalPassiveMode();
// 获取FTP登陆目录下的所有文件
if(ftpPath!=null){
if(!ftp.changeWorkingDirectory(ftpPath)){
throw new RuntimeException("找不到该目录:"+ftpPath);
}
}
FTPFile[] files = ftp.listFiles();
for (FTPFile file : files) {
String fileName = file.getName();
if (filter.accept(fileName)) {
BufferedOutputStream out = null;
try {
// IO流下载文件到本地
out = new BufferedOutputStream(
new FileOutputStream(new File(localFilePath
,fileName)));
// 开始下载
ftp.retrieveFile(file.getName(), out);
log.info("下载文件:" + file.getName() + "到本地路径:"
+ localFilePath);
i++;
} finally {
try {
if (out != null) {
out.close();
}
} catch (Exception e) {
log.error("", e);
}
}
}
}
} else {
i = -1;
}
} finally {
if(ftp != null&&ftp.isConnected()){
try {
log.info("关闭ftp连接");
ftp.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return i;
}
public static int download(String ip,int port,String userName,String password,String ftpPath,final String fileName,String localFilePath)throws SocketException, IOException{
return download(ip, port, userName, password,ftpPath,new FileFilter(){
public boolean accept(String fileName1) {
return fileName.equalsIgnoreCase(fileName1);
}
}, localFilePath);
}
public static int download(String ip,int port,String userName,String password,final String fileName,String localFilePath)throws SocketException, IOException{
return download(ip, port, userName, password,null,fileName, localFilePath);
}
/**
* ftp上传文件至服务器
* @throws SocketException
* @throws IOException
*/
public static void uploadFile(String ip, int port, String userName, String password, String localFile)
throws SocketException, IOException{
log.info("上传本地文件: " + localFile);
File file = new File(localFile);
InputStream in = null;
FTPClient ftpClient = null;
if(file != null){
try {
ftpClient = new FTPClient();
in = new FileInputStream(file);
ftpClient.connect(ip,port);
if(ftpClient.login(userName, password)){
ftpClient.enterLocalPassiveMode();
boolean flag= ftpClient.appendFile(file.getName(), in);
log.info("上传文件成功:" + flag);
}
}catch (SocketException e) {
log.error("ftp上传文件失败:", e);
throw e;
}catch (IOException e) {
log.error("ftp上传文件失败:", e);
throw e;
} finally{
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(ftpClient != null){
try {
ftpClient.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public static void upload(String ip, int port, String userName, String password, String path,String remotePath)
throws SocketException, IOException{
upload(ip, port, userName, password, new File(path), remotePath);
}
/**
* ftp上传文件至服务器
* @throws SocketException
* @throws IOException
*/
public static void upload(String ip, int port, String userName, String password, File localFile,String remotePath)
throws SocketException, IOException{
log.info("上传本地文件: " + localFile.getName());
InputStream in = null;
FTPClient ftpClient = null;
if(localFile != null){
try {
ftpClient = new FTPClient();
in = new FileInputStream(localFile);
ftpClient.connect(ip,port);
if(ftpClient.login(userName, password)){
ftpClient.enterLocalPassiveMode();
if(remotePath!=null){
if(!ftpClient.changeWorkingDirectory(remotePath)){
ftpClient.makeDirectory(remotePath);
ftpClient.changeWorkingDirectory(remotePath);
}
}
boolean flag= ftpClient.storeFile(localFile.getName(), in);
log.info("上传文件成功:" + flag);
}
}catch (SocketException e) {
log.error("ftp上传文件失败:", e);
throw e;
}catch (IOException e) {
log.error("ftp上传文件失败:", e);
throw e;
} finally{
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(ftpClient != null){
try {
ftpClient.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
posted @
2011-01-21 12:01 David1228 阅读(2683) |
评论 (0) |
编辑 收藏
Oracle数据库写法:
--查询第5-10条记录
方式一:
select * from (select rownum myrow,t.* from efb_random_pwd t) where myrow between 5 and 10;
以下两种方式数据量大的时候效率好些。
方式二:
select * from (select rownum r,a.* from efb_random_pwd a where rownum<=20) where r>=10;
方式三:
select * from efb_random_pwd where rowid in(
select rid from (select rownum num,rowid rid from efb_random_pwd a where rownum <=10) where num > = 5);
MySql数据库写法:
select * from tablename where LIMIT 9,10
从10条开始取,取10条,则就是10--20
SqlServer数据库写法:
1:select top 20 * from tablename where id not exists (select top 10 * from tablename)//前20条记录再过滤掉前10条
2:select top10 * from (select top 20 * from order by column) order by column desc//子查询中取20条倒序,然后从子查询中取前10条
posted @
2011-01-20 13:33 David1228 阅读(187) |
评论 (0) |
编辑 收藏
在学习javascript中正则是经常使用的,在正则中的特殊符号,需要转义等,下面对正则中的转义和特殊字符进行介绍
首先是元字符,意思是,在使用这些字符时,必须使用转义字符,负责会出错.
元字符有:()[]{}\^$|?*
任何时候用在正则表达式中用到以上字符必须进行转义.
举例:假如匹配?这个字符
var re = /\?/;
或者
var re = new RegExp("\\?");
正则中的特殊符号:
注意到第二个正则,当用到\的时候,多用了\来进行转义\ 最后达到两个\\,叫做双重转义
其次 特殊符号
在则会功能则中可以使用ASCII代码也可以用Unicode代码.
当用字符用十六进制表示时,在字符签名必须加上\x
当用八进制时,在紫府前必须加上 \
当用Unicode编码表示是必须加上 \
还有其它一些特殊符号
字符 说明
\t 制表符
\n 换行符
\r 回车符
\a 换页符
\e alert字符
\cX escape字符
\b 与X相对应的字符
\v 回退字符
\0 空字符
如果用RegExp构造函数来使用它们,则必须使用双重转义.
以上就是正则中的特殊符号
正则表达之字符类:
先说一下字符类的意思,字符类是用于测试的字符组合.字符类是放到中括号[]中的,可以有效的告诉正则去匹配.在字符类又分为五个简单的类,分别说一下
1.简单类
简单类就是你想要匹配的字母组
举例说明
var _class = /[abc]de/gi;
上面的一个字符类就是一个简单的类,可以匹配ade,bde,cde.三种,后面的g和i分别是全局和不区分大小写.
再简单类中还可以使用unicode编码
var _class = /[a\u0062c]de/gi;
这个跟上面的一样,可以匹配ade,bde,cde.三种,后面的g和i分别是全局和不区分大小写.
2.负向类
负向类就是你要排除的字母,用上尖号(^)表示负向类
举例//www.forasp.cn 转载请注明
var _class = /[^abc]de/gi;
用了负向类^就排除了a,b,c三个开头的字符串,即 ade,bde,cde都不匹配
3.范围类
范围类即指定从一个字符到另一个字符的范围,用中杠(-)表示.
举例
var _class = /[a-c]de/gi;//这就是表示从a到c,即,abc都匹配
上面的就匹配了ade,bde,cde.三种.也可以加上负向类表示不匹配
var _class = /[^a-c]de/gi;//这就是表示从a到c,即,abc都不匹配
4.组合类
组合类是有几种其它类的组合而合成的字符类.
举例
var _class = /[1-9a-c]/gi;
上面的表达式就是1-9或者a-c均能匹配,列举1,2,3,4,5,6,7,8,9,a,b,c
在此 要注意的是字符内部类之间不能有空格.还有不能有交叉.
5.预定义类//www.forasp.cn 转载请注明
预定义类就是将复杂的组合类预定义成特定的代码.
列举了javascrip中的预定义类
代码 等同于 匹配
. [^\n\r] 出了换行和回车以外的任何字符
\d [0-9] 数字
\D [^0-9] 非数字
\s [ \t\n\xB\f\r] 空白字符
\S [^ \t\n\xB\f\r] 非空白字符
\w [a-zA-Z_0-9] 单词字符,包括字母下划线和数字
\W [^a-zA-Z_0-9] 非单词字符
以上就是常用的正则表达式的字符类,常用谨记
====================
正则表达之量词
正则表达式中的量词,规定了特定的字符串出现的次数.当指定某个模式应当出现的出售时,可以指定硬性数量.
可以说分为两类量词
1.简单量词,如下标识
代码 描述
? 出现零次或者一次
* 出现任意次数
+ 至少出现一次
{n} 一定出现n次
{n,m} 至少出现n次最多出现m次
{n,} 至少出现n次
举例说明以上的标识,gi是全局部分大小写,下面就不说gi了.
var foraspcn = /[ab]?c/gi;//匹配 c,ac,bc
var foraspcn = /[ab]*c/gi;//匹配 c,aac,bbc...
var foraspcn = /[ab]+c/gi;//匹配 ac,bc,aac,bbc..
var foraspcn = /[ab]{1}c/gi;//匹配 ac,bc
var foraspcn = /[ab]{1,2}c/gi;//匹配 ac,bc,aac,bbc
var foraspcn = /[ab]{1,}c/gi;//匹配 ac,bc,aac,bbc...
看看看懂没有,有的时候有的是相等的比如
?就等于{0,1}
*等于{0,}
+等于{1,}
2.贪婪的,惰性的,支配性的量词
首先解释一下三种量词.
贪婪量词就是先看整个字符串师傅匹配,如果没有,则去掉字符串最后一个字符,再次匹配.一直到发现最后一个匹配或者字符串不剩下任何字符.目前的量词都是贪婪的.
惰性量词是首先看第一个字符是否匹配,如果单独这一个字符不够,则读入下一个,与组成两个字符去匹配,如果没有发现再次读取下一个字符,直到发现匹配或者整个字符串都没有匹配.惰性和贪婪正好相反.
支配量词擦好难过时匹配整个字符串,如果不匹配则不再尝试.支配量词就是整体匹配一次.$hidden$
贪婪的,惰性的,支配性的量词 表如下
贪婪的 惰性的 支配性 描述
? ?? ?+ 零次或者一次出现
* *? *+ 零次或者多次出现
+ +? ++ 至少一次出现
{n} {n}? {n}+ 正好n次出现
{n,m} {n,m}? {n,m}+至少n次出现,至多m次出现
{n,} {n,}? {n,}+ 至少n次出现
以上就是正则中量词的相关内容
posted @
2010-12-30 15:40 David1228 阅读(448) |
评论 (0) |
编辑 收藏
正则表达式中/i,/g,/ig,/gi,/m的区别和含义
/i (忽略大小写)
/g (全文查找出现的所有匹配字符)
/m (多行查找)
/gi(全文查找、忽略大小写)
/ig(全文查找、忽略大小写)
posted @
2010-12-30 15:25 David1228 阅读(260) |
评论 (0) |
编辑 收藏
摘要: TitleType text here...
/**//* @projectDescription jQuery Password Strength Plugin - A jQuery plugin to provide accessibility functions...
阅读全文
posted @
2010-12-30 14:47 David1228 阅读(2490) |
评论 (0) |
编辑 收藏
public class ExportExcelUtil {
/**
* 这是一个通用的方法,利用了JAVA的反射机制,可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出到指定IO设备上
*
* @param title
* 表格标题名
* @param headers
* 表格属性列名数组
* @param dataset
* 需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。此方法支持的
* javabean属性的数据类型有基本数据类型及String,Date,byte[](图片数据)
* @param fieldNames
* 传入的对应headers属性列名数组的具体的字段名称,javabean风格,模式如:model.user.name
* @param out
* 与输出设备关联的流对象,可以将EXCEL文档导出到本地文件或者网络中
* @param pattern
* 如果有时间数据,设定输出格式。默认为"yyy-MM-dd"
*/
public void exportExcel(String title, String[] headers,String[] fieldNames,List dataset, OutputStream out, String pattern) {
headers=this.addString("序号", 0, headers);
int column=headers.length;
HSSFWorkbook hwb = POIExcelUtil.createWorkbook();// 创建一个excel工作单
HSSFSheet hs=hwb.createSheet(title);
HSSFPatriarch patriarch = hs.createDrawingPatriarch();
// 定义注释的大小和位置,详见文档
HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0,0, 0, 0, (short) 4, 2, (short) 6, 5));
comment.setString(new HSSFRichTextString("提示:数据为单页数据!"));
comment.setAuthor("liuhonglai");
hs.addMergedRegion(new CellRangeAddress(0, (short) 0, 0,(short) (column - 1))); // 合并单元格
int listSize = dataset!=null?dataset.size():0;
int rows = listSize + 2;// 定义总的行数
for (int i = 0; i < rows; i++) {// 循环创建行数
HSSFRow hr = POIExcelUtil.createRow(i, hs);// 根据查询的数据在sheet中创建行
for (int j = 0; j < column; j++) {// 循环列数
HSSFCell hc = POIExcelUtil.createCell(j, hr);// 创建列
if (i == 0) {// 控制第一行的样式
HSSFCellStyle cs = POIExcelUtil.createCellStyle(hwb);
HSSFFont font = POIExcelUtil.createFont(hwb);
font.setFontHeightInPoints((short) 14);
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
cs.setFont(font);// 设置字体
cs.setWrapText(true);
cs.setBorderBottom(HSSFCellStyle.BORDER_THIN);// 下边框
cs.setBorderLeft(HSSFCellStyle.BORDER_NONE);// 左边框
cs.setBorderRight(HSSFCellStyle.BORDER_NONE);// 右边框
cs.setBorderTop(HSSFCellStyle.BORDER_NONE);// 上边框
cs.setAlignment(CellStyle.ALIGN_CENTER);// 设置水平对齐方式
cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER);// 设置垂直对齐方式
StringBuffer buffer = new StringBuffer();
buffer.append(title);
POIExcelUtil.setSheetTitle(hs, cs, hr, hc, buffer.toString()); // 设置标题
break;
}
if (i == 1) {// 控制第二行的样式,并设置列的名称
HSSFCellStyle cs = POIExcelUtil.createCellStyle(hwb);
hr.setHeightInPoints((float) 24);
HSSFFont font = POIExcelUtil.createFont(hwb);
cs.setFont(font);// 设置字体
cs.setAlignment(CellStyle.ALIGN_CENTER);
cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
cs.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index);// 设置单元格背景
cs.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
hc.setCellType(HSSFCell.CELL_TYPE_STRING);
hc.setCellStyle(cs);
hc.setCellValue(headers[j]);
} else {// 设置内容
if(dataset!=null){
switch (j) {
case 0: //序号
hc.setCellValue(i - 1);
break;
default:
Object t= dataset.get(i - 2);// 去掉前两行
if(j==2||j==3){
hs.setColumnWidth((int) j, (int) (35.7 * 150));
}else{
hs.setColumnWidth((int) j, (int) (35.7 * 80));
}
String fieldName =fieldNames[j-1];
Object value=null;
// String getMethodName = "get"+ fieldName.substring(0, 1).toUpperCase()+ fieldName.substring(1);
// Class tCls = t.getClass();
// try {
// Method getMethod = tCls.getMethod(getMethodName,new Class[] {});
// value = getMethod.invoke(t, new Object[] {});
// } catch (SecurityException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (IllegalArgumentException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (NoSuchMethodException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (IllegalAccessException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (InvocationTargetException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
value = getColumnValue(t, fieldName);
String textValue = null;
if (value instanceof Integer) {
int intValue =( (Integer) value).intValue();
textValue=String.valueOf(intValue);
} else if (value instanceof Float) {
float fValue = ((Float) value).floatValue();
textValue=String.valueOf(fValue);
} else if (value instanceof Double) {
double dValue =( (Double) value).doubleValue();
textValue=String.valueOf(dValue);
} else if (value instanceof Long) {
long longValue =( (Long) value).longValue();
textValue=String.valueOf(longValue);
}else if (value instanceof Boolean) {
boolean bValue = ((Boolean) value).booleanValue();
textValue=String.valueOf(bValue);
} else if (value instanceof Date) {
Date date = (Date) value;
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
textValue = sdf.format(date);
} else if (value instanceof byte[]) {
// 有图片时,设置行高为60px;
hr.setHeightInPoints(60);
// 设置图片所在列宽度为80px,注意这里单位的一个换算
hs.setColumnWidth(i, (short) (35.7 * 80));
// sheet.autoSizeColumn(i);
byte[] bsValue = (byte[]) value;
HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0,
1023, 255, (short) 6, i-1, (short) 6, i-1);
anchor.setAnchorType(2);
patriarch.createPicture(anchor, hwb.addPicture(
bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));
} else {
// 其它数据类型都当作字符串简单处理
if(value==null){
textValue="";
}else{
textValue = value.toString();
}
}
hc.setCellValue(textValue);
break;
}
}
}
}
}
POIExcelUtil.setPrintSetup(hwb, hs, rows, column);
try {
hwb.write(out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 递归方式处理.
* @param obj 传入的对象
* @param fileNames 有层级javabean方式,model.user.name
* @return Object 值
* @author david
*/
private static Object getColumnValue(Object obj,String fieldNames){
if(null != fieldNames && !"".equals(fieldNames)){
try {
Object objVal = null;
int sp = fieldNames.indexOf(".");
String fieldName = "";
String afterFieldNames = "";
if(sp == -1){
fieldName = fieldNames;
}else{
fieldName = fieldNames.substring(0,sp);
afterFieldNames = fieldNames.substring(sp + 1,fieldNames.length());
}
String getMethodName = "get"+ fieldName.substring(0, 1).toUpperCase()+ fieldName.substring(1);
Class classz = obj.getClass();
Method getMethod;
getMethod = classz.getMethod(getMethodName,new Class[] {});
objVal = getMethod.invoke(obj, new Object[] {});
if(StringUtils.isBlank(afterFieldNames)){
return objVal;
}else{
return getColumnValue(objVal, afterFieldNames);
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return null;
}
private String[] addString(String str,int index,String[] old){
String[] temp=new String[old.length+1];
System.arraycopy(old, 0, temp, 0, old.length);
for(int i=old.length;i>index;i--){
temp[i]=temp[i-1];
}
temp[index]=str;
return temp;
}
}
posted @
2010-12-02 15:45 David1228 阅读(423) |
评论 (0) |
编辑 收藏
POI导出EXCEL经典实现
在web开发中,有一个经典的功能,就是数据的导入导出。特别是数据的导出,在生产管理或者财务系统中用的非常普遍,因为这些系统经常要做一些报表打印的工作。而数据导出的格式一般是EXCEL或者PDF,我这里就用两篇文章分别给大家介绍下。(注意,我们这里说的数据导出可不是数据库中的数据导出!么误会啦^_^)
呵呵,首先我们来导出EXCEL格式的文件吧。现在主流的操作Excel文件的开源工具有很多,用得比较多的就是Apache的POI及JExcelAPI。这里我们用Apache POI!我们先去Apache的大本营下载POI的jar包:http://poi.apache.org/ ,我这里使用的是3.0.2版本。
将3个jar包导入到classpath下,什么?忘了怎么导包?不会吧!好,我们来写一个导出Excel的实用类(所谓实用,是指基本不用怎么修改就可以在实际项目中直接使用的!)。我一直强调做类也好,做方法也好,一定要通用性和灵活性强。下面这个类就算基本贯彻了我的这种思想。那么,熟悉许老师风格的人应该知道,这时候该要甩出一长串代码了。没错,大伙请看:
package org.leno.export.util;
import java.util.Date;
public class Student {
private long id;
private String name;
private int age;
private boolean sex;
private Date birthday;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(long id, String name, int age, boolean sex, Date birthday) {
super();
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.birthday = birthday;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean getSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
package org.leno.export.util;
public class Book {
private int bookId;
private String name;
private String author;
private float price;
private String isbn;
private String pubName;
private byte[] preface;
public Book() {
super();
}
public Book(int bookId, String name, String author, float price,
String isbn, String pubName, byte[] preface) {
super();
this.bookId = bookId;
this.name = name;
this.author = author;
this.price = price;
this.isbn = isbn;
this.pubName = pubName;
this.preface = preface;
}
public int getBookId() {
return bookId;
}
public void setBookId(int bookId) {
this.bookId = bookId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getPubName() {
return pubName;
}
public void setPubName(String pubName) {
this.pubName = pubName;
}
public byte[] getPreface() {
return preface;
}
public void setPreface(byte[] preface) {
this.preface = preface;
}
}
上面这两个类一目了然,就是两个简单的javabean风格的类。再看下面真正的重点类:
package org.leno.export.util;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.text.SimpleDateFormat;
import javax.swing.JOptionPane;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
/**
* 利用开源组件POI3.0.2动态导出EXCEL文档
* 转载时请保留以下信息,注明出处!
* @author leno
* @version v1.0
* @param <T> 应用泛型,代表任意一个符合javabean风格的类
* 注意这里为了简单起见,boolean型的属性xxx的get器方式为getXxx(),而不是isXxx()
* byte[]表jpg格式的图片数据
*/
public class ExportExcel<T> {
public void exportExcel(Collection<T> dataset, OutputStream out) {
exportExcel("测试POI导出EXCEL文档", null, dataset, out, "yyyy-MM-dd");
}
public void exportExcel(String[] headers, Collection<T> dataset,
OutputStream out) {
exportExcel("测试POI导出EXCEL文档", headers, dataset, out, "yyyy-MM-dd");
}
public void exportExcel(String[] headers, Collection<T> dataset,
OutputStream out, String pattern) {
exportExcel("测试POI导出EXCEL文档", headers, dataset, out, pattern);
}
/**
* 这是一个通用的方法,利用了JAVA的反射机制,可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出到指定IO设备上
*
* @param title
* 表格标题名
* @param headers
* 表格属性列名数组
* @param dataset
* 需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。此方法支持的
* javabean属性的数据类型有基本数据类型及String,Date,byte[](图片数据)
* @param out
* 与输出设备关联的流对象,可以将EXCEL文档导出到本地文件或者网络中
* @param pattern
* 如果有时间数据,设定输出格式。默认为"yyy-MM-dd"
*/
@SuppressWarnings("unchecked")
public void exportExcel(String title, String[] headers,
Collection<T> dataset, OutputStream out, String pattern) {
// 声明一个工作薄
HSSFWorkbook workbook = new HSSFWorkbook();
// 生成一个表格
HSSFSheet sheet = workbook.createSheet(title);
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth((short) 15);
// 生成一个样式
HSSFCellStyle style = workbook.createCellStyle();
// 设置这些样式
style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 生成一个字体
HSSFFont font = workbook.createFont();
font.setColor(HSSFColor.VIOLET.index);
font.setFontHeightInPoints((short) 12);
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 把字体应用到当前的样式
style.setFont(font);
// 生成并设置另一个样式
HSSFCellStyle style2 = workbook.createCellStyle();
style2.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style2.setBorderRight(HSSFCellStyle.BORDER_THIN);
style2.setBorderTop(HSSFCellStyle.BORDER_THIN);
style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);
style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
// 生成另一个字体
HSSFFont font2 = workbook.createFont();
font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
// 把字体应用到当前的样式
style2.setFont(font2);
// 声明一个画图的顶级管理器
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
// 定义注释的大小和位置,详见文档
HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 2, (short) 6, 5));
// 设置注释内容
comment.setString(new HSSFRichTextString("可以在POI中添加注释!"));
// 设置注释作者,当鼠标移动到单元格上是可以在状态栏中看到该内容.
comment.setAuthor("leno");
//产生表格标题行
HSSFRow row = sheet.createRow(0);
for (short i = 0; i < headers.length; i++) {
HSSFCell cell = row.createCell(i);
cell.setCellStyle(style);
HSSFRichTextString text = new HSSFRichTextString(headers[i]);
cell.setCellValue(text);
}
//遍历集合数据,产生数据行
Iterator<T> it = dataset.iterator();
int index = 0;
while (it.hasNext()) {
index++;
row = sheet.createRow(index);
T t = (T) it.next();
//利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值
Field[] fields = t.getClass().getDeclaredFields();
for (short i = 0; i < fields.length; i++) {
HSSFCell cell = row.createCell(i);
cell.setCellStyle(style2);
Field field = fields[i];
String fieldName = field.getName();
String getMethodName = "get"
+ fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
try {
Class tCls = t.getClass();
Method getMethod = tCls.getMethod(getMethodName,
new Class[] {});
Object value = getMethod.invoke(t, new Object[] {});
//判断值的类型后进行强制类型转换
String textValue = null;
// if (value instanceof Integer) {
// int intValue = (Integer) value;
// cell.setCellValue(intValue);
// } else if (value instanceof Float) {
// float fValue = (Float) value;
// textValue = new HSSFRichTextString(
// String.valueOf(fValue));
// cell.setCellValue(textValue);
// } else if (value instanceof Double) {
// double dValue = (Double) value;
// textValue = new HSSFRichTextString(
// String.valueOf(dValue));
// cell.setCellValue(textValue);
// } else if (value instanceof Long) {
// long longValue = (Long) value;
// cell.setCellValue(longValue);
// }
if (value instanceof Boolean) {
boolean bValue = (Boolean) value;
textValue = "男";
if (!bValue) {
textValue ="女";
}
} else if (value instanceof Date) {
Date date = (Date) value;
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
textValue = sdf.format(date);
} else if (value instanceof byte[]) {
// 有图片时,设置行高为60px;
row.setHeightInPoints(60);
// 设置图片所在列宽度为80px,注意这里单位的一个换算
sheet.setColumnWidth(i, (short) (35.7 * 80));
// sheet.autoSizeColumn(i);
byte[] bsValue = (byte[]) value;
HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0,
1023, 255, (short) 6, index, (short) 6, index);
anchor.setAnchorType(2);
patriarch.createPicture(anchor, workbook.addPicture(
bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));
} else{
//其它数据类型都当作字符串简单处理
textValue = value.toString();
}
//如果不是图片数据,就利用正则表达式判断textValue是否全部由数字组成
if(textValue!=null){
Pattern p = Pattern.compile("^""d+("".""d+)?$");
Matcher matcher = p.matcher(textValue);
if(matcher.matches()){
//是数字当作double处理
cell.setCellValue(Double.parseDouble(textValue));
}else{
HSSFRichTextString richString = new HSSFRichTextString(textValue);
HSSFFont font3 = workbook.createFont();
font3.setColor(HSSFColor.BLUE.index);
richString.applyFont(font3);
cell.setCellValue(richString);
}
}
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//清理资源
}
}
}
try {
workbook.write(out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
// 测试学生
ExportExcel<Student> ex = new ExportExcel<Student>();
String[] headers = { "学号", "姓名", "年龄", "性别", "出生日期" };
List<Student> dataset = new ArrayList<Student>();
dataset.add(new Student(10000001, "张三", 20, true, new Date()));
dataset.add(new Student(20000002, "李四", 24, false, new Date()));
dataset.add(new Student(30000003, "王五", 22, true, new Date()));
// 测试图书
ExportExcel<Book> ex2 = new ExportExcel<Book>();
String[] headers2 = { "图书编号", "图书名称", "图书作者", "图书价格", "图书ISBN",
"图书出版社", "封面图片" };
List<Book> dataset2 = new ArrayList<Book>();
try {
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("book.jpg"));
byte[] buf = new byte[bis.available()];
while ((bis.read(buf)) != -1) {
//
}
dataset2.add(new Book(1, "jsp", "leno", 300.33f, "1234567",
"清华出版社", buf));
dataset2.add(new Book(2, "java编程思想", "brucl", 300.33f, "1234567",
"阳光出版社", buf));
dataset2.add(new Book(3, "DOM艺术", "lenotang", 300.33f, "1234567",
"清华出版社", buf));
dataset2.add(new Book(4, "c++经典", "leno", 400.33f, "1234567",
"清华出版社", buf));
dataset2.add(new Book(5, "c#入门", "leno", 300.33f, "1234567",
"汤春秀出版社", buf));
OutputStream out = new FileOutputStream("E:""a.xls");
OutputStream out2 = new FileOutputStream("E:""b.xls");
ex.exportExcel(headers, dataset, out);
ex2.exportExcel(headers2, dataset2, out2);
out.close();
JOptionPane.showMessageDialog(null, "导出成功!");
System.out.println("excel导出成功!");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
不行,头有点晕^_^。呵呵,又是泛型,又是反射,又是正则表达式,又是重载,还有多参数列表和POI API。一下子蹦出来,实在让人吃不消。不管了,顶住看效果先。在本地运行后,我们发现在E:""下生成了两份excel文件:学生记录和图书记录,并且中文,数字,颜色,日期,图片等等一且正常。恩,太棒了。有人看到这里开始苦脸了:喂,我怎么一运行就报错啊!呵呵,看看什么错吧!哦,找不到文件,也就是说你没有book.jpg嘛。好,拷贝一张小巧的图书图片命名为book.jpg放置到当前工程下吧。注意,您千万别把张桌面大小的图片丢进去了^_^!看到效果了吧。现在我们再来简单梳理一下代码,实际上上面就做了一个导出excel的方法和一个本地测试main()方法。并且代码的结构也很清晰,只是涉及的知识点稍微多一点。大家细心看看注释,结合要完成的功能,应该没有太大问题的。好啦,吃杯茶,擦把汗,总算把这个类消化掉,你又进步了。咦,你不是说是在WEB环境下导出的吗?别急,因为导出就是一个下载的过程。我们只需要在服务器端写一个Jsp或者Servlet组件完成输出excel到浏览器客户端的工作就好了。我们以Servlet为例,还是看代码吧:
package org.leno.export.util;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author leno
* 使用servlet导出动态生成的excel文件,数据可以来源于数据库
* 这样,浏览器客户端就可以访问该servlet得到一份用java代码动态生成的excel文件
*/
public class Export extends javax.servlet.http.HttpServlet{
static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
File file = new File(getServletContext().getRealPath("WEB-INF/book.jpg"));
response.setContentType("octets/stream");
response.addHeader("Content-Disposition", "attachment;filename=test.xls");
//测试图书
ExportExcel<Book> ex = new ExportExcel<Book>();
String[] headers = { "图书编号", "图书名称", "图书作者", "图书价格", "图书ISBN",
"图书出版社", "封面图片" };
List<Book> dataset = new ArrayList<Book>();
try {
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(file));
byte[] buf = new byte[bis.available()];
while ((bis.read(buf)) != -1) {
//将图片数据存放到缓冲数组中
}
dataset.add(new Book(1, "jsp", "leno", 300.33f, "1234567",
"清华出版社", buf));
dataset.add(new Book(2, "java编程思想", "brucl", 300.33f, "1234567",
"阳光出版社", buf));
dataset.add(new Book(3, "DOM艺术", "lenotang", 300.33f, "1234567",
"清华出版社", buf));
dataset.add(new Book(4, "c++经典", "leno", 400.33f, "1234567",
"清华出版社", buf));
dataset.add(new Book(5, "c#入门", "leno", 300.33f, "1234567",
"汤春秀出版社", buf));
OutputStream out = response.getOutputStream();
ex.exportExcel(headers, dataset, out);
out.close();
System.out.println("excel导出成功!");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
写完之后,如果您不是用eclipse工具生成的Servlet,千万别忘了在web.xml上注册这个Servelt。而且同样的,拷贝一张小巧的图书图片命名为book.jpg放置到当前WEB根目录的/WEB-INF/下。部署好web工程,用浏览器访问Servlet看下效果吧!是不是下载成功了。呵呵,您可以将下载到本地的excel报表用打印机打印出来,这样您就大功告成了。完事了我们就思考:我们发现,我们做的方法,不管是本地调用,还是在WEB服务器端用Servlet调用;不管是输出学生列表,还是图书列表信息,代码都几乎一样,而且这些数据我们很容器结合后台的DAO操作数据库动态获取。恩,类和方法的通用性和灵活性开始有点感觉了。好啦,祝您学习愉快!
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lenotang/archive/2008/08/24/2823230.aspx
posted @
2010-11-24 09:32 David1228 阅读(1066) |
评论 (0) |
编辑 收藏