linux下apache ftpserver的安装配置

apache-ftpd安装过程非常简单,但是需要做一些配置,一个是用户的配置另外一个就是端口的配置,在防火墙iptables打开的情况需要配置两个端口一个用与ftp连接一个用于ftp数据的传输。

从官方网站下载http://mina.apache.org/ftpserver-project/downloads.html ,下载linux包ftpserver-1.0.6.tar.gz

1.安装文件

比如安装到路径/usr/local/apache-ftpd

tar zxvf ftpserver-1.0.6.tar.gz
cp ftpserver-1.0.6 /usr/local/apache-ftpd

2.配置用户

编辑文件res/conf/user.properties

vi res/conf/user.properties

配置用户admin并设置ftp保存的文件路径,注意对目录的可写权限是writepermission=true,要不然不能上传文件

# Password is "admin"
ftpserver.user.admin.userpassword=21232F297A57A5A743894A0E4A801FC3
ftpserver.user.admin.homedirectory=/usr/local/ftp/
ftpserver.user.admin.enableflag=true
ftpserver.user.admin.writepermission=true
ftpserver.user.admin.maxloginnumber=0
ftpserver.user.admin.maxloginperip=0
ftpserver.user.admin.idletime=0
ftpserver.user.admin.uploadrate=0
ftpserver.user.admin.downloadrate=0

注意这里的ftp文件路径是/usr/local/ftp/,需要创建这个目录

mkdir /usr/local/ftp

3.配置连接端口

编辑文件res/conf/ftpd-typical.xml

vi res/conf/ftpd-typical.xml

在listeners节点下加入数据监听接口

<listeners>
	<nio-listener name="default" port="2121">
		<ssl>
			<keystore file="./res/ftpserver.jks" password="password" />
		</ssl>
		<data-connection idle-timeout="30">
		<active local-port="2120"/>
		<passive ports="2120" />
		</data-connection>
	</nio-listener>
</listeners>

这里配置的端口是2121和2120,所以防火墙iptables需要开启这两个端口其他机器才能访问这个ftp的2121端口

4.创建启动脚本并配置位开机启动

在bin目录下创建start.sh脚本,内容如下

/usr/local/apache-ftpd/bin/ftpd res/conf/ftpd-typical.xml &

保存并设置脚本可执行的权限

chmod +x bin/start.sh

开机启动,将启动脚本加入到开机执行脚本中

 vi /etc/rc.local

在文件中加入下面一行

/usr/local/apache-ftpd/bin/start.sh

这样开机的时候就会自动启动ftp服务了

也可以执行start.sh启动ftp 如

bin/start.sh

到此安装过程全部结束,如果想停止ftp服务只能通过ps找到进程将进程杀死.

以上配置完成之后ftp访问路径ftp://admin:admin@ip:2121/ 可以在浏览器地址栏输入进行验证ftp服务是否已经启动好。

PHP防盗链

盗链是指服务提供商自己不提供服务的内容,通过技术手段绕过其它有利益的最终用户界面(如广告),直接在自己的 网站上向最终用户提供其它服务提供商的服务内容,骗取最终用户的浏览和点击率。受益者不提供资源或提供很少的资源,而真正的服务提供商却得不到任何的收 益。做好防止盗链的工作,是每个网站开发者的重要工作。

做好防盗链工作能给网站服务器减少不少压力,这里我们分享一种php防盗链的实现方法:

一般的下载的步骤:查找->输出查找结果列表->进入软件详细页面->点击下载按钮->打开下载页面->点击下载,开始下载

我的方法就是在下载页面做文章

首先在网站的公共文件里定义一个$key=sdkfjwojf32413这相当于一个密钥一样

在下载页面生成一个随机数:$certcode = ‘84615354’ (每次打开生成的都不一样)

然后用以上两个变量和软件的ID生成一个md5()加密串

然后生成软件的真实下载地址:file.php?id=5&codekey=ksfjwofsdkfsf

这里的id是软件的编号可以根据他从数据库找到软件地址 $codekey=md5($id.$certcode.$key)
然后把certcode保存到session里,

在file.php的参数里面得到的codekey和id再从公共文件里得到$key 再从session里得到$certcode

对codekey进么验证,看是否正确,如果不正确就退出,否则就进行如下操作

1、删除session(再次打开这个地址就无效了)

2、从数据库里读取软件地址,然后读取软件内容,并输出(用PHP的文件读取方法输出要下载的软件内容而不是直接把地址给他下载)

这样如果要下载,就必须打开你自己的下载页面,从你的下载页面打开地址才能进行下载,而且下载地址每次都不一样,因为生成的随机数不一样

别的地方就算连到你的下载地址,也是下载不了的。

拓展阅读(具体实现):

1.简单防盗链

  1. $ADMIN[defaulturl] = “http://www.vvschool.cn/404.htm”;//盗链返回的地址
  2. $okaysites = array(“http://www.vvschool.cn/”,“http://www.siyizhu.com”); //白名单
  3. $ADMIN[url_1] = “http://www.vvschool.cn/temp/download/”;//下载地点1
  4. $ADMIN[url_2] = “”;//下载地点2,以此类推
  5. $reffer = $HTTP_REFERER;
  6. if($reffer) {
  7. $yes = 0;
  8. while(list($domain$subarray) = each($okaysites)) {
  9. if (ereg($subarray,“$reffer”)) {
  10. $yes = 1;
  11. }
  12. }
  13. $theu = “url”.“_”.“$site”;
  14. if ($ADMIN[$theu] AND $yes == 1) {
  15. header(“Location: $ADMIN[$theu]/$file”);
  16. else {
  17. header(“Location: $ADMIN[defaulturl]”);
  18. }
  19. else {
  20. header(“Location: $ADMIN[defaulturl]”);
  21. }?>

使用方法:将上述代码保存为dao4.php,比如我测试用的validatecode.rar在我的站点http://vvschool.cn/temp/download里面,则用以下代码表示下载连接.

文件名?site=1&file=文件

2.服务器防盗链

3.软件下载的防盗链方法

  1. //放置下载软件的根目录相对于当前脚本目录的相对目录
  2. $fileRelPath = “../../software”;
  3. //例外允许连接的网址,注意:自身域名不需要填入,设定为肯定可以下载,
  4. // 空字符串(“”)表示直接输入网址下载的情况
  5. $excludeReferArr = array(“www.wreny.com”“wreny.com”);
  6. chdir($fileRelPath);
  7. $fileRootPath = getcwd() .“/”;
  8. $filePath=$HTTP_GET_VARS[“file”];
  9. $url=parse_url($_SERVER[“HTTP_REFERER”]);
  10. if($url[host]!=$_SERVER[“HTTP_HOST”] && !in_array($referHost$excludeReferArr)){
  11. ?>

其实,反盗链方式也有不少, 这里只列出一个大概思想作为参考:⑴ IIS 反盗链, 利用ISAPI_Rewrite,可作为Windows下反盗链的一个解决方案;⑵ 图片反盗链,在图片中加入水印,虽然盗链者可以达到目的,但是却也在为自己的网站做宣传。

CodeIgniter 防止XSS攻击

odeIgniter 包含了跨站脚本攻击的防御机制,它可以自动地对所有POST以及COOKIE数据进行过滤,或者您也可以针对单个项目来运行它。默认情况下,它 不会 全局运行,因为这样也需要一些执行开销,况且您也不一定在所有情况下都用得到它.

XSS过滤器会查找那些常被用来触发JavaScript或者其他类型的企图劫持cookie或进行其它恶意行为的代码. 如果发现任何不允许的内容,它将把那些内容转换为字符实体,以确保安全.

注意: 此函数只应该用来处理那些提交过来的数据. 它不适合在常规运行时使用,因为它执行时的开销也是不容忽视的.

1、要使用XSS过滤器对数据进行过滤,请使用此函数:

$this->security->xss_clean()

使用示例:

$data = $this->security->xss_clean($data);

2、如果你希望过滤器能自动过滤所有被访问到的POST或者COOKIE数据,请打开你的 application/config/config.php 文件,进行如下设置即可启用自动过滤:

$config['global_xss_filtering'] = TRUE;

说明: 如果你使用表单验证类,同样也有XSS过滤的选项.

如果开启了全局xss过滤,则获取表单数据时可以直接使用:

$this->input->post('name')

如果,没有开启全局设置,只是希望对单一的数据进行xss过滤,我们可以这样使用:

$this->input->post('name',TRUE)

3、第二个可选的参数, is_image, 允许此函数对 图片进行检测以发现那些潜在的 XSS 攻击, 这对于保证文件上传的安全非常有用. 当此参数被设置为 TRUE 时, 此函数的返回值不是一个修改过的字符串而是一个布尔值, 如果图片是安全的则返回 TRUE, 相反, 如果图片中包含有潜在的、可能会被浏览器尝试运行的恶意信息, 函数将返回FALSE.

if ($this->security->xss_clean($file, TRUE) === FALSE)
{
    // file failed the XSS test
}

spring mvc下载文件简单实现

文件下载有好多种方式,通过返回值,通过servlet的返回输出流等,我们这里使用spring的controller简单实现如何下载文件,并从url传入参数。

这是controller的简单实现,使用aspose.cells解析excel模板,并保存到输出流就可以下载了。

/**
* 下载文件,参数可以通过url传入
*/
@RequestMapping(value="/download/{fileName}.xls")
public void download(@RequestParam(required=false,value="arg1") String arg1,HttpServletRequest request, HttpServletResponse response){
	
	//解析excel模板
	WorkbookDesigner designer = new WorkbookDesigner();  
	String template_file_path = "d:/aspose/cell_sample.xls";  
	Workbook wb = new Workbook(template_file_path); 
	designer.setWorkbook(wb);
	
	//解析数据
	//designer.setDataSource("list", new MapData(getHashMapList()));//map list作为数据源
	//designer.process();//全自动赋值
	
	//文件输出到 输出流
	wb.save(response.getOutputStream(), SaveFormat.EXCEL_97_TO_2003);
	
}

在前端的脚本中直接使用url下载代码如下

window.location = escape("/download/myfile.xls?arg1=val1");

以上简易实现文件下载,注意如果是url传入中文的话,tomcat必须配置url的编码模式为utf-8,要不然的话在后台取到的参数会可能是乱码的。

《三体1》8.叶文洁

汪淼摘下V装具后,发现自己的内衣已被冷汗浸透了,很像是从一场寒冷的噩梦中醒来。他走出纳米中心,下楼开车,按丁仪给的地址去杨冬的母亲家。

乱纪元,乱纪元,乱纪元……

这个概念在汪淼的头脑中萦绕。为什么那个世界的太阳运行会没有规律?一个球状的行星,不管其运行轨道是正圆还是偏长的椭圆,其围绕恒星的运动一定是周期性的,全无规律的运行是不可能的……汪淼突然对自己很恼火,他使劲地摇头想赶走头脑中的这一切,不过是个游戏嘛,但他失败了。

乱纪元,乱纪元,乱纪元……

见鬼!别去想它!!为什么非想它不可?为什么?!

很快,汪淼找到了答案。他已经有很多年没有玩过电子游戏了,这些年来电子游戏的软硬件技术显然已经进化了很多,其中的虚拟现实场景和附加效果都是他学生时代所无法比拟的。但汪淼明白,《三体》的真实不在于此。记得在大三的一次信息课中,教授挂出了两幅大图片,一幅是画面庞杂精细的《清明上河图》,另一幅是一张空旷的天空照片,空荡荡的蓝天上只有一缕似有似无的白云。教授问这两幅画中哪一幅所包含的信息量更大,答案是后者要比前者大一至两个数量级!

《三体》正是这样,它的海量信息是隐藏在深处的,汪淼能感觉到,但说不清。他突然悟出,《三体》的不寻常在于,与其他的游戏相比,它的设计者是反其道而行之——一般游戏的设计者都是尽可能地增加显示的信息量,以产生真实感;但《三体》的设计者却是在极力压缩信息量,以隐藏某种巨大的真实,就像那张看似空旷的天空照片。

汪淼放松了思想的缰绳,任其回到《三体》世界。

飞星!关键在于不引人注意的飞星,一颗飞星,二颗飞星,三颗飞星……这分别意味着什么?

正想着,车已开到他要去的小区大门了。

在要去的那栋楼门口,汪淼看到一位六十岁左右的头发花白、身材瘦削的女性,戴着眼镜,提着一个大菜篮子吃力地上楼梯。他猜她大概就是自己要找的人,一问,她果然就是杨冬的母亲,叶文洁。听汪淼说明来意后,她露出发自内心的感动,她是汪淼常见到的那种老知识分子,岁月的风霜已消去了他们性情中所有的刚硬和火热,只剩下如水的柔和。

汪淼拿过菜篮子同她一起上了楼,走进她的家门后发现,这里并不像他想象的那么冷清——有三个孩子在玩耍,最大的不超过五岁,小的刚会走路。杨母告诉汪淼,这都是邻居的孩子。

“他们喜欢在我这儿玩儿,今天是星期天,他们的父母要加班,就把他们丢给我了……哦,楠楠,你的画儿画完了吗?嗯,真好看,起个题目吧!太阳下的小鸭子,好,奶奶给你题上,再写上六月九日,楠楠作……中午你们都想吃什么呢?洋洋?烧茄子?好好;楠楠?昨天吃过的荷兰豆?好好;你呢,咪咪?肉肉?不,你妈妈说了,不要吃那么多肉肉,不好消化的,吃鱼鱼好吗?看奶奶买回来的这么大的鱼鱼……”

她肯定想要孙子或孙女,但即使杨冬活着,会要孩子吗?看着杨母和孩子们投入地对话,汪淼心想。

杨母将篮子提进厨房,出来后对汪淼说:“小汪啊,我先去把菜泡上,现在的蔬菜农药残留很多,给孩子们吃至少要泡两小时以上……你可以先到冬冬的房间里看看。”

杨母最后一句看似无意的提议令汪淼陷入紧张和不安之中,她显然看出了汪淼此行在内心深处的真正目的。她说完就转身回到厨房,没有看汪淼一眼,自然看不到他的窘态,她这几乎天衣无缝的善解人意令汪淼一阵感动。

汪淼转身穿过快乐的孩子们,走向杨母刚才指向的那个房间。他在门前停住了,突然被一种奇异的感觉所淹没,仿佛回到了少年多梦的时节,一些如清晨露珠般晶莹脆弱的感受从记忆的深处中浮起,这里面有最初的伤感和刺痛,但都是玫瑰色的。

汪淼轻轻推开门,扑面而来的淡淡的气息是他没有想到的,那是森林的气息,他仿佛进入了一间护林人的林间小屋。墙壁被一条条棕色的树皮覆盖着,三只凳子是古朴的树桩,写字台也是由三个较大的树桩拼成的,还有那张床,铺的显然是东北的乌拉草。这一切都很粗糙、很随意,没有刻意表现出某种美感。以杨冬的职位,她的收入是很高的,可以在任何一处高尚社区买下房子。可她一直同母亲住在这里。

汪淼走到树桩写字台前,上面的陈设很简单,没有与学术有关的东西。也没有与女性有关的东西;也许都已经拿走了,也许从来就没在这里存在过。他首先注意到一张镶在木镜框中的黑白照片,是杨冬母女的合影,照片中的杨冬正值幼年,母亲蹲下正好同她一样高。风很大,将两人的头发吹到一起。照片的背景很奇怪,天空呈网格状,汪淼仔细察看支撑那网络的粗大的钢铁结构。推想那是一个抛物面天线或类似的东西,因为巨大,它的边缘超出了镜头。

照片中,小杨冬的大眼睛中透出一种令汪淼心颤的恐惶,仿佛照片外的世界令她恐惧似的。汪淼注意到的第二件东西是放在写字台一角的一本厚厚的大本子,首先令他迷惑的是本子的材质,他看到封面上有一行稚拙的字:“杨冬的桦皮本”,这才知道这本子是桦树皮做的,时光已经使银白色的桦皮变成暗黄。他伸手触了一下本子,犹豫了一下又缩了回来。

“你看吧,那是冬冬小时候的画儿。”杨母在门口说。

汪淼捧起桦皮本,轻轻地一页页翻看。每幅画上都有日期,明显是母亲为女儿注上的,就像他刚进门时看到的那样。汪淼又发现了一件多少让他不可理解的事:从画上的日期看,这时的杨冬已经三岁多了,这么大的孩子通常都能够画出比较分明的人或物体的形状;但杨冬的画仍然只是随意纷乱的线条,汪淼从中看出了一种强烈的恼怒和绝望,一种想表达某种东西又无能为力的恼怒和绝望,这种感觉,是这种年龄的普通孩子所不具有的。

杨母缓缓地坐到床沿上,双眼失神地看着汪淼手中的桦皮本,她女儿就是在这里,在安睡中结束了自己的生命。汪淼在杨母身边坐下,他从来没有过如此强烈的愿望,要与他人分担痛苦。杨母从汪淼手中拿过桦皮本,抱在胸前,轻声说:“我对冬冬的教育有些不知深浅,让她太早接触了那些太抽象、太终极的东西。当她第一次表现出对那些抽象理论的兴趣时,我告诉她,那个世界,女人是很难进人的。她说居里夫人不是进人了吗?我告诉她,居里夫人根本没有进入,她的成功只是源于勤奋和执著,没有她,那些工作别人也会完成,倒是像吴健雄(当代最杰出的物理学家之一,在实验物理学研究上取得伟大的成就。她在实验室中首次证明了李政道和杨振宁关于弱相互作用中宇称不守恒的理论推测,推翻了宇称守恒定律。)这样的女人还比她走得远些,但那真的不是女人的世界。女性的思维方式不同于男性,这没有高下之分,对世界来说都是必不可少的。”

“冬冬没有反驳我。到后来,我真的发现她身上有一些特殊的东西,比如给她讲一个公式,别的孩子会说“这公式真巧妙”之类的,她则会说这公式真好看、真漂亮,那神情就像她看到一朵漂亮的野花一样。她父亲留下了一堆唱片,她听来听去,最后选择了一张巴赫的反复听,那是最不可能令孩子,特别是女孩子入迷的音乐了。开始我以为她是随意为之,但问她感受时,这孩子说:她看到一个巨人在大地上搭一座好大好复杂的房子,巨人一点一点地搭着,乐曲完了,大房子也就搭完了……”

“您对女儿的教育真是成功。”汪霖感慨地说。

“不,是失败啊!她的世界太单纯,只有那些空灵的理论。那些东西一崩溃,就没有什么能支撑她活下去了。”

“叶老师,您这么想我觉得也不对,现在发生了一些让我们难以想象的事,这是一次空前的理论灾难,做出这种选择的科学家又不只是她一人。”

“可只有她一个女人,女人应该像水一样的,什么样的地方都能淌得过去啊。”

……

告辞时,汪淼才想到了来访的另一个目的,于是他向杨母说起了观测宇宙背景辐射的事。

“哦,这个,国内有两个地方正在做,一个在乌鲁木齐观测基地,好像是中科院空间环境观测中心的项目;另一个很近,就在北京近郊的射电天文观测基地,是中科院和北大那个联合天体物理中心搞的。前面那个是实际地面观察,北京这个只是接收卫星数据,不过数据更准确、全面一些。那里有我的一个学生,我帮你联系一下吧。”杨母说着,去找电话号码,然后给那个学生打电话,似乎很顺利。

“没问题的,我给你个地址,你直接去就行。他叫沙瑞山,明天正好值夜班……你好像不是搞这专业的吧?”杨母放下电话问。

“我搞纳米,我这是为了……另外一些事情。”汪淼很怕杨母追问下去,但她没有。

“小汪啊,你脸色怎么这么不好?好像身体很虚的。”杨母关切地问。

“没什么,就是这样儿。”汪淼含糊地说。

“你等等,”杨母从柜子里拿出一个小木盒,汪淼看到上面标明是人参,“过去在基地的一位老战士前两天来看我,带来这个……不不,你拿去,人工种植的,不是什么珍贵的东西,我血压高,根本用不着的。你可以切成薄片泡茶喝,我看你脸色,好像血很亏的样子。年轻人,一定要爱护自己啊。”

汪淼的心中涌起一股暖流,双眼湿润了,他那颗两天来绷得紧紧的心脏像被放到了柔软的天鹅绒上。“叶老师。我会常来看您的。”他接过木盒说。

linux下vi命令大全

进入vi的命令
vi filename :打开或新建文件,并将光标置于第一行首
vi +n filename :打开文件,并将光标置于第n行首
vi + filename :打开文件,并将光标置于最后一行首
vi +/pattern filename:打开文件,并将光标置于第一个与pattern匹配的串处
vi -r filename :在上次正用vi编辑时发生系统崩溃,恢复filename
vi filename….filename :打开多个文件,依次进行编辑

移动光标类命令
h :光标左移一个字符
l :光标右移一个字符
space:光标右移一个字符
Backspace:光标左移一个字符
k或Ctrl+p:光标上移一行
j或Ctrl+n :光标下移一行
Enter :光标下移一行
w或W :光标右移一个字至字首
b或B :光标左移一个字至字首
e或E :光标右移一个字至字尾
) :光标移至句尾
( :光标移至句首
}:光标移至段落开头
{:光标移至段落结尾
nG:光标移至第n行首
n+:光标下移n行
n-:光标上移n行
n$:光标移至第n行尾
H :光标移至屏幕顶行
M :光标移至屏幕中间行
L :光标移至屏幕最后行
0:(注意是数字零)光标移至当前行首
$:光标移至当前行尾

屏幕翻滚类命令
Ctrl+u:向文件首翻半屏
Ctrl+d:向文件尾翻半屏
Ctrl+f:向文件尾翻一屏
Ctrl+b;向文件首翻一屏
nz:将第n行滚至屏幕顶部,不指定n时将当前行滚至屏幕顶部。

插入文本类命令
i :在光标前
I :在当前行首
a:光标后
A:在当前行尾
o:在当前行之下新开一行
O:在当前行之上新开一行
r:替换当前字符
R:替换当前字符及其后的字符,直至按ESC键
s:从当前光标位置处开始,以输入的文本替代指定数目的字符
S:删除指定数目的行,并以所输入文本代替之
ncw或nCW:修改指定数目的字
nCC:修改指定数目的行

删除命令
ndw或ndW:删除光标处开始及其后的n-1个字
do:删至行首
d$:删至行尾
ndd:删除当前行及其后n-1行
x或X:删除一个字符,x删除光标后的,而X删除光标前的
Ctrl+u:删除输入方式下所输入的文本

搜索及替换命令
/pattern:从光标开始处向文件尾搜索pattern
?pattern:从光标开始处向文件首搜索pattern
n:在同一方向重复上一次搜索命令
N:在反方向上重复上一次搜索命令
:s/p1/p2/g:将当前行中所有p1均用p2替代
:n1,n2s/p1/p2/g:将第n1至n2行中所有p1均用p2替代
:g/p1/s//p2/g:将文件中所有p1均用p2替换

选项设置
all:列出所有选项设置情况
term:设置终端类型
ignorance:在搜索中忽略大小写
list:显示制表位(Ctrl+I)和行尾标志($)
number:显示行号
report:显示由面向行的命令修改过的数目
terse:显示简短的警告信息
warn:在转到别的文件时若没保存当前文件则显示NO write信息
nomagic:允许在搜索模式中,使用前面不带“\”的特殊字符
nowrapscan:禁止vi在搜索到达文件两端时,又从另一端开始
mesg:允许vi显示其他用户用write写到自己终端上的信息

最后行方式命令
:n1,n2 co n3:将n1行到n2行之间的内容拷贝到第n3行下
:n1,n2 m n3:将n1行到n2行之间的内容移至到第n3行下
:n1,n2 d :将n1行到n2行之间的内容删除
:w :保存当前文件
:e filename:打开文件filename进行编辑
:x:保存当前文件并退出
:q:退出vi
:q!:不保存文件并退出vi
:!command:执行shell命令command
:n1,n2 w!command:将文件中n1行至n2行的内容作为command的输入并执行之,若不指定n1,n2,则表示将整个文件内容作为command的输入
:r!command:将命令command的输出结果放到当前行

寄存器操作
“?nyy:将当前行及其下n行的内容保存到寄存器?中,其中?为一个字母,n为一个数字
“?nyw:将当前行及其下n个字保存到寄存器?中,其中?为一个字母,n为一个数字
“?nyl:将当前行及其下n个字符保存到寄存器?中,其中?为一个字母,n为一个数字
“?p:取出寄存器?中的内容并将其放到光标位置处。这里?可以是一个字母,也可以是一个数字
ndd:将当前行及其下共n行文本删除,并将所删内容放到1号删除寄存器中。

VI的使用
——————————————————————————–

一、插入文本
┌──┬────────────┐
│命令│描述          │
├──┼────────────┤
│i  │在当前字符前插入文本  │
├──┼────────────┤
│I  │在行首插入文本      │
├──┼────────────┤
│a  │在当前字符后添加文本  │
├──┼────────────┤
│A  │在行末添加文本     │
├──┼────────────┤
│o  │在当前行后面插入一空行 │
├──┼────────────┤
│O  │在当前行前面插入一空行 │
├──┼────────────┤
│R  │以改写方式输入文本   │
└──┴────────────┘
二、移动光标
┌─────┬───────────┐
│命令   │描述         │
├─────┼───────────┤
│j或下箭头 │向下移动一行     │
├─────┼───────────┤
│k或上箭头 │向上移动一行     │
├─────┼───────────┤
│h或左箭头 │左移一个字符     │
├─────┼───────────┤
│l或右箭头 │右移一个字符     │
├─────┼───────────┤
│w     │右移一个词      │
├─────┼───────────┤
│W     │右移一个以空格分隔的词│
├─────┼───────────┤
│b     │左移一个词      │
├─────┼───────────┤
│B     │左移一个以空格分隔的词│
├─────┼───────────┤
│0     │移到行首       │
│Ctrl-F  │向前翻页       │
├─────┼───────────┤
│Ctrl-B  │向后翻页       │
├─────┼───────────┤
│nG    │到第n行        │
├─────┼───────────┤
│G     │到最后一行      │
└─────┴───────────┘
三、替换文本
┌─────┬──────┐
│命令   │描述    │
├─────┼──────┤
│$     │到行尾   │
├─────┼──────┤
│(     │到句子的开头│
├─────┼──────┤
│)     │到句子的末尾│
├─────┼──────┤
│{     │到段落的开头│
├─────┼──────┤
│}     │到段落的末尾│
└─────┴──────┘

四、删除文本
┌───┬───────────┐
│命令 │描述          │
├───┼───────────┤
│r   │替换一个字符      │
├───┼───────────┤
│c   │修改文本直到按下Esc健 │
├───┼───────────┤
│cw  │修改下一个词      │
├───┼───────────┤
│cnw  │修改接下来的n个词   │
└───┴───────────┘
五、文本编辑
┌──┬──────────────────────┐
│命寺│描述                    │
├──┼──────────────────────┤
│yy │将一行文本移到缺省缓冲区中          │
├──┼──────────────────────┤
│yn │将下一个词移到缺省缓冲区中          │
├──┼──────────────────────┤
│ynw │将后面的n个词移到缺省缓冲区中        │
├──┼──────────────────────┤
│p  │如果缺省缓冲区中包含一行文本,则在当前   │
│  │行后面插入一个空行井将缺省缓冲区中的声   │
│  │容粘贴到这一行中;如果缺省缓冲区中包含   │
│  │多个词,把这些词粘贴到光标的右边.     │
├──┼──────────────────────┤
│P  │如果缺省缓冲区中包含一行文本,则正当前    │
│   │行前面插入一个空行井将缺省缓冲区中的内    │
│  │容粘贴到这一行中;如果缺省缓冲区中包含    │
│   │多个词,把这些词粘贴到光标的左边


└──┴──────────────────────┘
六、保存退出
┌───────────┬───────────────┐
│命令         │描述             │
├───────────┼───────────────┤
│zz          │保存并退出          │
├───────────┼───────────────┤
│:w filename      │写入文件            │
├───────────┼───────────────┤
│:W          │写入文件           │
├───────────┼───────────────┤
│:x          │保存(如果当前文件修改过)并退出│
├───────────┼───────────────┤
│:q!          │不保存文件,直接退出      │
├───────────┼───────────────┤
│:q          │退出vi            │

VI常用技巧

VI命令可以说是Unix/Linux世界里最常用的编辑文件的命令了,但是因为它的命令集众多,很多人都不习惯使用它,其实您只需要掌握基本命令,然后加以灵活运用,就会发现它的优势,并会逐渐喜欢使用这种方法。本文旨在介绍VI的一些最常用命令和高级应用技巧。

一、基本命令介绍

—- 1.光标命令

k、j、h、l——上、下、左、右光标移动命令。虽然您可以在Linux中使用键盘右边的4个光标键,但是记住这4个命令还是非常有用的。这4个键正是右手在键盘上放置的基本位置。
nG——跳转命令。n为行数,该命令立即使光标跳到指定行。
Ctrl+G——光标所在位置的行数和列数报告。
w、b——使光标向前或向后跳过一个单词。
—- 2.编辑命令
i、a、r——在光标的前、后以及所在处插入字符命令(i=insert、a=append、r=replace)。
cw、dw——改变(置换)/删除光标所在处的单词的命令 (c=change、d=delete)。
x、d$、dd——删除一个字符、删除光标所在处到行尾的所有字符以及删除整行的命令。
—- 3.查找命令
—- /string、?string——从光标所在处向后或向前查找相应的字符串的命令。
—- 4.拷贝复制命令
—- yy、p——拷贝一行到剪贴板或取出剪贴板中内容的命令。

二、常见问题及应用技巧

—- 1.在一个新文件中读/etc/passwd中的内容,取出用户名部分。
—- vi file
—- :r /etc/passwd 在打开的文件file中光标所在处读入/etc/passwd
—- :%s/:.*//g 删除/etc/passwd中用户名后面的从冒号开始直到行尾的所有部分。
—- 您也可以在指定的行号后读入文件内容,例如使用命令“:3r /etc/passwd”从新文件的第3行开始读入 /etc/passwd的所有内容。
—- 我们还可以使用以下方法删掉文件中所有的空行及以#开始的注释行。
—- #cat squid.conf.default | grep -v ^$ | grep -v ^#

—- 2.在打开一个文件编辑后才知道登录的用户对该文件没有写的权限,不能存盘,需要将所做修改存入临时文件。
—- vi file
—- :w /tmp/1 保存所做的所有修改,也可以将其中的某一部分修改保存到临时文件,例如仅仅把第20~59行之间的内容存盘成文件/tmp/1,我们可以键入如下命令。
—- vi file
—- :20,59w /tmp/1

—- 3.用VI编辑一个文件,但需要删除大段的内容。
—- 首先利用编辑命令“vi file”打开文件,然后将光标移到需要删除的行处按Ctrl+G显示行号,再到结尾处再按Ctrl+G,显示文件结尾的行号。
—- :23,1045d 假定2次得到的行号为23和1045,则把这期间的内容全删除,也可以在要删除的开始行和结束行中用ma、mb命令标记,然后利用“:a,bd”命令删除。

—- 4.在整个文件的各行或某几行的行首或行尾加一些字符串。
—- vi file
—- :3,$s/^/some string / 在文件的第一行至最后一行的行首插入“some string”。
—- :%s/$/some string/g 在整个文件每一行的行尾添加“some string”。
—- :%s/string1/string2/g 在整个文件中替换“string1”成“string2”。
—- :3,7s/string1/string2/ 仅替换文件中的第3行到第7行中的“string1”成“string2”。
—- 注意: 其中s为substitute,%表示所有行,g表示global。

—- 5.同时编辑2个文件,拷贝一个文件中的文本并粘贴到另一个文件中。
—- vi file1 file2
—- yy 在文件1的光标处拷贝所在行
—- :n 切换到文件2 (n=next)
—- p 在文件2的光标所在处粘贴所拷贝的行
—- :n 切换回文件1

—- 6.替换文件中的路径。
—- 使用命令“:%s#/usr/bin#/bin#g”可以把文件中所有路径/usr/bin换成/bin。也可以使用命令“:%s//usr/bin//bin/g”实现,其中“”是转义字符,表明其后的“/”字符是具有实际意义的字符,不是分隔符。

java调用linux命令

Java可以直接调用Linux命令,形式如下:
Runtime.getRuntime().exec(command)
举例:运行ls,top命令可以这样:
Runtime.getRuntime().exec(“ls”);
但是这样执行时没有任何输出,原因:
调用Runtime.exec方法将产生一个本地的进程,并返回一个Process子类的实例,
(注意:Runtime.getRuntime().exec(command)返回的是一个Process类的实例),
该实例可用于控制进程或取得进程的相关信息. 由于调用Runtime.exec方法所创建的子进程没有自己的终端或控制台,因此该子进程的标准IO(如stdin,stdou,stderr)都通过Process.getOutputStream(),Process.getInputStream(), Process.getErrorStream()方法重定向给它的父进程了.用户需要用这些stream来向子进程输入数据或获取子进程的输出. 可以采用如下方法:
try
{
Process process = Runtime.getRuntime().exec (“ls”);
InputStreamReader ir=new InputStreamReader(process.getInputStream());
LineNumberReader input = new LineNumberReader (ir);
String line;
while ((line = input.readLine ()) != null){
System.out.println(line)
}
catch (java.io.IOException e){
System.err.println (“IOException ” + e.getMessage());
}

apache+flowplayer支持flv流媒体拖动播放

使用flowplay播放flv文件,默认情况下apache提供的http服务是不支持拖动到还没有缓冲好的区域,只能在缓冲区范围内拖动,想要支持拖动到任意位置播放,必须需要服务器的支持,并且flowplay也需要插件来支持。

1.linux下apache服务器安装mod_flvx.so模块

从这个地址https://github.com/osantana/mod_flvx下载mod_flvx.c文件,编译并安装

apxs -c -i ./mod_flvx.c

apxs是apache自带的工具在apache安装目录的bin目录下

在conf/httpd.conf配置文件中加入两行配置

LoadModule flvx_module modules/mod_flvx.so
AddHandler flv-stream .flv

重启apache服务

bin/apachectl retart

这样服务器端的配置就完成了

2.下载flowplayer播放器和插件

下载flash版本的免费flowplayer:https://flowplayer.org/pricing/player.html

下载插件Pseudostreaming插件http://flash.flowplayer.org/plugins/streaming/pseudostreaming.html

把插件复制到flowplay目录下

image

打开example文件夹里面的示例index.html,脚本部分修改如下

<!-- this will install flowplayer inside previous A- tag. -->
<script>
	var fp = flowplayer("player", "../flowplayer-3.2.18.swf",			
	{
		// configure clip to use "apache" plugin for providing video data
		clip: {
			provider: 'apache',
			url:'http://192.168.1.25/video/1440749458644.flv',
			scaling: 'fit'
		},			 
		// streaming plugins are configured normally under the plugins node
		plugins: {
			apache: {
				url: "../flowplayer.pseudostreaming-3.2.13.swf"
			}
		}
	});
</script>

以上完成前端的插件加载并播放视频

3.准备视频文件

视频文件需要处理才能支持拖动播放,yamdi(http://yamdi.sourceforge.net/)和flvtool2(http://blog.inlet-media.de/flvtool2/)都是对flv文件 进行MetaData注入的工具,貌似yamdi效率更高一些,处理命令如下

yamdi -i sample.flv -o sample_with_metadata.flv
flvtool2 -U sample.flv

以上工具都有windows和linux版本,都可以从官方网站下载,linux下自然是要编译安装了。准备好视频放入到apache的htdocs/video目录中,当然根据实际情况放到正确的发布目录里面,然后运行上面的示例页面,拖动到后续还没加载的区域看看是否已经能够正常播放了。

总结

简单的一个视频拖动播放的后面有不少的事情要做好,apache提供的服务是正常的http协议,在没有处理之前播放flv文件和下载没有什么区别,数据从文件开始的地方开始读取到结束,拖动的时候就不一样了是在请求后面加上一次参数?start=从某个时间点开始传送数据,所以呢服务端必须支持这样的请求,因此就出现了上面的配置过程。

aspose-word for java使用map作为数据源

aspose对word的操作和对excel的操作是分为两个独立的jar包实现的,同样的word模板的使用也是非常之方便,依然很遗憾默认并没有实现使用map数据作为数据源,这里我们来实现数据源接口IMailMergeDataSource来提供map数据源。

1.word模板,使用MergeFeild绑定数据

在word模板中通过菜单”插入→文档部件→域”插入MergeField域

1 2

根据上面插入域的方法,我们来创建一个简单的模板,使用一个map对象和一个map的列表

 

12

注意一个区域是以TableStart:和TableEnd:结束,冒号后面是数据源的名字.

2.实现IMailMergeDataSource接口提供map数据源

/**
 * 实现对HashMap的支持
 */
public class MapData implements IMailMergeDataSource  {

	@SuppressWarnings("rawtypes")
	private List<Map> dataList;

	private int index;

	// word模板中的«TableStart:tableName»«TableEnd:tableName»对应
	private String tableName = null;

	/**
	 * @param dataList
	 *            数据集
	 * @param tableName
	 *            与模板中的Name对应
	 */
	@SuppressWarnings("rawtypes")
	public MapData(List<Map> dataList, String tableName) {
		this.dataList = dataList;
		this.tableName = tableName;
		index = -1;
	}

	/**
	 * @param data
	 *            单个数据集
	 * @param tableName
	 *            与模板中的Name对应
	 */
	@SuppressWarnings("rawtypes")
	public MapData(Map data, String tableName) {
		if (this.dataList == null) {
			this.dataList = new ArrayList<Map>();
			this.dataList.add(data);
		}
		this.tableName = tableName;
		index = -1;
	}

	/**
	 * 获取结果集总数
	 * 
	 * @return
	 */
	private int getCount() {
		return this.dataList.size();
	}

	@Override
	public IMailMergeDataSource getChildDataSource(String arg0)
			throws Exception {
		return null;
	}

	@Override
	public String getTableName() throws Exception {
		return this.tableName;
	}

	/**
	 * 实现接口 获取当前index指向数据行的数据 将数据存入args数组中即可
	 * 
	 * @return ***返回false则不绑定数据***
	 */
	@Override
	public boolean getValue(String key, Object[] args) throws Exception {
		if (index < 0 || index >= this.getCount()) {
			return false;
		}
		if (args != null && args.length > 0) {
			args[0] = this.dataList.get(index).get(key);
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 实现接口 判断是否还有下一条记录
	 */
	@Override
	public boolean moveNext() throws Exception {
		index += 1;
		if (index >= this.getCount()) {
			return false;
		}
		return true;
	}


}

3.实现IMailMergeDataSourceRoot接口以提供多个数据源

/**
 * 提供多个数据源
 * @author Administrator
 *
 */
public class MapDataSet implements  IMailMergeDataSourceRoot {

	/**
	 * 多个数据源
	 */
	private Map<String,IMailMergeDataSource> ds = new HashMap<String,IMailMergeDataSource>();
	
	public MapDataSet(){}

	@Override
	public IMailMergeDataSource getDataSource(String arg0) throws Exception {
		if(this.ds.containsKey(arg0)){
			return this.ds.get(arg0);
		}
		return null;
	}
	/**
	 * 添加一个数据源
	 * @param tableName
	 * @param data
	 */
	public void add(IMailMergeDataSource data){
		try {
			this.ds.put(data.getTableName(), data);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

4.使用实现好的数据源解析word模板

	public static void main(String[] args) throws Exception{
		String template_file_path = "d:/aspose/word_sample.doc";  
		Document doc = new Document(template_file_path);

		//两个数据源
		MapDataSet ds = new MapDataSet();
		ds.add( new MapData(getHashMapData(),"map"));
		ds.add( new MapData(getHashMapList(),"list"));
		
		//主从数据源
		/*
		DataSet dataset = new DataSet();
		DataTable dt1 = mapListToDataTable(getHashMapList(),"dt1");
		DataTable dt2 = mapListToDataTable(getHashMapList(),"dt2");
		dataset.getTables().add(dt1);
		dataset.getTables().add(dt2);
		dataset.getRelations().add(new DataRelation("name_key",dt1.getColumns().get("name"), dt2.getColumns().get("name")));
		doc.getMailMerge().executeWithRegions(dataset);
		*/
		//没有数据的模板清楚掉
		doc.getMailMerge().setCleanupOptions(MailMergeCleanupOptions.REMOVE_UNUSED_REGIONS);
		//自动插入数据
		doc.getMailMerge().executeWithRegions(ds);
		
		doc.save("d:/aspose/word_sample_i.doc");
		
		System.out.println("ok!");
	}
	
	/**
	 * 单个数据
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static HashMap getHashMapData(){
		
		HashMap data = new HashMap();
		
		data.put("name", "fullstacks");
		data.put("age", "30");
		
		return data;
		
	}
	
	/**
	 * hashMap 列表
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	private static List<Map> getHashMapList(){
		 List<Map> datas= new ArrayList<Map>();
		 datas.add(getHashMapData());
		 datas.add(getHashMapData());
		 datas.add(getHashMapData());
		 datas.add(getHashMapData());
		 return datas; 
	}

以上代码执行之后得到的效果如下

13

5.使用主从关系的列表

创建一个word模板如下

14

使用DataSet创建主从关系的数据结构,这里提供一个将Map列表转换为一个DataTable

	/**
	 * map列表转换为datatable
	 * @param data
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static DataTable mapListToDataTable(List<Map> datas,String tableName){
		if(datas == null || datas.size() == 0)return null;
		DataTable dt = new DataTable(tableName);
		Map fistrow = datas.get(0);
		for(Object key: fistrow.keySet()){
			dt.getColumns().add(new DataColumn((String)key,fistrow.get(key).getClass()));			
		}
		for(Map item:datas){
			DataRow dr = dt.newRow();
			for(Object key: item.keySet()){
				dr.set((String)key, item.get(key));
			}
			try {
				dt.getRows().add(dr);
			} catch (ConstraintException e) {
				e.printStackTrace();
			} catch (InvalidConstraintException e) {
				e.printStackTrace();
			}
		}	
		return dt;
	}

构建DataSet数据源

		DataSet dataset = new DataSet();
		DataTable dt1 = mapListToDataTable(getHashMapList(),"dt1");
		DataTable dt2 = mapListToDataTable(getHashMapList(),"dt2");
		dataset.getTables().add(dt1);
		dataset.getTables().add(dt2);
		dataset.getRelations().add(new DataRelation("name_key",dt1.getColumns().get("name"), dt2.getColumns().get("name")));
		doc.getMailMerge().executeWithRegions(dataset);

得到的效果如下

15

总结

以上是实现了一个通用的数据结构map作为aspose word的数据源,如果是结合spring jdbc的话,从数据库中查询出来的结果数据就是一个hashmap的list,这样就可以使用了,不必要转换为datatable那么麻烦,然后如果是多个数据源的话,就可以使用上面实现的MapDataSet实现,已提供多个数据源一次性把word模板解析完毕,如果是主从表的结构数据只能通过自带DataSet来完成了,上面已提供了一个静态方法方便把map列表转换为datatable,如果数据量比较大的话这样遍历可能效率低下,可以直接使用dataredder作为数据源,这样效率更高。

aspose-cells for java使用map作为数据源

使用excel作为模板导出数据是很普遍的应用,而且非常方便,aspose-cells是这样一个商业的软件,使用非常之方便,几行代码就可以搞定将数据自动插入到excel模板中,但是默认的并没有实现以map作为数据源,只是提供了一个借口ICellsDataTable,下面我们来实现这个接口。

1.实现接口ICellsDataTable支持Map的数据

/**
 * 使用hashmap作为数据源
 * @author Administrator
 *
 */
public class MapData implements ICellsDataTable {
	//数据集合  
    @SuppressWarnings("rawtypes")
	private List<Map> dataList = null;  

    //索引  
    private int index;  
      
    //存放dataList当中Map<String, Object>的key  
    private String[] columns = null;  
  
    @SuppressWarnings("rawtypes")
	public MapData(Map data) {  
        if(this.dataList == null) {  
            this.dataList = new ArrayList<Map>();  
        }  
        dataList.add(data);
    }  
      
    @SuppressWarnings("rawtypes")
	public MapData(List<Map> data) {  
        this.dataList = data;  
    }  
      
    /** 
     * 初始化方法 
     */  
    public void beforeFirst() {  
        index = -1;  
        columns = this.getColumns();  
    }  
  
    /** 
     * WorkbookDesigner自动调用 
     * 会将this.getColumns()方法所返回的列 按照顺序调用改方法 
     */  
    @SuppressWarnings("rawtypes")
	public Object get(int columnIndex) {  
        if(index < 0 || index >= this.getCount()) {  
            return null;  
        }  
        Map record = this.dataList.get(index);  
        String columnName = this.columns[columnIndex];  
        return record.get(columnName);  
    }  
  
    /** 
     * 根据columnName返回数据 
     */  
    @SuppressWarnings("rawtypes")
	public Object get(String columnName) {  
        Map record = this.dataList.get(index);  
        return record.get(columnName);  
    }  
  
    /** 
     * 获得列集合 
     */  
    @SuppressWarnings({ "rawtypes", "unchecked" })
	public String[] getColumns() {  
        Map temp = this.dataList.get(0);  
        Set<Entry> entrys = temp.entrySet();  
        List<String> columns = new ArrayList<String>();  
        for (Entry e : entrys) {  
            columns.add((String)e.getKey());  
        }  
        String[] s = new String[entrys.size()];  
        columns.toArray(s);  
        return s;  
    }  
  
    public int getCount() {  
        return this.dataList.size();  
    }  
  
    public boolean next() {  
        index += 1;  
        if(index >= this.getCount())  
        {  
            return false;  
        }  
        return true;  
    }  
  
}

2.使用的示例代码

我们来创建一个简单的excel模板,如下图所示

image

下面的代码将数据插入到这个模板中,这里我们做了两个数据源,分别命名为map和list,在模板的单元格中以&=开始加上数据源的名字加个点后面跟map里面的key名。格式就是&=name.key

public class ExcelUtils {

	public static void main(String[] args) throws Exception{		
		WorkbookDesigner designer = new WorkbookDesigner();  
		String template_file_path = "d:/aspose/cell_sample.xls";  
		Workbook wb = new Workbook(template_file_path); 
		designer.setWorkbook(wb);
				
		//给模板对象设置数据源  
		designer.setDataSource("map", new MapData(getHashMapData()));//hashmap对象作为数据源		
		//设置列表数据
		designer.setDataSource("list", new MapData(getHashMapList()));//map list作为数据源
		
		designer.process();//全自动赋值
		
		wb.save("d:/aspose/cell_sample_i.xls");//可以保存到数据流里面,以便下载使用
		System.out.println("ok!");
	}
	
	/**
	 * 单个数据
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static HashMap getHashMapData(){
		
		HashMap data = new HashMap();
		
		data.put("name", "fullstacks");
		data.put("age", "30");
		
		return data;
		
	}
	
	/**
	 * hashMap 列表
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	private static List<Map> getHashMapList(){
		 List<Map> datas= new ArrayList<Map>();
		 datas.add(getHashMapData());
		 datas.add(getHashMapData());
		 datas.add(getHashMapData());
		 datas.add(getHashMapData());
		 return datas; 
	}
	
}

上面的模板插入数据之后的效果如下

image

以上就是完美使用map作为数据源的实现,当然也可以实现以其他数据作为数据源,java bean作为数据源是直接支持的了。

总结

商业的软件使用起来确实是非常方便,几行代码的事情,使用一些开源的东西可能稍微要写一些复杂的代码,那么使用excel模板一个最大的好处就是能够在模板里面吧excel格式和样式都配好,包括一些统计等等,只需要插入数据就可以了。

Linux下安装Tomcat7与优化

默认情况下tomcat的配置适合开发模式或者比较小的系统应用,当访问量稍微多的时候比如1000人同时在线做一些频繁的业务操作的时候,可能性能方面就会存在问题,所以有必要在生产环境下对tomcat做一些优化。

tomcat 常用运行模式有3种,分别为 bio,nio,apr.生产环境建议用apr,从操作系统级别来解决异步的IO问题,大幅度的提高性能.

1.准备材料

apache-tomcat-7.0.65.tar.gz , 下载地址https://tomcat.apache.org/download-70.cgi ,下载apr 地址http://apr.apache.org/ ,下载两个文件apr-1.5.2.tar.gz和apr-util-1.5.4.tar.gz

2.安装

apr的安装

tar zxvf apr-1.5.2.tar.gz
cd apr-1.5.2
./configure --prefix=/usr/local/apr
make
make install

安装在路径 /usr/local/apr

apr-util的安装

tar zxvf apr-util-1.5.4.tar.gz
cd apr-util-1.5.4
./configure --with-apr=/usr/local/apr/bin/apr-1-config 
make
make install

解压tomcat压缩包,并复制到/usr/local/tomcat7

tar zxvf apache-tomcat-7.0.65.tar.gz
cp -r apache-tomcat-7.0.65 /usr/local/tomcat7

安装tomcat-navtive

cd /usr/local/tomcat7/bin
tar zxvf tomcat-native.tar.gz //该文件在tomcat的bin目录下面
cd /usr/local/tomcat7/bin/tomcat-native-1.1.33-src/jni/native
./configure --with-apr=/usr/local/apr/bin/apr-1-config --with-java-home=/usr/java/jdk1.7.0_75/
make
make install

这里注意的地方就是系统一定要先安装好jdk,要不然会报错,确保环境变量echo $JAVA_HOME能够看到jdk的安装目录。

3.编辑文件bin/catalina.sh加载apr,在任意地方加入下面一行

CATALINA_OPTS="$CATALINA_OPTS -Djava.library.path=/usr/local/apr/lib"

4.编辑conf/server.xml使用apr运行模式

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" prestartminSpareThreads="true"
        maxThreads="1000" minSpareThreads="4" maxSpareThreads="500" acceptCount="700"/>
		
<Connector executor="tomcatThreadPool" URIEncoding="UTF-8" useBodyEncodingForURI="true" enableLookups="false"
               port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol"
               connectionTimeout="20000"
               redirectPort="8443" />

5.配置jvm运行参数,在bin目录下创建文件bin/setenv.sh

JAVA_OPTS="-Xms1024m -Xmx1024m -Xmn512m -Xss1024K -XX:PermSize=64m -XX:MaxPermSize=2048m -XX:+UseParallelGC"

jre版本不一样一些参数也不一样,可以参考详细的参数说明进行配置

6.配置数据库连接池,编辑文件conf/context.xml

 <Resource name="jdbc/fullstacks"
	author="Container"
	type="javax.sql.DataSource"
	username="root"
	password="123"
	driverClassName="com.mysql.jdbc.Driver"
	validationQuery="SELECT 1"
	logAbandoned="true"
	removeAbandoned="true"
	removeAbandonedTimeout="10"
	testOnBorrow="true"
	testWhileIdle="true"
	minIdle="1"
	maxIdle="20"
	maxWait="5000"
	maxActive="2000"
	initialSize="1"
	timeBetweenEvictionRunsMillis="10000"
	numTestsPerEvictionRun="10"
	minEvictableIdleTimeMillis="10000"
	url="jdbc:mysql://192.168.1.140:3306/fullstacks?useUnicode=true&amp;characterEncoding=UTF-8" />

数据库驱动程序需要复制到tomcat的lib目录下面才能使用。

7.spring中配置数据源

<bean id="dataSourceId" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName">
            <value>java:comp/env/jdbc/fullstacks</value>
        </property>
</bean>

8.优化网络参数,编辑文件/etc/sysctl.cnf

net.core.netdev_max_backlog = 32768 
net.core.somaxconn = 32768 
net.core.wmem_default = 8388608 
net.core.rmem_default = 8388608 
net.core.rmem_max = 16777216 
net.core.wmem_max = 16777216 
net.ipv4.ip_local_port_range = 1024 65000 
net.ipv4.route.gc_timeout = 100 
net.ipv4.tcp_fin_timeout = 30 
net.ipv4.tcp_keepalive_time = 1200 
net.ipv4.tcp_timestamps = 0 
net.ipv4.tcp_synack_retries = 2 
net.ipv4.tcp_syn_retries = 2 
net.ipv4.tcp_tw_recycle = 1 
net.ipv4.tcp_tw_reuse = 1 
net.ipv4.tcp_mem = 94500000 915000000 927000000 
net.ipv4.tcp_max_orphans = 3276800 
net.ipv4.tcp_max_syn_backlog = 65536

命令sysctl -p生效

9.配置linux打开文件和进程

编辑文件/etc/security/limits.conf ,在后面加入

* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535

以上需要重启机器才能生效,也可以使用命令行暂时配置

ulimit -u 65535
ulimit -n 65535

10.启动和关闭tomcat

bin/start.sh
bin/shutdown.sh

以上基本上就配置完了,大概1000的在用户没啥问题,根据服务器硬件配置可适当调整参数。

总结

性能的影响因素是多方面的,互相影响,首先是系统本身没问题,数据库的响应没问题,web容器顺畅,硬件顺畅,网络带宽足够,再使用一些小工具进行检测,只有在大量用户在实际的生产环境中使用系统,才能发现问题,找到问题的根源到底是哪一块引发的性能瓶颈,调整一下自然一切都变得顺畅。

redis mongodb memcache三者的性能比較

memcache  用于键值对关系的服务器端缓存,用于存储一些常用的不是很大,但需要快速反应的数据redis 其实用法和memcache基本一样,可能就是几个参数有所不 同。当然 它们缓存的效果也不一样,具体的哪里不一样,以下就是一些资料,和自己的总结

1、 Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其他东西,例如图片、视频等等。
2、 数据类型–Memcache在添加数据时就要指定数据的字节长度,例如:
set key3 0 0 8
lxsymcto
STORED
而redis不需要,如:redis 127.0.0.1:6379>set key2 “lxsymblog”
OK
redis 127.0.0.1:6379>get key2
“lxsymblog”
3、虚拟内存–Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘
4、过期策略–memcache在set时就指定,例如set key1 0 0 8,即永不过期。Redis可以通过例如expire 设定,例如expire name 10
5、分布式–设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从
6、存储数据安全–memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化)
7、灾难恢复–memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复

 

从以下几个维度,对redis、memcache、mongoDB 做了对比,欢迎拍砖

1、性能

都比较高,性能对我们来说应该都不是瓶颈

总体来讲,TPS方面redis和memcache差不多,要大于mongodb

2、操作的便利性

      memcache数据结构单一

      redis丰富一些,数据操作方面,redis更好一些,较少的网络IO次数

       mongodb支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富

3、内存空间的大小和数据量的大小

       redis在2.0版本后增加了自己的VM特性,突破物理内存的限制;可以对key value设置过期时间(类似memcache)

       memcache可以修改最大可用内存,采用LRU算法

       mongoDB适合大数据量的存储,依赖操作系统VM做内存管理,吃内存也比较厉害,服务不要和别的服务在一起

4、可用性(单点问题)

对于单点问题,

             redis,依赖客户端来实现分布式读写;主从复制时,每次从节点重新连接主节点都要依赖整个快照,无增量复制,因性能和效率问题,

所以单点问题比较复杂;不支持自动sharding,需要依赖程序设定一致hash 机制。

一种替代方案是,不用redis本身的复制机制,采用自己做主动复制(多份存储),或者改成增量复制的方式(需要自己实现),一致性问题和性能的权衡

             Memcache本身没有数据冗余机制,也没必要;对于故障预防,采用依赖成熟的hash或者环状的算法,解决单点故障引起的抖动问题。

             mongoDB支持master-slave,replicaset(内部采用paxos选举算法,自动故障恢复),auto sharding机制,对客户端屏蔽了故障转移和切分机制。

5、可靠性(持久化)

对于数据持久化和数据恢复,

         redis支持(快照、AOF):依赖快照进行持久化,aof增强了可靠性的同时,对性能有所影响

          memcache不支持,通常用在做缓存,提升性能;

          MongoDB从1.8版本开始采用binlog方式支持持久化的可靠性

6、数据一致性(事务支持)

         Memcache 在并发场景下,用cas保证一致性

        redis事务支持比较弱,只能保证事务中的每个操作连续执行

        mongoDB不支持事务

7、数据分析

         mongoDB内置了数据分析的功能(mapreduce),其他不支持

8、应用场景

        redis:数据量较小的更性能操作和运算上

        memcache:用于在动态系统中减少数据库负载,提升性能;做缓存,提高性能(适合读多写少,对于数据量比较大,可以采用sharding)

        MongoDB:主要解决海量数据的访问效率问题

 

最近一直在研究key-value的存储,简单记一下感受。。一些memcache和redis的安装和使用就不赘述啦。只简单说说两种方案的差别。一些 感想和测试结果未必足够能说明问题,有什么不妥请大家指正。因为这两天在学习的过程发现一直在更正自己认识的缺陷,每天都会否定前一天的想法。。好了,费 话少说。

经过对50万个数据存储的研究发现:

每秒单条指令执行量

memcache  约3万次

redis     约1万次

而且,memcache的一大优点是可以通过一个函数直接设置过期时间,而redis需要两个函数才可以既设置了键值对又设置过期时间,也就是redis在这点上效率变成了原来的一半,即5千次,这对于大部分需求来说,有点太慢了。

memcache的测试代码如下:

<?php

$mem = new Memcache;

$mem->connect(“127.0.0.1”, 11211);

$time_start = microtime_float();

//保存数据

for($i = 0; $i < 100000; $i ++){

$mem->set(“key$i”,$i,0,3);

}

$time_end = microtime_float();

$run_time = $time_end – $time_start;

echo “用时 $run_time 秒\n”;

function microtime_float()

{

list($usec, $sec) = explode(” “, microtime());

return ((float)$usec + (float)$sec);

}

?>

redis的测试代码如下:redis1.php 此代码大概需要10秒左右

<?php

//连接

$redis = new Redis();

$redis->connect(‘127.0.0.1’, 6379);

$time_start = microtime_float();

//保存数据

for($i = 0; $i < 100000; $i ++){

$redis->sadd(“key$i”,$i);

}

$time_end = microtime_float();

$run_time = $time_end – $time_start;

echo “用时 $run_time 秒\n”;

//关闭连接

$redis->close();

 

function microtime_float()

{

list($usec, $sec) = explode(” “, microtime());

return ((float)$usec + (float)$sec);

}

?>

如果需要在设置键值的同时设置过期时间,大概执行需要20秒左右,测试代码如下:redis2.php

<?php

//连接

$redis = new Redis();

$redis->connect(‘127.0.0.1’, 6379);

$time_start = microtime_float();

//保存数据

for($i = 0; $i < 100000; $i ++){

$redis->sadd(“key$i”,$i);

$redis->expire(“key$i”,3);

}

$time_end = microtime_float();

$run_time = $time_end – $time_start;

echo “用时 $run_time 秒\n”;

//关闭连接

$redis->close();

 

function microtime_float()

{

list($usec, $sec) = explode(” “, microtime());

return ((float)$usec + (float)$sec);

}

?>

后来在网上发现redis有一个神奇的功能叫事务,通过multi原子性的将一段代码块依次执行,从而达到一个完整功能模块的执行。不幸的是,通过测 试发现,采用multi方式执行代码时并没有减少请求次数,相反在执行multi指令和exec指令时都要发送请求,从而将运行时间变成了原来的四倍,即 四条指令的运行时间。测试代码如下:redis3.php

<?php

//连接

$redis = new Redis();

$redis->connect(‘127.0.0.1’, 6379);

$time_start = microtime_float();

//保存数据

for($i = 0; $i < 100000; $i ++){

$redis->multi();

$redis->sadd(“key$i”,$i);

$redis->expire(“key$i”,3);

$redis->exec();

}

$time_end = microtime_float();

$run_time = $time_end – $time_start;

echo “用时 $run_time 秒\n”;

//关闭连接

$redis->close();

 

function microtime_float()

{

list($usec, $sec) = explode(” “, microtime());

return ((float)$usec + (float)$sec);

}

?>

问题出现了瓶颈,有好多公司需要海量数据处理,每秒5000次远不能满足需求,然后由于redis主从服务器上比memcache有更大的优势, 为了将来数据的着想,不得不使用redis,这时候出现了一种新的方式,即phpredis提供的pipline功能,该功能能够真正的将几条代码封装成 一次请求,从而大大提高了运行速度,50万次的数据执行只有了58秒。测试代码如下:redis4.php

<?php

//连接

$redis = new Redis();

$redis->connect(‘127.0.0.1’, 6379);

$time_start = microtime_float();

//保存数据

for($i = 0; $i < 100000; $i ++){

$pipe=$redis->pipeline();

$pipe->sadd(“key$i”,$i);

$pipe->expire(“key$i”,3);

$replies=$pipe->execute();

}

$time_end = microtime_float();

$run_time = $time_end – $time_start;

echo “用时 $run_time 秒\n”;

//关闭连接

$redis->close();

 

function microtime_float()

{

list($usec, $sec) = explode(” “, microtime());

return ((float)$usec + (float)$sec);

}

?>

运用这个操作可以非常完美的将赋值操作和设置过期时间操作打包到一个请求去执行,大大提高了运行效率。

redis安装:http://mwt198668.blog.163.com/blog/static/48803692201132141755962/

memcache安装:http://blog.csdn.net/barrydiu/article/details/3936270

redis设置主从服务器:http://www.jzxue.com/fuwuqi/fuwuqijiqunyuanquan/201104/15-7117.html

memcache设置主从服务器:http://www.cnblogs.com/yuanermen/archive/2011/05/19/2051153.html

《三体1》7.三体1、周文王、长夜

汪淼拔通了丁仪的电话,对方接听后,他才想起现在已是凌晨一点多了。
“我是汪淼,真对不起,这么晚打扰。”
“没关系,我正失眠。”
“我……遇到一些事,想请你帮个虻。你知道国内有观测宇宙背景辐射的机构吗?”汪淼产生了一种倾诉的欲望,但旋即觉得幽灵倒计时之事目前还是不要让更多的人知道为好。
“宇宙背景辐射?你怎么对这个有雅兴?看来你真的遇到一些事了……你去看过杨冬的母亲吗?”
“啊——真对不起,我忘了。
“没关系,现在科学界,很多人都……像你说的那样遇到了一些事,心不在焉的。不过你最好还是去看看她,她年纪大了,又不愿雇保姆,要是有什么费力气的事麻烦你帮着干干……哦,宇宙背景辐射的事,你正好可以去找杨冬的母亲问问,她退休前是搞天体物理专业的,与国内的这类研究机构很熟。
“好好,我今天下班就去。”
“那先谢谢了,我是真的无法再面对与杨冬有关的一切了。”
打完电话后,汪淼坐到电脑前,开始打印网页上显示的那张很简单的莫尔斯电码对照表。这时他已经冷静下来,将思绪从倒计时上移开,想着关于“科学边界”和申玉菲的事,想到她玩的网络游戏。关于申玉菲,他能肯定的唯一一件事就是她不是爱玩游戏的人,这个说话如电报般精简的女人给他唯一的印象就是冷,她的冷与其他的某些女性不同,不是一张面具,而是从里到外冷透了。汪淼总是下意识地将她与早已消失的DOS操作系统联系在一起,一面空荡荡的黑屏幕,只有一个简单得不能再简单的“C:\\”提示符在闪动,你输入什么它就输出什么,一个字都不会多,也不会有变化。现在他知道,“C:\\”提示符后面其实是一个无底深渊。
她真会有兴致玩游戏,而且是戴着V装具玩儿?她没有孩子,那套V装具只能是自己买回去用的,这有些不可思议。
汪淼在浏览器的地址栏中输入那个很容易记住的游戏网址:网页上显示该游戏只支持V装具方式。汪淼想起了纳米中心的职工娱乐室里好像有一套V装具,就走出已经空荡荡的中心实验大厅,去值班室要了钥匙,在娱乐室中穿过一排台球桌和健身器材,在一台电脑旁找到了V装具,费了很大劲才把感应服穿上,然后戴上显示头盔,启动电脑。
启动游戏后,汪淼置身于一片黎明之际的荒原,荒原呈暗褐色,细节看不清楚,远方地平线上有一小片白色的曙光,其余的天空则群星闪烁。一声巨响,两座发着红光的山峰砸落到远方的大地上,整个荒原笼罩在红色光芒之中。被激起的遣天蕞日的尘埃散去后,汪淼看清了那两个顶天立地的大字:三体。
随后出现了个注册界面,汪淼用“海人”这个ID注册,然后成功登录。
荒原依旧,但V装具感应服中的压缩机咝咝地启动了,汪淼感到一股逼人的寒气。前方出现了两个行走的人影,在曙光的背景前呈黑色的剪影……汪淼追了上去,他看到两人都是男性,披着破烂的长袍,外面还裹着一张肮脏的兽皮,都带着一把青铜时代那种又宽又短的剑。其中一人背着一只有他一半高的细长的木箱子,。那人扭头看看汪森,他的脸像那兽皮一样脏和皱,双眼却很有神,眸子映着曙光。“冷啊”他说。
“是。真冷”汪森附和道。
“这是战国时代,我是周文王。”那人说。
“周文王不是战国时代的人吧?”汪淼问。
“他一直活到现在呢,纣王也活着”另一个没背箱子的人说,“我是周文王的追随者,我的ID就叫‘周文王追随者’,他可是个天才。”
“我的ID是‘海人’,”汪淼说,“您背的是什么?”
周文王放下那只长方形木箱,将一个立面象一扇门似的打开。露出里面的五层方格,借着晨曦的微光。汪淼看到每层之间都有高低不等的一小堆细沙,每格中都有从上一格流下的一道涓细的沙流
“沙漏,八小时漏完一次,颠倒三次就是一天。不过我常常忘了颠倒,要靠追随者提醒。”周文王介绍说。
“你们好像是在长途旅行,有必要背这么笨重的计时器吗?”
“那怎么计时呢?”
“拿个小型的日晷多方便,或者干脆只看太阳也能知道大概的时间。”
周文王和追随者面面相觑。然后一起盯着汪淼,好像他是个白痴,“太阳?看太阳怎么能知道时间?这可是乱纪元。”
汪森正要询问这个怪异名词的含义,追随者哀鸣道:“真冷啊,冷死我了!”
汪淼也觉得冷,但他不能随便脱下感应服,一般情况下。那样做会被游戏注销ID的。他说:“太阳出来就会暖和些的。”
“你在冒充伟大的先知吗?连周文王都不算先知呢!”追随者冲汪淼不屑地摇摇头。
“这需要先知吗?谁还看不出来太阳一两个小时后就会升起。”汪淼指指天边说。
“这是乱纪元!”追随者说。
“什么是乱纪元?”
“除了恒纪元,都是乱纪元。”周文王说,像回答一个无知孩童的提问。
果然,天边的晨光开始暗下去,很快消失了,夜幕重新笼罩了一切,苍穹星光灿烂。
“原来现在是黄昏不是早晨?”汪淼问。
“是早晨,早晨太阳不一定能升起,这是乱纪元。”
寒冷使汪淼很难受。“看这样子,太阳要很长时间以后才会升出来。”他哆嗉着指指模糊的地平线说。
“你怎么又会有这种想法?那可不一定,这是乱纪元。”追随者说着转向周文王,“姬昌,给我些鱼干吃吧。”
“不行!”周文王断然说道,“我也是勉强吃饱,要保证我能走到朝歌,而不是你。”
说话间。汪淼注意到另一个方向的地平线又出现了曙光,他分不清东南西北,但肯定不是上次出现时的方向。
这曙光很快增强,不一会儿,这个世界的太阳升起来了,是一颗蓝色的小太阳,很像增强了亮度的月亮,但还是让汪淼感到了一丝温暖,并看清了大地的细节。但这个白昼很短暂,太阳在地平线上方划了一道浅浅的弧形就落下了,夜色和寒冷又笼罩了一切。
三人在一棵枯树前停下,周文王和追随者拔出青铜剑来砍柴,汪淼将碎柴收集到一块。追随者拿出火镰,噼啪、噼啪打了好一阵,升起了一堆火。汪淼的感应服的前胸部分变暖和了,但背后仍然冰冷。
“烧些脱水者,火才旺呢。”追随者说。
“住嘴!那是纣王干的事!”
“反正路上那些散落的,都破成那样,泡不活了。如果你的理论真能行。别说烧一些,吃一些都成,与那理论相比,几条命算什么。”
“胡说!我们是学者!”
篝火燃尽后,三人继续赶路。由于他们之间交谈很少。系统加快了游戏时间的流逝速度。周文王很快将背上的沙漏翻了六下,转眼间两天过去了。太阳还没有升起过一次,甚至天边连曙光的影子都没有。
“看来太阳不会出来了。”汪淼说,同时调出游戏界面来看了一下自己的HP,它正因寒冷而迅速减小。
“你又冒充伟大的先知了……”追随者说,汪淼和他一起说出了后半句,“这是乱纪元!”
这话说完不久,天边真的出现了曙光,并且迅速增强,转眼间太阳就升了起来。汪淼发现这次升起的是一颗大太阳。当它升至一半时,直径占了视野内至少五分之一的地平线。暖流扑面而来,今汪淼心旷神怡,但他看周文王和追随者时,发现他们都一脸惊恐,仿佛魔鬼降临。
“快,找阴凉地儿!”追随者大喊,汪淼跟着他们飞奔。跑到了一处低矮的岩石后面蹲下来。岩石的阴影在渐渐缩短,周围的大地像处于白炽状态般刺眼,脚下的冻土迅速融化,由坚硬如铁变成泥泞一片,热浪滚滚。汪淼很快出汗了。当大太阳升到头顶正上方时,三人用兽皮蒙住头,强光仍如利箭般从所有缝隙和孔洞中射进来。三人绕着岩石挪到另一边,躲进那边刚刚出现的阴影中……
太阳落山后,空气依然异常闷热,大汗淋漓的三人坐在岩石上,追随者沮丧地说:“乱纪元旅行,真是在地狱里走路。我受不了了;再说我也没吃的了,你不分我些鱼干,又不让吃脱水者,唉——”
“那你只能脱水了。”周文王说,一手用兽皮扇着风。
“脱水以后,你不会扔下我吧?”
“当然不会。我保证把你带到朝歌。”
追随者脱下了被汗水浸湿的长袍,赤身躺到泥地上。在落日的余晖中,汪淼看到追随者身上的汗水突然增加了,他很快知道那不是出汗,这人身体内的水分正在被彻底排出,这些水在沙地上形成了几条小小的溪流,追随者的整个躯体如一根熔化的蜡烛在变软变薄……十分钟后水排完了,那躯体化为一张人形的软皮一动不动地铺在泥地上,面部的五官都模糊不清了。
“他死了吗?”汪淼问。他想起来了,一路上不时看到有这样的人形软皮,有的已破损不全,那就是不久前追随者想要用来烧火的脱水者。
“没有。”周文王说着,将追随者变成的软皮拎起来,拍了拍上面的土,放到岩石上将他(它)卷起来,就像卷一只放了气的皮球一般,“在水里泡一会儿,他就会恢复原状活过来,就像泡干蘑菇那样。”
“他的骨骼也变软了?”
“是的,都成了干纤维,这样便于携带。”
“这个世界中的每个人都能脱水吗?”
“当然,你也能,要不,在乱纪元是活不下去的。”周文王将卷好的追随者递给汪淼,“你带着他吧,扔到路上不是被人烧了,就是吃了。”
汪淼接过软皮,很轻的一小卷,用胳膊夹着倒也没有什么异样的感觉。
汪淼夹着脱水的追随者,周文王背着沙漏,两人继续着艰难的旅程。同前几天一样,这个世界中的太阳运行得完全没有规律,在连续几个严寒的长夜后,可能会突然出现一个酷热的白天,或者相反。两人相依为命,在篝火边抵御严寒,泡在湖水中度过酷热。好在游戏时间可以加快,一个月可以在半小时内过完,这使得乱纪元的旅程还是可以忍受的。
这天,漫漫长夜已延续了近一个星期(按沙漏计时),周文王突然指着夜空欢呼起来:“飞星!飞星!两颗飞星!!”
其实,汪淼之前就注意到那种奇怪的天体,它比星星大,能显出乒乓球大小的圆盘形状,运行速度很快,肉眼能明显地看到它在星空中移动,只是这次出现了两个。
周文王解释说:“两颗飞星出现,恒纪元就要开始了!”
“以前看到过的。”
“那只有一个。”
“最多只有两个吗?”
“不,有时会有三个,但不会再多了。”
“三颗飞星出现,是不是预示着更美好的纪元?”
周文王用充满恐惧的眼神瞪了汪淼一眼,“你在说什么呀。三颗飞星……祈祷它不要出现吧。”
周文王的话没错,他们向往的恒纪元很快开始了,太阳升起落下开始变得有规律,一个昼夜渐渐固定在十八小时左右,日夜有规律的交替使天气变得暖和了一些。
“恒纪元能持续多长时间?”汪淼问。
“一天或一个世纪,每次多长谁都说不准。”周文王坐在沙漏上,仰头看着正午的太阳,“据记载,西周曾有过长达两个世纪的恒纪元,唉,生在那个时代的人有福啊。”
“那乱纪元会持续多长时间呢?”
“不是说过嘛,除了恒纪元都是乱纪元,两者互为对方的间隙。”
“那就是说,这是一个全无规律的混乱世界?!”
“是的。文明只能在较长的气候温暖的恒纪元里发展。大部分时间里,人类集体脱水存贮起来,当较长的恒纪元到来时,再集体浸泡复活,生产和建设。”
“那怎样预知每个恒纪元到来的时间和长短呢?”
“做不到,从来没有做到过。当恒纪元到来时,国家是否浸泡取决于大王的直觉,常常是:浸泡复活了,庄稼种下了,城镇开始修筑,生活刚刚开始,恒纪元就结束了,严寒和酷热就毁灭了一切。”周文王说到这里,一手指向汪淼,双眼变得炯炯有神,“好了,你已经知道了这个游戏的目标:就是运用我们的智力和悟性,分析研究各种现象,掌握太阳运行的规律,文明的生存就维系于此。”
“在我看来太阳运行根本就没有规律。”
“那是因为你没能悟出世界的本原。”
“你悟出来了?”
“是的,这就是我去朝歌的目的,我将为纣王献上一份精确的万年历:”
“可这一路上,没看到你有这种能力。”
“对太阳运行规律的预测只能在朝歌做出,因为那里是阴阳的交汇点,只有在那里取的卦才是准确的。”两人又在严酷的乱纪元跋涉了很长时间,其间又经历了一次短暂的恒纪元,终于到达了朝歌。
汪淼听到一种不间断的类似于雷声的轰鸣。这声音是朝歌大地上许多奇怪的东西发出的,那是一座座巨大的单摆,每座都有几十米高:单摆的摆锤是一块块巨石,被一大柬绳索吊在架于两座细高石塔间的天桥上。每座单摆都在摆动中=驱动它们的是一群群身穿盔甲的士兵,他们合着奇怪的号子。齐力拉动系在巨石摆锤上的绳索,维持着它的摆动。汪淼发现,所有巨摆的摆动都是同步的,远远看去,这景象怪异得使人着速,像大地上竖立着一座座走动的钟表,又像从夭而降的许多巨大、抽象的符号。
在巨摆的环绕下。有一座巨大的金字塔,夜幕中如同一座高耸的黑山,这就是纣王的宫殿。汪淼跟着周文王走进了金字塔基座上的一个不高的洞门,门旁几名守卫的士兵在黑暗中如幽灵般无声地徘徊。他们沿着一条长长的隧道向里走,隧道窄而黑,间隔很远才有一枝火炬。
“在乱纪元,整个国家在脱水中,但纣王一直醒着,陪伴着这片没有生机的国土。要想在乱纪元生存,就得居住在这种墙壁极厚的建筑中,几乎像住在地下,才能避开严寒和酷热。”周文王边走边对汪淼解释。
走了很长的路,才进入了纣王位于金字塔中心的大殿,其实这里并不大,很像一个山洞。身披一大张花兽皮坐在一处高台上的人显然是纣王了,但首先吸引汪淼目光的是一位黑衣人,他的黑衣几乎与大殿中浓重的阴影融为一体,那张苍白的脸仿佛是浮在虚空中。
“这是伏羲。”纣王对刚进来的周文王和汪淼介绍那位黑衣人,仿佛他们一直就在那儿似的,而黑衣人才是新来的,“他认为,太阳是脾气乖戾的大神,他醒着的时候喜怒无常,是乱纪元;睡着时呼吸均匀,是恒纪元。伏曦建议竖起了外面的那些大摆,日夜不停地摆动,声称这对太阳神有强烈的催眠作用,能使其陷入漫长的昏睡。但直到现在,我们看到太阳神仍醒着,最多只是不时打打盹儿。”
纣王挥了一下手,有人端来一个陶罐,放到伏曦面前的小石台上——汪淼后来知道,那是一罐调味料。伏曦长叹一声,端起陶罐喝下去,那咕咚咕咚的声音仿佛黑暗深处有一颗硕大的心脏在跳动。喝了一半后,他将剩下的调味料倒在身上,然后扔下陶罐,走向大殿角落的一口架在火上的青铜大鼎,爬上鼎沿;他跳进大鼎,激起了一大团蒸气。
“姬昌坐下,一会儿就开宴。”纣王指指那口大鼎说。
“愚蠢的巫术。”周文王朝大鼎偏了下头,轻蔑地说。
“你对太阳悟出了什么?”纣王问,火光在他的双眸中跳动。
“太阳不是大神,太阳是阳,黑夜是阴,世界是在阴阳平衡中运转的,这不在我们的控制之中,但可以预测。”周文王说着,抽出青铜剑,在火炬照到的地板上画出了一对大大的阴阳鱼。然后以令人目眩的速度在周围画出了六十四卦,看上去如同火光中时隐时现的大年轮,“大王,这就是宇宙的密码,借助它,我将为您的王朝献上一部精确的万年历。”
“姬昌啊,我现在急需知道的,是下一个长恒纪元什么时候到来。”
“我将立刻为您占卜。”周文王说着,走到阴阳鱼中央盘腿坐下,抬头望着大殿的顶部,目光仿佛穿透了厚厚的金字塔看到了星空,他的双手手指同时在进行着复杂的运动,组合成一部高速运转的计算器。寂静中,只有大鼎中的汤发出咕嘟咕嘟的声响,仿佛煮在汤中的巫师在梦呓。
周文王从阴阳图中站起来,头仍仰着,说:“下面将是一段为期四十一天的乱纪元。然后将出现为期五天的恒纪元,接下来是为期二十三天的乱纪元和为期十八天的恒纪元,然后是为期八天的乱纪元,当这段乱纪元结束后,大王,您所期待的长恒纪元就到来了,这个恒纪元将持续三年零九个月,其间气候温暖,是一个黄金纪元。”
“我们首先需要证实一下你前面的预测。”纣王不动声色地说。
汪淼听到上方传来一阵轰隆隆的声音,大殿顶上的一块石板滑开,露出一处正方形的洞口,汪淼调整方向,看到这个方洞通到金字塔的外面,在这个方洞的尽头,汪森看到了几颗闪烁的星星。
游戏的时间加快了,由两名士兵看守的周文王带来的沙漏几秒钟就翻动一次,标志着八小时的流逝。上方的窗口无规律地闪烁起来,不时有一束乱纪元的阳光射进大殿,有时很微弱,如月光一般;有时则十分强烈,投在地上的方形光斑白炽明亮,使所有的火炬黯然失色。汪淼数着沙漏翻动的次数,当翻到一百二十次左右时,阳光投进窗口的间隔变得规则了,预测中的第一个恒纪元到来。沙漏再翻动十五下后,窗口的闪烁又紊乱起来,乱纪元又开始了。然后又是恒纪元,然后又是乱纪元,它们的开始和持续时间虽然有些小误差,但与周文王的预测已是相当的吻合了。当最后一段为期八天的乱纪元结束后,他预言的长恒纪元开始了。汪淼数着沙漏的翻动,二十天过去了,射进大殿的日光仍遵循着精确的节奏。这时,游戏时间的流逝被调整到正常。
纣王向周文王点点头:“姬昌啊,我将为你树起一座丰碑,比这座宫殿还要高大。”
周文王深鞠一躬:“我的大王,让您的王朝苏醒吧,繁荣吧!”
纣王在石台上站起身,张开双臂,仿佛要拥抱整个世界,他用一种很奇怪的歌唱般的音调喊道:“浸泡——”
听到这号令,大殿内的人都跑向洞门。在周文王的示意下,汪淼跟着他沿着长长的隧道向金字塔外走去。走出洞门,汪森看到时值正午,太阳在当空静静地照耀着大地,微风吹过,他似乎嗅到了春天的气息。周文王和汪淼一同来到了距金字塔不远的一处湖畔,湖面上的冰已融化了,阳光在微波间跳动。
先出来的一队士兵高呼着:“浸泡!浸泡!”都奔向湖边一处形似谷仓的高大石砌建筑。在来的路上,汪淼不时在远处看到过这种建筑,周文王告诉他那是“干仓”,是存贮脱水人的大型仓库。士兵们打开干仓的石门,从中搬出一卷卷落满灰尘的皮卷,他们每人都抱着、夹着好几个皮卷,走向湖边,将那些皮卷扔进湖中。那些皮卷一遇到水,立刻舒展开来,一时间,湖面上漂浮着一片似乎是剪出来的薄薄的人形。每一张“人片”都在迅速吸水膨胀。渐渐地,湖面上的“人片”都变成了圆润的肉体,这些肉体很快具有了生命的迹象,一个个挣扎着从齐腰深的湖水中站立起来。他们睁大如梦初醒的眼睛看着这风和日丽的世界。“浸泡!”一个人高呼起来,立刻引来了一片欢呼声:“浸泡!浸泡!!”……这些人从湖中跑上岸,赤身裸体地奔向干仓,将更多的皮卷投入湖中,浸泡复活的人一群群从湖中跑出来。这一幕也发生在更远处的湖泊和池溏中,整个世界在复活。
“噢,天啊!我的指头——”
汪森顺着声音看去,见一个刚浸泡复活的人站在湖中。举着一只手哭喊道,那手缺了中指,血从手上断指处滴到湖中。其他复活者纷纷拥过他的身边,兴高采烈地奔向湖岸,没有人注意他。
“行了,你就知足吧!”一个经过的复活者说,“有人整条胳膊腿都没了,有人脑袋被咬了个洞,如果再不浸泡,我们怕是都要被乱纪元的老鼠啃光了!”
“我们脱水多长时间了?”另一位复活者问。
“看看大王宫殿上积的沙尘有多厚就知道了,刚听说现在的大王已不是脱水前的大王了,不知是他的儿子还是孙子。”
浸泡持续了八天才完全结束,这时所有的脱水人都已复活,世界又一次获得了新生。这八天中,人们享受着每天二十个小时、周期准确的日出日落。沐浴在春天的气息里,所有人都衷心地赞美太阳、赞美掌管宇宙的诸神。第八天夜里,大地上的篝火比天上的星星都密,在漫长的乱纪元中荒废的城镇又充满了灯火和喧闹,同文明以前的无数次浸泡一样,所有人将彻夜狂欢,迎接日出后的新生活。
但太阳再也没有升起来。
各种计时器都表明日出的时间已过,但各个方向的地平线都仍是漆黑一片。又过了十个小时,没有太阳的影子,连最微弱的晨光都见不到。一天过去了,无边的夜在继续着;两天过去了,寒冷像一只巨掌在暗夜中压向大地。
“请大王相信我,这只是暂时的,我看到了宇宙中的阳在聚集,太阳就要升起来了,恒纪元和春天将继续!”金字塔的大殿里,周文王跪在纣王端坐的石台下哀求道。
“还是把鼎烧上吧。”纣王叹了口气说。
“大王!大王!”一名大臣从洞门里跌跌撞撞地跑进来,带着哭腔喊道,“天上,天上有三颗飞星!!”
大殿中的所有人都惊呆了,空气仿佛凝固了,只有纣王仍然不动声色一他转向以前一直不屑于搭理的汪淼,“你还不知道出现三颗飞星意味着什么吧?姬昌啊,告诉他。”
“这意味着漫长的严寒岁月,冷得能把石头冻成粉末。”周文王长叹一声说
“脱水——\”纣王又用那歌唱般的声音喊道。其实,在外面的大地上,人们早已开始陆续脱水,重新变成人干以度过正在到来的漫漫长夜,他们中的幸运者被重新搬入千仓,还有大量的人干被丢弃在旷野上。周文王慢慢站起身,朝架在火上的青铜大鼎走去,他爬上鼎沿,跳进去前停了几秒钟,也许是看到伏羲煮得烂熟的脸正在汤中冲他轻笑。
“用文火。”纣王无力地说,然后转向其他人,“该EXIT的就EXIT吧,游戏到这儿已经没什么玩头了。”
洞门上方出现了发着红光的EXIT标志,人们纷纷向那里走去:汪森也跟随而去,穿过洞门和长长的隧道来到了金字塔外,看到黑夜里大雪纷飞,刺骨的寒冷使他打了个冷颤。天空的一角显示出游戏的时间又加快了。
十天后。雪仍在下着,但雪片大而厚重,像是凝结的黑暗。有人在汪淼耳边低声说:“这是在下二氧化碳干冰了。”汪淼扭头一看,是周文王的追随者
又过了十天,雪还在下,但雪花已变得薄而透明,在金字塔洞门透出的火炬的微光中呈现出一种超脱的淡蓝色,像无数飞舞的云母片。
“这雪花已经是凝固的氧、氮了,大气层正在绝对零度中消失。”
金字塔被雪埋了起来,最下层是水的雪,中层是干冰的雪,上层是固态氧、氮的雪。夜空变得异常晴朗,群星像一片银色的火焰。一行字在星空的背景上出现:
这一夜持续了四十八年,第137号文明在严寒中毁灭了,该文明进化至战国层次。
文明的种子仍在,它将重新启动,再次开始在三体世界中命运莫测的进化,欢迎您再次登录。
退出前,汪淼最后注意到的是夜空中的三颗飞星,它们相距很近,相互围绕着,在太空深渊中跳着某种诡异的舞蹈。

Linux中安装Apache 2.4并限制下载速度

apache官方并没有提供linux的安装包只提供windows下的安装包,那么linux下的安装只能通过源代码的编译来安装了,下面我们来看看如何安装。

1.准备材料

下载源代码http://httpd.apache.org/download.cgi下载httpd-….tar.gz包,然后解压缩安装,按顺序执行下面的命令

gzip -d httpd-NN.tar.gz
tar xvf httpd-NN.tar
cd httpd-NN
./configure --prefix=/usr/local/apache2.4
make
make install

以上如果没有错误的话就安装在/usr/local/apache2.4目录下了,一般情况下会需要apr和apr-util以及pcre的依赖包才能

2.准备依赖包

apr和apr-util包可以从http://apr.apache.org/下载,使用gzip和tar命令解压后分别放到apache源代码根目录的srclib/apr和srclib/apr-util目录中,注意一定不能带版本号的了。

pcre可以从http://www.pcre.org下载,注意是下载pcre而不是pcre2,下载之后解压然后安装到一个指定的目录

./configure --prefix=/usr/local/pcre
make
make install

3.编译安装apache加依赖包的参数

./configure --prefix=/usr/local/apache2.4 --with-included-apr --with-pcre=/usr/local/pcre/bin/pcre-config
make
make install

以上应该是不会发生错误了,这样就安装完成了

4.启动和关闭

/usr/local/apache2.4/bin/apachectl -k start
/usr/local/apache2.4/bin/apachectl -k stop

第一行是启动第二行是停止,默认情况系你的启动可能会报错,因为ServerName错误,编辑httpd.conf配置文件

vi /usr/local/apache2.4/conf/httpd.conf

找到 ServerName 192.168.1.25:80 把服务器的正确ip地址写上保存好,重启之后就成功了,欢迎页面http://localhost就可以访问了

5.配置限速模块

同样编辑httpd.conf文件,找到

LoadModule ratelimit_module modules/mod_ratelimit.so

这一样吧前面的#去掉,在文件末尾加上下面的配置

<Location /video>
 SetOutputFilter RATE_LIMIT
 SetEnv rate-limit 200
</Location>

上面配置的意思是在路径/video路径下的下载速度限制最大为200kb/s

重启之后,复制一个比较大的文件如test.zip放到htdocs/video目录下,然后使用浏览器下载http://localhost/video/test.zip,多下载几个,最后发现速度都是在200kb/s以内。

总结

apache的限速是限制每个连接的下载速度,在有限的带宽的情况下非常有用,避免部分连接把带宽都占满,可以与tc配置使用限制指定端口的带宽,可以达到不同的端口下载速度不一样。

LINUX中IPTABLES和TC对端口的带宽限制

不管是iptables还是tc(traffic control)功能都很强大,都是与网络相关的工具,那么我们就利用这两个工具来对端口进行带宽的限制.

1.使用命令ifconfig查看服务器上的网卡信息,比如网卡eth0是用来对外的网络,也就是用户通过该网卡连接到系统,那么我们就对这个网卡进行带宽的限制

ifconfig

2.建立eth0队列

tc qdisc add dev eth0 root handle 1: htb default 20

命令解释:将一个htb队列绑定在eth0上,编号为1:0,默认归类是 20

3.建立跟分类

tc class add dev eth0 parent 1:0 calssid 1:1 htb  rate 3Mbit

命令解释:在队列1:0上创建根分类1:1 限速,类别htb,限速3Mbit

4.创建分类

tc class add dev eth0 parent 1:1 classid 1:20 htb rate 2Mbit ceil 3Mbit

以根分类1:1为父类创建分类1:20 ,类别为htb 限速 1Mbit 最大3Mbit(htb可借用其它类带宽)

5.添加公平队列

tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10

命令解释:sfq是公平队列 ,防止一个会话占用全部带宽

6.创建分类过滤器

tc filter add dev eth0 parent 1:20 protocol ip u32 match ip sport 8080 0xffff classid 1:20

命令解释:以分类1:20为父类创建编号为1:20的过滤器 ,加载u32模块,指定端口为8080

到此为止带宽就限制住了,最大带宽为3Mbit,也就是200多k的下载速度。

7.删除tc队列

tc qdisc del dev eth0 root

把建立好的队列删除,带宽不再限制。

 

以上只是使用tc进行对带宽的限制,当然也可以结合iptables使用,那么以上的第六步就不太一样了

6.创建过滤器并制定handle

tc filter add dev em2 parent 1:0 protocol ip prio 1 handle 1000 fw classid 1:20

7.使用iptable对端口绑定tc队列

iptables -t mangle -I POSTROUTING -o eth0 -sport 8080 -j MARK --set-mark 1000
iptables -t mangle -I POSTROUTING -o eth0 -sport 8080 -j RETURN

以上就是iptables与tc结合的结果,这里限制的是端口,当然也可以制定某个目标ip只限制制定ip的带宽。

 

总结

这里提到限制的是带宽,而且下载根据连接数进行平均分配,对TC而言,限制200k的话,一个连接那速度就是200k,如果两个连接就变成100k一个,而iptables的话,如果一个连接占满了200k的带宽,那么第二个连接就直接被拒绝了。

最终如果只是想对应用系统的下载的所有连接每个连接都限制在200k的下载速度的话,最好还是应用服务器自己进行限制。

Cannot assign requested address

今天用php连接最近新开发的一个服务做测试,发现命令行打印出:Cannot assign requested address

网上找了下原因,大致上是由于客户端频繁的连服务器,由于每次连接都在很短的时间内结束,导致很多的TIME_WAIT,以至于用光了 可用的端 口号,所以新的连接没办法绑定端口,即“Cannot assign requested address”。是客户端的问题不是服务器端的问题。通过netstat,的确看到很多TIME_WAIT状态的连接。

client端频繁建立连接,而端口释放较慢,导致建立新连接时无可用端口。

网上的解决方法:

执行命令修改如下2个内核参数 (需要root权限)
sysctl -w net.ipv4.tcp_timestamps=1  开启对于TCP时间戳的支持,若该项设置为0,则下面一项设置不起作用
sysctl -w net.ipv4.tcp_tw_recycle=1  表示开启TCP连接中TIME-WAIT sockets的快速回收

Eclipse+Maven热部署调试

Eclipse JEE原生方式(WTP)调试Web应用的时候,当修改java类的时候,tomcat会自动重启,大部分的人都处于这种状态中,改点东西然后等待重启几十秒的时间,这是在浪费生命,修改资源文件不需要重启,其实java本身已经支持hot code replace热部署,以下是简单的配置。

maven必须使用tomcat插件

<plugin>
	<groupId>org.apache.tomcat.maven</groupId>
	<artifactId>tomcat7-maven-plugin</artifactId>
	<version>2.2</version>
</plugin>

eclipse中tomcat的server.xml的配置

image

文件中找到你项目的Context配置,设置reloadable=”false” 就可以了,默认是ture。

<Context docBase="stapp.web" path="/stapp.web" reloadable="false" source="org.eclipse.jst.jee.server:stapp.web"/>

修改完毕重启tomcat,然后修改java代码并保存,发现tomcat不在自动重启了,页面访问正常并执行了修改之后的代码,断点在新的代码上也没问题。

2015年度最流行PHP框架Laravel居首

一个月前,编程开发教学资源平台SitePoint启动了2015年度最流行PHP框架调查。此次调查收到的回复数量远远超过SitePoint迄今为止的所有调查。Bruno Skvorc是SitePoint PHP栏目的编辑。近日,他发布了此次调查的结果,并做了相关分析。

不出所料,Laravel再次优势胜出,如下图所示:

phptop

Bruno观察到,在投票数超过50的国家中,大部分英语国家的开发人员都青睐Laravel,法国开发人员则忠于自己的产品Symfony,捷克开发人员偏爱在西方世界鲜有人知的Nette,而乌克兰开发人员更爱PHPixie。在年龄方面,除了未成年组(PHPixie居首)外,Laravel在所有年龄段的开发人员中都是最受欢迎的,Symfony紧随其后,而CodeIgniter仍然有许多忠实的用户。还有一点非常有趣,就是Phalcon的流行程度较去年大幅下滑,这可能与样本数量有关。

Bruno认为,Laravel的成功,除了得益于良好的代码外,还离不开大力的宣传。框架创建者Taylor Otwell不仅确保Laravel拥有几近完美的文档,还围绕它创建商业服务及发展合作伙伴。Laracasts覆盖了所有缺失的文档和应用场景。在ForgeEnvoyer发布之前,Taylor会与众多博主探讨即将发布的功能,这样,它们就能在发布时获得最大的曝光率。该框架还有自己的subredditPackalystPackagist类似,但只面向Laravel,此外还有Larajobs.com。Laravel甚至还有自己的T恤。

因此,在Bruno看来,一个框架要想长远发展,就要在宣传上下一些功夫。比如,请专业人士设计一个好的logo。文档发布之前可以请不相关的人帮助审查,因为正规的英语对于获得良好的第一印象至关重要。要乐于同潜在的开发者布道师交 流,通过询问他们不喜欢什么来提升他们对于产品的信心。在构建产品的过程中,听取其他人的意见和建议,其中可能会有更好的解决方案。让开发者布道师进行与 你的框架相关的写作,这种关系可能会成长为像Laravel和Laracasts一样的互惠关系。在产品未成熟之前,不要公开进行alpha和beta测 试。

Bruno承认,Laravel确实简单易用,但他不喜欢Laravel近乎垄断的地位。他希望能够联系并邀请框架维护者和那些使用这些项目的人,一起构建一个跨框架的知识库,比较各种方案,不是为了证明一个框架比另一个框架好,而是为了相互学习。

对于(图一)所示的结果,网友akmnahid提出了质疑:

这里提到的大部分框架,每个版本都是单列的,但Laravel合并到了一起。

对此,Bruno解释说:

即使将其它框架的每个版本合并,Laravel仍然会胜出。

……除了目录结构和语法的一些变化外,Laravel 4和5几乎完全相同,而Yii1和Yii2差别非常大……

有多名网友也表达了类似的观点。而网友Hall_of_Famer对CodeIgniter获得如此多的票数表示不解。Bruno认为这与开发人员的习惯有关。许多人宁可花20天的时间在遗留代码中“重新造个轮子”,也不愿意花2天的时间学习一个更好的框架。

完整调查结果已经发布在Github上,感兴趣的读者可以下载分析,并从中发现其它一些有趣的现象。

在Linux系统如何让程序开机时自动启动

系统的服务在开机时一般都可以自动启动,那在linux系统下如果想要程序在开机时自动启动怎么办?我们知道在 windows系统“开始”–>“所有程序”–>“启动”里面放个快捷方式就行,那Linux系统下呢?…系统的服务在开机时一般都可以自动启动,那在linux系统下如果想要程序在开机时自动启动怎么办?我们知道在 windows系统“开始”–>“所有程序”–>“启动”里面放个快捷方式就行,那Linux系统下呢?
这也是一个比较简单的问题,有不少的方法可以解决,这里介绍三种方法。因为是简单介绍,所以具体细节不是很详细,可以通过man看看相关手册。 

一、/etc/rc.local 

这是一个最简单的方法,编辑“/etc/rc.local”,把启动程序的shell命令输入进去即可(要输入命令的全路径),类似于windows下的“启动”。 

使用命令 vi /etc/rc.local 然后在文件最后一行添加要执行程序的全路径。 

例如,每次开机时要执行一个haha.sh,这个脚本放在/opt下面,那就可以在“/etc/rc.local”中加一行“/opt/./haha.sh”,或者两行“cd /opt”和“./haha.sh”。 

二、crontab(类似于windows的任务计划服务)

通过crontab可以设定程序的执行时间表,

例如让程序在每天的8点,或者每个星期一的10点执行一次。

 crontab -l 列出时间表;
crontab -e编辑时间表;
crontab -d删除时间表;

 “-l”没什么可说的,就是一个查看而已; 

“-e”是编辑,和vi没什么差别(其实就是用vi编辑一个特定文件); 

“-d”基本不用,因为它把该用户所有的时间表都删除了,一般都是用“-e”编辑把不要了的时间表逐行删除;

 那到底该如何编辑呢? 

crontab文件的格式是:M H D m d CMD。
一个6个字段,其中最后一个CMD就是所要执行的程序,

如haha.sh。
M:分钟(0-59)
H:小时(0-23)
D:日期(1-31)
m:月份(1-12)
d:一个星期中的某天(0-6,0代表周日)
这5个时间字段用空格隔开,其值可以是一个数字,也可以用逗号隔开的多个数字(或其他) ,如果不需设置,则默认为“*”。

 例如,每天的8点5分执行haha.sh,就是“5 8 * * * /opt/./haha.sh”。
好像和“开机程序自动启动”扯远了,现在回归正题。其实上面介绍的crontab的功能已经具备了开机自动启动的能力,可以写一个监测脚本,每5分钟执行一次(*/5 * * * * ./haha.sh),如果程序不在了就重新启动一次。 

编辑文件

#vi /etc/crontab

重启服务

#service crond restart

三、注册系统服务 操作系统自带的服务,如ssh,ftp等等,开机都是自动启动的,我们也可以通过这种方式让自己开发的程序提高“身价”。
  

比如我想把某个已经安装了的服务添加为系统服务,可以执行以下命令: chkconfig –add 服务名称 (首先,添加为系统服务,注意add前面有两个横杠)   chkconfig -leve 启动级别 服务名 on (说明,3级别代表在命令行模式启动,5级别代表在图形界面启动,on表示开启) chkconfig -leve 启动级别 服务名 off (说明,off表示关闭自启动) 

例如:chkconfig -level 3 mysql on (说明:让mysql服务在命令行模式,随系统启动) 也可以使用   chkconfig –add 服务名称    来删除系统服务  如果要查看哪些服务被添加为系统服务可以使用命令 : ntsysv 或者chkconfig –list   如果要查看哪些程序被添加为自启动,可以使用命令  : cat   /etc/rc.local (查看这个文件中添加了哪些程序路径)

 下面举例说说,如何把一个shell脚本添加为系统服务,并跟随系统启动: 可以看到“/etc/rc.d/init.d”下有很多的文件,每个文件都是可以看到内容的,其实都是一些shell脚本。 

系统服务的启动就是通过“/etc/rc.d/init.d”中的脚本文件实现的。我们也可以写一个自己的脚本放在这里。 

脚本文件的内容也很简单,类似于这个样子(例如起个名字叫做“hahad”): . /etc/init.d/functions start() {
echo “Starting my process ”
cd /opt
./haha.sh
}
stop() {
killall haha.sh
echo “Stoped”
}
写了脚本文件之后事情还没有完,

继续完成以下几个步骤: chmod +x hahad                    

#增加执行权限
chkconfig –add hahad            

 #把hahad添加到系统服务列表
chkconfig hahad on                 

#设定hahad的开关(on/off)
chkconfig –list hahad               

#就可以看到已经注册了hahad的服务 这时候才完成了全部工作。

java 基础教程hello world

Java是完全面向对象的语言。Java通过虚拟机的运行机制,实现“跨平台”的理念。我在这里想要呈现一个适合初学者的教程,希望对大家有用。

“Hello World!”

先来看一个HelloWorld.java程序。这个程序在屏幕上打印出一串字符”Hello World!”:

public class HelloWorld
{
    public static void main(String[] args)
    {
        System.out.println("Hello World!");
    }
}

程序中包括Java的一些基本特征:

  • 类(class):上面程序定义了一个类HelloWorld,该类的名字与.java文件的名字相同。
  • 方法(method):类的内部定义了该类的一个方法main。
  • 语句(statement):真正的“打印”功能由一个语句实现,即: System.out.println(“Hello World!”);

 

下面两点有关Java的书写方式:

  • Java中的语句要以;结尾 (与C/C++相同)。
  • 用花括号{}来整合语句,形成程序块。通过程序块,我们可以知道程序的不同部分的范围,比如类从哪里开始,到哪里结束。

编译与运行

Java程序要经过编译器编译才能执行。在Linux或Mac下,可以下载安装Java JDK

使用javac来编译。在命令行中输入下面语句编译:

$javac HelloWorld.java

当前路径下,将有一个名为HelloWorld.class的文件生成。

使用java命令来运行。Java会搜寻该类中的main方法,并执行。

$java HelloWorld

 

变量

计算机语言通常需要在内存中存放数据,比如C语言中的变量,Java也有类似的变量。Java和C语言都是静态类型的语言。在使用变量之前,要声明变量的类型。

变量(variable)占据一定的内存空间。不同类型的变量占据不同的大小。Java中的变量类型如下:

存储大小     例值     注释

byte      1byte        3      字节

int       4bytes       3      整数

short     2bytes       3      短整数

long      8bytes       3      长整数

float     4bytes     1.2      单精度浮点数

double    8bytes     1.2      双精度浮点数

char      2bytes     ‘a’      字符

boolean   1bit      true      布尔值

 

在Java中,变量需要先声明(declare)才能使用。在声明中,我说明变量的类型,赋予变量以特别名字,以便在后面的程序中调用它。你可以在程序中的任意位置声明变量。 比如:

public class Test
{
    public static void main(String[] args)
    {
        System.out.println("Declare in the middle:");
        int a;
        a = 5;
        System.out.println(a);  // print an integer
    }
}

上面a是变量名。可以在声明变量的同时,给变量赋值,比如 int a = 5;

*** “变量”的概念实际上来自于面向过程的编程语言。在Java中,所谓的变量实际上是“基本类型” (premitive type)。我们将在类的讲解中更多深入。

 

上面的程序还可以看到,Java中,可用//引领注释。

 

数组

Java中有数组(array)。数组包含相同类型的多个数据。我用下面方法来声明一个整数数组:

int[] a;

 

在声明数组时,数组所需的空间并没有真正分配给数组。我可以在声明的同时,用new来创建数组所需空间:

int[] a = new int[100];

这里创建了可以容纳100个整数的数组。相应的内存分配也完成了。

 

我还可以在声明的同时,给数组赋值。数组的大小也同时确定。

int[] a = new int[] {1, 3, 5, 7, 9};

使用int[i]来调用数组的i下标元素。i从0开始。

其他类型的数组与整数数组相似。

 

表达式

表达式是变量、常量和运算符的组合,它表示一个数据。1 + 1是常见的表达式。再比如:

public class Test
{
    public static void main(String[] args)
    {
        System.out.println("Declare in the middle:");
        int a;
        a = 5 + 1;
        System.out.println(a);  // print an integer
    }
}

上面的5 + 1也是一个表达式,等于6。

 

数学表达式

数学运算,结果为一个数值

1 + 2                  加法

4 – 3.4                减法

7 * 1.5                乘法

3.5 / 7                除法

7 % 2                  求余数

 

关系表达式

判断表达式是否成立。即一个boolean值,真假

a > 4.2                大于

3.4 >= b               大于等于

1.5 < 9                小于

6 <= 1                 小于等于

2 == 2                 等于

2 != 2                 不等于

 

布林表达式

两个boolean值的与、或、非的逻辑关系

true && false          and

(3 > 1) || (2 == 1)    or

!true                  not

 

位运算

对整数的二进制形式逐位进行逻辑运算,得到一个整数

&                      and

|                      or

^                      xor

~                      not

5 << 3                 0b101 left shift 3 bits

6 >> 1                 0b110 right shift 1 bit

 

还有下列在C中常见的运算符,我会在用到的时候进一步解释:

m++                    变量m加1

n–                    变量n减1

condition ? x1 : x2   condition为一个boolean值。根据condition,取x1或x2的值

 

控制结构

Java中控制结构(control flow)的语法与C类似。它们都使用{}来表达隶属关系。

 

选择 (if)

if (conditon1) {
    statements;
    ...
}
else if (condition2) {
    statements;
    ...
}
else {
    statements;
    ...
}

上面的condition是一个表示真假值的表达式。statements;是语句。

 

循环 (while)

while (condition) {

    statements;

}

 

循环 (do… while)

do {

    statements;

} while(condition);  // 注意结尾的;

 

循环 (for)

for (initial; condition; update) {

    statements;

}

 

跳过或跳出循环

在循环中,可以使用

break; // 跳出循环

continue; // 直接进入下一环

 

练习 写一个Java程序,计算从1加2,加3…… 一直加到999的总和

 

选择 (switch)

switch(expression) {

    case 1:

        statements;

        break;

    case 2:

        statements;

        break;

    …

    default:

        statements;

        break;

}