关于作者

用户名:BluEmOoNz
笔名:BluEmOoNz
地区:
行业:其他

日历  

快速登录

+ 用户名:
+ 密 码:

在线留言



软件下载

我的站点

博客推荐

访问统计:
文章个数:69
评论个数:63
留言条数:16




Powered by BlogDriver 2.1

BoKErSupportedbyVencent

 

文章

已锁定
此日志的浏览权限已被作者锁定,请同作者联系,发送短消息,如果你的身份符合作者的要求,点击此处可以进行浏览

- 作者: BluEmOoNz 2005年02月28日, 星期一 19:19  回复(0) |  引用(0) 加入博采

已锁定
此日志的浏览权限已被作者锁定,请同作者联系,发送短消息,如果你的身份符合作者的要求,点击此处可以进行浏览

- 作者: BluEmOoNz 2005年02月28日, 星期一 19:18  回复(0) |  引用(0) 加入博采

已锁定
此日志的浏览权限已被作者锁定,请同作者联系,发送短消息,如果你的身份符合作者的要求,点击此处可以进行浏览

- 作者: BluEmOoNz 2005年02月28日, 星期一 19:17  回复(0) |  引用(0) 加入博采

已锁定
此日志的浏览权限已被作者锁定,请同作者联系,发送短消息,如果你的身份符合作者的要求,点击此处可以进行浏览

- 作者: BluEmOoNz 2005年02月28日, 星期一 19:15  回复(0) |  引用(0) 加入博采

QQ号码大放送

375084013----rsIj45pTlXEm
121819270----bkZ584MuUQML
375133287----I7k01ZW6h2hX
443597172----7wQ8rmEEIT4D
419526395----XlL6XEtae3Kq
315489725----TaLRSUcxZGtB
273436478----M6ducPVxZkD7
419528990----liZWGG1ri5G6
282517652----w97RnVJbbsLp
393147153----0rmGG94Fjhac
369387810----igyuJuHj8cvb
405873632----I8Z5nGQhmmHS
415604731----PBv8Do3KeZIe
312900459----4pHZi7yXyC7j
349916527----PsOvruvindcr
419532606----xf5ijxE1FOrp
413744566----COJXtl0xuejS
402392560----gNPJw72GBXlR
121849113----HHTYQZKtIYI2

305368207----TOJhUhPQR6Oq
419538369----WX7YzgXMZjeS
402401316----qNcxSrXOZMdq
402401597----bvVjgM4czoYm
121853437----OjUKXQpyxUKW
273449789----x2NFKavcm3Bq
447476220----18Wz8exn2Mvd
273450635----KYxr1hGsRsNA
273450908----QBv5IRHfhKfq
121856815----hZWUI2TQOg3l
421461671----E9Rsvc3U5Nci
447476864----zTTuLjzcYIj6
447477035----JrtY0ftJpLTX
124516894----2O5hTO3Fgeoq
332357885----8c9NgZRqEmBs
121860019----HSuZMpCddShK
280499709----RIx0nHPNZ7Sa
332360206----6LQEYZFP3TSD
379347555----P9D4dBKq34rF
344527138----rOrTkdGo9MHV
272262065----VoF9urf6niDU
121863785----3NhnUuoaMIHp
419568492----D6WGsXqpQrvc
345997935----WBiGkdzQsir1
277934843----DstVk3deKjZw
443635801----mzLloxAc1oUR
369406879----RWCqQTHlGMHb
419574571----TtGoyU0OaZpK
419575509----Us7HPXbX722H
419575830----WkKRZjdGg53W
419577576----IaGOaXIAuPut
124527655----96lJS7SXIya6
124529754----srYDLFWCrwHo
121871759----moArojdDWFoV
402417351----mLaLrnWinKOU
419582669----Bbl48VntWRlq
447479306----lPq3hYboo6q3
124532782----YLFQF3920w7b
373920123----cf2lnIiDGEiy
419587184----9pFB9BEQ8OIS
124535602----b0sNAbNcsN0n
419592076----8ysYzegBBynS
312926423----B6Jnol9rIGTv
280511403----bc5mxwztDC18
289819536----AMIH5vpAIXc3
369415420----m8xYrcuPiyG1
312927720----IWdg0NSo4DPy
121879774----tpNAswjBmZPp
121879855----wCuSg7GF1qyE
419599744----MIuevcCru2LJ
124539564----Mw6fGuZgVwSr
332372357----y9qxdex96hqa
419604241----E8SMXK6BmpOX
419604353----CABjDzG9BAfV
359012773----EQVl6Mj2AS0g
346010866----dlrHytYZyIZA
419610083----ERANpuOWGm4C
443648061----VFF39AOccKSg
419610876----h4ZykGQnyUff
419611519----ZH3MuBX4duVU
332375854----MlK2whKO1jJq
124546203----9zklusmjx0vD
373928453----RCr3WiaWWugd
124546978----JITo4W1bOgaQ
419614475----kP8Ttx2yjKY5
415644942----WOaRmNa1H3pb
419614741----yGagtNe6zwEz
280517447----RHENHgF6Aill
121887298----VwHA93PsUFrY
419617398----fOHQfe1ztsqp
280518342----5mxgHxRPGSH9
289826201----WNR1awG5hUSC
405907627----e9EMUiVgWlVv
344545284----QjAJx0tVaH02
121890827----Dt5Dy4mqAR3n
124552725----hHTytjfcUByt
402430018----sFrsh4luoiEh
443652314----5WRLritj9LHR
124552784----PC0sQtfFkvVa
409094519----lkKvOmKIgvqV
329351264----fKLNVzBfeyxf
360992733----EvwFuXtVp3eE
359019845----5EkHvwwJrQDu
419631284----EZ19vk6yUaLC
349953956----QUasSXkOa4Tv
332382886----x7xKbHwaoIfF
315537626----PXEjIeL4XVaw
419634872----pjH88wLegDkF
273480757----vdeJGbpLQcxC
121898046----au9thxnoWzro
364323282----VnVaYtLuOxvR
273481630----zU1TsuuUCr7y
364324615----k3odrOpYnmTZ
421490930----2HAFcdSBpt0p
282562205----NFy4uaYyQtfG
329356808----28bS2GNWf414
360998951----3FNpwQktPgYf
375197158----q3VdR6qZpCl6
309842731----c37hy4OoHy70
312943318----CFryXCj5wVfL
361000252----Z7LZFkDuVdvm
364327841----lqRlFutgoNEp
443660277----5xwbgdQJnxsK
349960732----Ldf2p1R4EYDd
364328907----JouMeQQNlD3U
369432492----wobkvzMhgzuq
361003172----BGSWxklVDtZS
375200564----GSoZ9GBilkyh
402439011----3ISEdkjCOcQV
413788214----jMHhA7Kyo92P
124562059----ojsJuBLhbAz7
315547494----AvLQYj0u3t2h
282569219----vYGc9mpvGn8C
375203546----zMi4VUm1OOoa
396131975----yjz4n0LI4Ly4
415660853----gc1iiLps6dOk
373946091----mjcc6xrMIztc
369438511----cOgAtSsCsa06
124563274----FJNQvWNm6VCe
375205823----SlD0Ot7QFUvM
369439787----9yiDu7wqFv3K
419645105----1wdQD3VAv0NS
289844829----QeT5wjdOAmPZ
359036374----WHdvWkjxicVK
124564635----ZDv1OyPMJzxF
254176123----hC6Ahd4ErxLN
277972051----KuAts6ac3Ren
277972176----70buVRixKVBD

307656458----t2b5qxBUuHzt
280540422----GhxBgjmY3vMs
289847989----YxpvVcHQE8ZI
447484913----DqaI9oZTdpv2
361012550----SMQ87O6xbQyb
381200653----MowZGcJ7dqVd
121904735----QoyAUYLZBCtq
277973672----I650JCw22FPF
393205663----BIoi5YN26LWg
402451382----sa5rVWURzXQJ
272303277----ZEb79ZcF0Ojx
409118132----ZS9TIuncYzOe
254180865----wweHfUl3OqQg
312959041----l06X4x5QFVrk
419653766----SLCUugqznsi7
447485523----mikZL96goyy1
124568511----qbCN6unghYIG
379391196----6NUjf3395k0D
396142668----srqHdcOOYm21
273501142----rFCKrno6F3bR
305423096----vISFbws4NyJp
124568732----Q84LjEzuuGGK
344571703----2LhOBAONZiur
359043689----Jv4yoh58JXrm
254183332----ULZw14mZKoYC
344572577----ECPIExn2mwc4
124569850----wmduuRv1ksQp
364345414----sZlFCKZwJoEm
379393558----zifNAjPTAnqP
375217643----YgrqOw2pkR5e
419658268----JpsJcPqz0YrO
124570483----YniQQkTe7n6p
346043476----l7OKMxUL9sfL
364346894----ruF2l2dwcKjG
329378753----aonetsrTGi6z
396146216----sL1YkHJYWB62
273504806----7nRfikGAWr45
375218447----8HEAp9sBbhS5
381208043----xSNyjRW54Zmu
282584587----4J5q9kcujbr0
364347562----Ucbxz0gmTOm5
349981266----SGr9t5nKELs8
364348718----lfzEW761Rrw7
381209620----9deC28cRapht
381209633----L8ySuU18mW96
312965506----fNWeDd2IMcya
405939573----LWBVqg6bNDck
344576613----y2YMmRxz3cQk
346045967----QBFvj7zemu3T
393214402----TitKnLOMM3Lz
419663054----epVKLmUbT91Q
419663193----Ut8fB3OY81j2
443682783----z8mhpXo1SwDp
124573515----uarjDXtrKfL1
415679229----nzE4swUlTsUa
332410932----Sqhh91rojOqj
419665227----IXPJObtgxjcE
415680197----TWJRUSvqK9G9
349984297----Vh6GfSiVRW7u
329383743----xFTf8fKaX81W
359051429----WEVFgwfYWdY5
415680707----otm261ehJJvK
359051645----3SeevgyArqWW
413810588----r2i09HT9m1Ju
419668159----lBbP7gowswST
312969868----uvsMukzPwnzW
272315305----EzX2RQO6U61g
273510646----kErz5gsMagnP
447487266----FSMk0zPOLKDb
250274561----nFKCmGUtBlQV
369458754----2K9jPqMQSaSM
419670356----420xBuVFG2FL
273511687----sVmwBNc8vOOS
312971153----ohWEIQxA7mWN
361027586----hECkJ8ybaZ8m
254192641----cCSaMffgBMLw
419672121----OsIeQKxgBM8p
419672279----sijhAM9qU5Qr
124577726----sYjk9AUJIDMz
282592329----SpqJuIILfF5U
375227303----89FtM4NK8RmI
405947234----zXdUNYfOMDif
332417238----GfCA6Laoq817
121915547----11U7Msc4TCHI
359057193----zqiM6VLSjO2s
307676157----gANSmBUZsMlT
121916479----05mo4bXpY9nj
419676819----rozr8Nbj8sa3
447488071----jkB3CANLLQWj
402469358----6FjtsuKlEcCG
121917409----zkUAay4nNUk7
121917470----sATrSOeiPV3F
447488131----9QsgEtpfmNwB
121917746----KaYCpwiWJjuw
121917930----BMgK0CG1qWrw
419680657----PnMKhaxo8rXz
124581952----WbaLiQf058OS
415688942----kcpNMS6lIR9J
307678629----3AgX7UQeJAZI
364360593----fgZgugV647wX
393226095----2zREjy50k64L
282597541----fSReJGgls8Mt
332421321----dW7D1suZ3AG6
419684936----Ud5r9QLS2MNb
124584501----gkzre7DtU4Vt
272323753----BZeUqJM6ePPM
443694607----oOaoBOoQN0JR
121922054----3TQTqIZu9nLt
124584961----EVvO236M7lHF
413820660----aT65x81WAJKN
419686695----BKGdnlfak5dN
124585288----edTEhw2QnAUa

329394816----TlBVChlxsy9C
250319476----WO1deP0kqBru
419687947----wTeRD8QlCPHV
289872133----uQmxeGFte3QA
359063501----DNNQwnhiE67k
373976493----2pVkzGi58DYR
272325942----YPfAJLKfY3VS
369468282----aDLXxEZwzosG
121923918----HToO3jsqwQu3
349997469----rwIDUiJ4pvnP
359064355----lXSAAh78uKbK
413823470----X1WPrtHPUfmi
415694266----fLyKttCJdrfd
443697721----ksNAD9OZRAW6
121924306----DL0AED7KyfSl
393231072----PpoQ6QxrsE7B
402475980----qgll5zBe3GAy
289874374----FcdjoUKWKUXJ
254204779----K7xXfmcDVaXG
289875834----5a3e6bVczBrA
124587533----MDKvrhTiahDW
346065805----ufq2drDm8mPg
381229651----Wjv0117g1k3B
443700178----bxlhsM1dG8hh
282605345----5rdlPU1hr6kw
312985163----CkFQrwNF9f0F
361041005----xZxtMIeaH6X3
272331348----06EG4tkwemgS
282606536----HFkKFwYzYp5R
359068761----TK0O4Cdu8Ags
413827870----TDl1s15BrVHM
332430153----dfssTnnSszie
350002975----APDVc9o5VXKN
393235519----ZCT7SwOQ8HlW
402479987----FLObr2aokcrX
402480061----aRC9Sn9VvUY4
307688912----Dn03XQ1SWKqD
332430908----GYtFGUfNBLrs
361042675----oaaendHacfwl
396170336----n9XY2FGv46gE
405961606----VMtiNDiKLYUF
344598330----leQT5xwH4gd9
419693643----CVO6o3VlpSZB
421539919----vSCv8HYpoxHT
447490342----hnVeaNGzgTu2
124588584----RdLpvyrwVKre
305451860----xfu0KTG700S0
419693750----uOxUXppdzOmK
346070328----ZlCdIbxy69ht
250366886----upw80tdsQjDx
254211758----N2wkG8zo00qL
305452950----N7Q2m1Gjy1Pm
415701884----FnfJGBGVpOSN
369476645----UYyqOQ2skU8S
332435146----R50A27uSlfoH
419694967----iNrFCGTplRej
286628314----FyAVgRNT5YCR
359074121----nWYPpvkFZBLR
379422190----KMc5crScTI7G
405966974----Tlon3tJwR3Mu
280576669----dSworjCIvrvk
332436435----5zMiUe5nKitB
359074616----sjwhV39NHz5B
359074841----YMNyGsmqQEXb
282613660----aKrb92WK2siL
447491020----CpBOYKyMdWgm
413835504----2KkmlMPoBPEI
121927367----SphCzt6kHkrM
282614631----0Y7DKFT4O8RC
282614869----ggyB17pCsLRk
286630142----OgNaLHchkTBw
447491187----vm5Iwfob9JJ7
402485264----GDJhKQIxAfIa
305457921----7Tb29HF9wzFE
124590126----Hbx6nomJTmjo
282614976----KOFdmDpOIf20
307696423----2iuiswZV3mfJ
443709374----O6JhAwXiG3cD
282616468----Qf5cHXDekWq2
307697869----6NyCQyYDJGaR
447491602----25fEvCOKFVxD
447491618----yXh8GN9qQBQJ
346077466----YRuMAhc3CGxH
375250966----TEzeQFvgG6UM
447491812----3bUjA389PXh8
280583326----9Afja4oFU9bo
289891563----X507g5oqRTXN
361053043----OMQVqpmTayQK
447491948----3z10I1X2HleZ
381245122----rsBFJYSguzzf
307701674----Ceqlge9G0aJO
278018499----bsA9BTBfGgsx
379428945----qQcQbFci8Qzo
409160980----R6P353bi5ApN
421553424----Amtr2WLrL30M
124591296----XPKl5EkFV1vo
364383070----89UjAwfiRrYq
373996859----f975hHoRdA1I
405977504----2vPeUvBioiNn
346083405----ZQvtseX0pGlP
313002779----pUW0f9kExMFt
447492639----XVrpT2fOBwOV
375257883----NgaKdkzLAtEA
124592019----PFfS4x2w2GyT
273545301----C7kgoTmYwoyD
286641113----e3E6cAf9NIvL
307706599----mZpKDCpKmXSq
313004044----2h2qtbvVTpa2
280590350----Xm4vahdiQo32
250449974----g2vutPzmB1nZ
254227861----xefEEzwbeHcS
280590714----idup0kA48BM7
305469309----qrbGxFkNgUiU
254228999----uyNsjxuCtMwO
344617318----VgVwfHLXOf7T
447493385----b1Oa5vravJvH
278026601----FMcnXZBgfdRP
372005842----ixKqnx66GUYK
379436142----bIdnI4RI1cRP
273550479----ni8PAnRaOSah
344620663----Gv2I8udE6xsu
364392755----vBUQGRUd6Zcw
315610192----5QFHhlwDVk0k
272357669----b1rRugBk4q0z
379440135----sHcrO2pW5CRp
305477008----ngiwI8xbLSz2
419706804----efJ6rEdukFIG
280599667----J9IStbYZerBD

415726021----kJmaaRI7zhZu
361072004----ksZWlmmMxadC
396198982----K5xkp8iV5sTN
305480050----avYLmZ3lOUR9
413858309----YYYqRvfYIX0u
381262513----7zlRmCcQG7zQ
447495236----19uJHQWkntcg
121934798----5ECbBjylziBR
447495462----Os0CDRiY3grP
375274996----WDAro1LSTDMw
305483485----dgEb7kZenIw1
419715959----yrJbQZ2KulK4
124598513----YwLw1qelVfYH
361077329----M5Vkdxo7PeBx
381267384----nZNT3Bjc0Bhv
415735069----8kSk10UIwXLV
419722674----J2FFNrvKUVlY
372019381----1M5AfF54MYFe
419730353----JNUCCT7O6UpY
124603878----mbwtLR0vyP1F
375281882----63PDR9JS40C8
447497123----fdJfaQfv7qk6
379459484----iq8Z6etKaUog
307732275----2tWrngnJOQzE
297310916----wm4lNHLNGONT
415748230----TbquYlO6VHkx
272387391----cav0dGWc6mAj
419774240----DRnQ0I2RLRKj
124635570----aGG5cot3Uumx
250975966----RsPkH4gfUOJW
409276894----2Jesh25zKNGd
307823581----jDzFxNxwB0FN
372120185----O1ud5G2zVWM7


- 作者: BluEmOoNz 2004年12月20日, 星期一 12:47  回复(0) |  引用(0) 加入博采

转载:PHP中的加密功能

PHP中的加密功能
数据加密在我们生活中的地位已经越来越重要了,尤其是考虑到在网络上发生的大量交易和传输的大量数据。如果对于采用安全措施有兴趣的话,也一定会有兴趣了解PHP提供的一系列安全功能。在本篇文章中,我们将介绍这些功能,提供一些基本的用法,以便你能够为自己的应用软件中增加安全功能。

预备知识
在详细介绍PHP的安全功能之前,我们需要花点时间来向没有接触过这方面内容的读者介绍一些有关密码学的基本知识,如果对密码学的基本概念已经非常熟悉,就可以跳过去这一部分。

密码学可以通俗地被描述为对加/解密的研究和实验,加密是将易懂的资料转换为不易懂资料的过程,解密则是将不易懂的资料转换为原来易懂资料的过程。不易懂的资料被称作密码,易懂的资料被称作明码。

数据的加/解密都需要一定的算法,这些算法可以非常地简单,如著名的凯撒码,但当前的加密算法要相对复杂得多,其中一些利用现有的方法甚至是无法破译的。

PHP的加密功能
只要有一点使用非Windows平台经验的人可能对crypt()也相当熟悉,这一函数完成被称作单向加密的功能,它可以加密一些明码,但不能够将密码转换为原来的明码。尽管从表面上来看这似乎是一个没有什么用处的功能,但它的确被广泛用来保证系统密码的完整性。因为,单向加密的口令一旦落入第三方人的手里,由于不能被还原为明文,因此也没有什么大用处。在验证用户输入的口令时,用户的输入采用的也是单向算法,如果输入与存储的经加密后的口令相匹配,则输入的口信一定是正确的。

PHP同样提供了使用其crypt()函数完成单向加密功能的可能性。我将在这里简要地介绍该函数:

string crypt (string input_string [, string salt])
其中的input_string参数是需要加密的字符串,第二个可选的salt是一个位字串,它能够影响加密的暗码,进一步地排除被称作预计算攻击的可能性。缺省情况下,PHP使用一个2个字符的DES干扰串,如果你的系统使用的是MD5(我将在以后介绍MD5算法),它会使用一个12个字符的干扰串。顺便说一下,可以通过执行下面的命令发现系统将要使用的干扰串的长度:

print "My system salt size is: ". CRYPT_SALT_LENGTH;
系统也可能支持其他的加密算法。crypt()支持四种算法,下面是它支持的算法和相应的salt参数的长度:

算法 Salt长度
CRYPT_STD_DES 2-character (Default)
CRYPT_EXT_DES 9-character
CRYPT_MD5 12-character beginning with $1$
CRYPT_BLOWFISH 16-character beginning with $2$

用crypt()实现用户身份验证
作为crypt()函数的一个例子,考虑这样一种情况,你希望创建一段PHP脚本程序限制对一个目录的访问,只允许能够提供正确的用户名和口令的用户访问这一目录。我将把资料存储在我喜欢的数据库MySQL的一个表中。下面我们以创建这个被称作members的表开始我们的例子:

mysql>CREATE TABLE members (
->username CHAR(14) NOT NULL,
->password CHAR(32) NOT NULL,
->PRIMARY KEY(username)
->);

然后,我们假定下面的数据已经存储在该表中:

用户名 密码
clark keloD1C377lKE
bruce ba1T7vnz9AWgk
peter paLUvRWsRLZ4U

这些加密的口令对应的明码分别是kent、banner和parker。注意一下每个口令的前二个字母,这是因为我使用了下面的代码,根据口令的前二个字母创建干扰串的:

$enteredPassword.
$salt = substr($enteredPassword, 0, 2);
$userPswd = crypt($enteredPassword, $salt);
// $userPswd然后就和用户名一起存储在MySQL中

我将使用Apache的口令-应答认证配置提示用户输入用户名和口令,一个鲜为人知的有关PHP的信息是,它可以把Apache的口令-应答系统输入的用户名和口令识别为$PHP_AUTH_USER和$PHP_AUTH_PW,我将在身份验证脚本中用到这二个变量。花一些时间仔细阅读下面的脚本,多注意一下其中的解释,以便更好地理解下面的代码:

crypt()和Apache的口令-应答验证系统的应用
<?php

$host = "localhost";
$user = "zorro";
$pswd = "hellodolly";
$db = "users";

// Set authorization to False

$authorization = 0;

// Verify that user has entered username and password

if (isset($PHP_AUTH_USER) && isset($PHP_AUTH_PW)) :

mysql_pconnect($host, $user, $pswd) or die("Can't connect to MySQL
server!");

mysql_select_db($db) or die("Can't select database!");

// Perform the encryption
$salt = substr($PHP_AUTH_PW, 0, 2);
$encrypted_pswd = crypt($PHP_AUTH_PW, $salt);

// Build the query

$query = "SELECT username FROM members WHERE
username = '$PHP_AUTH_USER' AND
password = '$encrypted_pswd'";

// Execute the query

if (mysql_numrows(mysql_query($query)) == 1) :
$authorization = 1;
endif;

endif;

// confirm authorization

if (! $authorization) :

header('WWW-Authenticate: Basic realm="Private"');
header('HTTP/1.0 401 Unauthorized');
print "You are unauthorized to enter this area.";
exit;

else :

print "This is the secret data!";

endif;

?>

上面就是一个核实用户访问权限的简单身份验证系统。在使用crypt()保护重要的机密资料时,记住在缺省状态下使用的crypt()并不是最安全的,只能用在对安全性要求较低的系统中,如果需要较高的安全性能,就需要我在本篇文章的后面介绍的算法。

下面我将介绍另一个PHP支持的函数━━md5(),这一函数使用MD5散列算法,它有几种很有趣的用法值得一提:

混编
一个混编函数可以将一个可变长度的信息变换为具有固定长度被混编过的输出,也被称作"信息文摘"。这是十分有用的,因为一个固定长度的字符串可以用来检查文件的完整性和验证数字签名以及用户身份验证。由于它适合于PHP,PHP内置的md5()混编函数将把一个可变长度的信息转换为128位(32个字符)的信息文摘。混编的一个有趣的特点是不能通过分析混编后的信息得到原来的明码,因为混编后的结果与原来的明码内容没有依赖关系。 即便只改变一个字符串中的一个字符,也将使得MD5混编算法计算出二个截然不同的结果。我们首先来看下表的内容及其相应的结果:

 
使用md5()混编字符串
<?php
$msg = "This is some message that I just wrote";
$enc_msg = md5($msg);
print "hash: $enc_msg ";
?>

结果:

hash: 81ea092649ca32b5ba375e81d8f4972c
注意,结果的长度为32个字符。再来看一下下面的表,其中的$msg的值有了一点微小的变化:

使用md5()对一个稍微变化的字符串进行混编
<?php
//注意,message中少了一个s
$msg = "This is some mesage that I just wrote";
$enc_msg = md5($msg);
print "hash2: $enc_msg <br /><br />";
?>

结果:

hash2: e86cf511bd5490d46d5cd61738c82c0c
可以发现,尽管二个结果的长度都是32个字符,但明文中一点微小的变化使得结果发生了很大的变化,因此,混编和md5()函数是检查数据中微小变化的一个很好的工具。

尽管crypt()和md5()各有用处,但二者在功能上都受到一定的限制。在下面的部分中,我们将介绍二个非常有用的被称作Mcrypt和Mhash的PHP扩展,将大大拓展PHP用户在加密方面的选择。

尽管我们在上面的小节中说明了单向加密的重要性,但有时我们可能需要在加密后,再把密码数据还原成原来的数据,幸运的是,PHP通过Mcrypt扩展库的形式提供了这种可能性。

Mcrypt
Mcrypt 2.5.7 Unix | Win32
Mcrypt 2.4.7是一个功能强大的加密算法扩展库,它包括有22种算法,其中就包括下面的几种算法:

Blowfish RC2 Safer-sk64 xtea
Cast-256 RC4 Safer-sk128
DES RC4-iv Serpent
Enigma Rijndael-128 Threeway
Gost Rijndael-192 TripleDES
LOKI97 Rijndael-256 Twofish
PanamaSaferplus Wake
安装:
在标准的PHP软件包中不包括Mcrypt,因此需要下载它,下载的地址为:ftp://argeas.cs-net.gr/pub/unix/mcr...它扩充在PHP中:

下载Mcrypt软件包。
gunzipmcrypt-x.x.x.tar.gz
tar -xvfmcrypt-x.x.x.tar
./configure --disable-posix-threads
make
make install
cd to your PHP directory.
./configure -with-mcrypt=[dir] [--other-configuration-directives]
make
make install
当然了,根据你的要求和PHP安装时与互联网服务器软件的关系,上面的过程可能需要作适当的修改。

使用Mcrypt
Mcrypt的优点不仅仅在于其提供的加密算法较多,还在于它可以对数据进行加/解密处理,此外,它还提供了35种处理数据用的函数。尽管对这些函数进行详细介绍已经超出了这篇文章的范围,我还是要就几个典型的函数作一下简要的介绍。

首先,我将介绍如何使用Mcrypt扩展库对数据进行加密,然后再介绍如何使用它进行解密。下面的代码对这一过程进行了演示,首先是对数据进行加密,然后在浏览器上显示加密后的数据,并将加密后的数据还原为原来的字符串,将它显示在浏览器上。

使用Mcrypt对数据进行加、解密
<?php

// Designate string to be encrypted
$string = "Applied Cryptography, by Bruce Schneier, is
a wonderful cryptography reference.";

// Encryption/decryption key
$key = "Four score and twenty years ago";

// Encryption Algorithm
$cipher_alg = MCRYPT_RIJNDAEL_128;

// Create the initialization vector for added security.
$iv = mcrypt_create_iv(mcrypt_get_iv_size($cipher_alg,
MCRYPT_MODE_ECB), MCRYPT_RAND);

// Output original string
print "Original string: $string <p>";

// Encrypt $string
$encrypted_string = mcrypt_encrypt($cipher_alg, $key,
$string, MCRYPT_MODE_CBC, $iv);

// Convert to hexadecimal and output to browser
print "Encrypted string: ".bin2hex($encrypted_string)."<p>";

$decrypted_string = mcrypt_decrypt($cipher_alg, $key,
$encrypted_string, MCRYPT_MODE_CBC, $iv);

print "Decrypted string: $decrypted_string";

?>

执行上面的脚本将会产生下面的输出:

Original string: Applied Cryptography, by Bruce Schneier, is a wonderful cryptography reference.

Encrypted string: 02a7c58b1ebd22a9523468694b091e60411cc4dea8652bb8072 34fa06bbfb20e71ecf525f29df58e28f3d9bf541f7ebcecf62b c89fde4d8e7ba1e6cc9ea24850478c11742f5cfa1d23fe22fe8 bfbab5e

Decrypted string: Applied Cryptography, by Bruce Schneier, is a wonderful cryptography reference.

上面的代码中二个最典型的函数是mcrypt_encrypt()和mcrypt_decrypt(),它们的用途是显而易见的。我使用了"电报密码本"模式,Mcrypt提供了几种加密方式,由于每种加密方式都有可以影响密码安全的特定字符,因此每种模式都需要了解。对于没有接触过密码系统的读者来说,可能对mcrypt_create_iv()函数更有兴趣,尽管对这一函数进行彻底的解释已经超出了本篇文章的范围,但我仍然会提到它创建的初始化向量(hence, iv),这一向量可以使每条信息彼此独立。尽管不是所有的模式都需要这一初始化变量,但如果在要求的模式中没有提供这一变量,PHP就会给出警告信息。

Mhash扩展库
http://sourceforge.net/projects/mhash/

0.8.3版的Mhash扩展库支持12种混编算法,仔细检查Mhash v.0.8.3的头文件mhash.h可以知道,它支持下面的混编算法:

CRC32 HAVAL160 MD5
CRC32B HAVAL192 RIPEMD160
GOST HAVAL224 SHA1
HAVAL128 HAVAL256 TIGER
安装
象Mcrypt一样,Mhash也没有包括在PHP软件包中,对于非Windows用户而言,下面是安装过程:

下载Mhash扩展库
gunzipmhash-x.x.x.tar.gz
tar -xvfmhash-x.x.x.tar
./configure
make
make install
cd <PHP所在的目录>
./configure -with-mhash=[dir] [--other-configuration-directives]
make
make install
象Mcrypt一样,根据PHP在互联网服务器软件上的安装方式,可能需要对Mhash进行其他的配置。

对于Windows用户而言,http://www.php4win.de 中有一个很好的包括Mhash扩展库在内的PHP软件包。只要下载并进行解压缩,然后根据其中的readme.first文档中的指令进行安装即可

使用Mhash
对信息进行混编非常简单,看一下下面的例子:

<?php
$hash_alg = MHASH_TIGER;
$message = "These are the directions to the secret fort. Two steps left, three steps right, and cha chacha.";
$hashed_message = mhash($hash_alg, $message);
print "The hashed message is ". bin2hex($hashed_message);
?>

执行这一段脚本程序将得到下面的输出结果:

The hashed message is 07a92a4db3a4177f19ec9034ae5400eb60d1a9fbb4ade461
在这里使用bin2hex()函数的目的是方便我们理解$hashed_message的输出,这是因为混编的结果是二进制格式,为了能够将它转化为易于理解的格式,必须将它转换为十六进制格式。

需要注意的是,混编是单向功能,其结果不依赖输入,因此可以公开显示这一信息。这一策略通常用于让用户比较下载文件和系统管理员提供的文件,以确保文件的完整性。

Mhash还有其他一些有用的函数。例如,我需要输出一个Mhash支持的算法的名字,由于Mhash支持的所有算法的名字都以MHASH_开头,因此,可以通过执行如下的代码完成这一任务:

<?php
$hash_alg = MHASH_TIGER;
print "This data has been hashed with the".mhash_get_hash_name($hashed_message)."hashing algorithm.";
?>

得到的输出是:

This data has been hashed with the TIGER hashing algorithm.
关于PHP和加密最后需要注意的一个问题
关于PHP和加密需要注意的最后的一个重要问题是在服务器和客户端之间传输的数据在传输过程中是不安全的!PHP是一种服务器端技术,不能阻止数据在传输过程中泄密。因此,如果想实现一个完整的安全应用,建议选用Apache-SSL或其他的安全服务器布置。

结论
这篇文章介绍了PHP最有用的功能之一━━数据加密,不仅讨论了PHP内置的crypt() 和md5()加密函数,还讨论了用于数据加密的功能强大的扩展库━━Mcrypt和Mhash。在这篇文章最后,我需要指出的是,一个真正安全的PHP应用还应该包括安全的服务器,由于PHP是一种服务器端的技术,因此,在数据由客户端向服务器端进行传输时,它不能保证数据的安全。
原作者:刘彦青


- 作者: BluEmOoNz 2004年12月4日, 星期六 12:46  回复(0) |  引用(0) 加入博采

转载:小组开发环境搭建备忘

                                  ——dhcp+apache+ftp+cvs+samba

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
http://www.chedong.com/tech/dev.html

关键词:linux develop environment cvs version contral gnats bug tracking samba dhcpd wget

内容摘要:本文主要介绍一些小组开发环境搭建中经常会遇到一些服务器服务设置,这些服务很多都是鉴于大部分的开发客户端仍然是Windows设置的,每个服务都提供了简单的基本配置示范。包括:

  • IP管理(DHCP):服务器IP地址的管理和解析(结合SAMBA的WINS服务),开发客户端的IP管理;
  • WEB服务(APACHE):文档共享,CVS的WEB界面浏览,论坛工具等;
  • FTP服务(FTP):用于文件下载/共享;
  • 版本控制(CVS):程序源代码和文档的版本控制;
  • 文件共享(SAMBA):基于NETBIOS的文件共享,方便WINDOWS客户端的访问(比如一些工具的安装等);
  • 数据库服务器(MYSQL):一些应用的后台数据库服务;
  • 备份机制(wget + rsync):备份

很多设置是缺省按照在bash环境中,在tcsh环境中,有一些设置不太一直。

服务器规划如下:

 主服务器 (Main) 备份服务器(Backup)
__________________ _______________
|APACHE WEB SERVER | | File Backup |
|SAMBA SHARE | | |
|DHCP SERVER | | DHCP Backup |
|CVS SERVER | | MySQL server |
|WIKI/BLOG SERVER | <=Backup=> | |
|Database backup | | |
------------------ --------------- 

硬件准备:至少要2台服务器

  1. 从理论上说,任何系统的崩溃只是时间问题,而且谁也不能保证开发者不犯错误;
  2. 解决以上问题的办法只有:备份,备份,备份......

操作系统准备

FreeBSD或GNU/Linux,系统安装时,本文的配置主要以在RedHat 8上运行为例。注意:安装时要将"开发工具"大类选上,后面的很多工具都需要使用GCC进行编译,有的应用脚本运行用到了perl。2台主服务器分别使用 IP地址192.168.0.200和192.168.0.201
语言环境缺省设置:

vi /etc/sysconfig/i18n 

删除UTF-8相关设置:
LANG="en_US"
SUPPORTED="en_US:en"
SYSFONT="latarcyrheb-sun16"
GNU/Linux安装完后:经常有很多不必要的服务需要删除,但根据服务器的不同,
要删除的服务也不一样:本来是想总结一个统一的脚本,后来发现是需要删除的
服务比需要保留的服务多,而且缺省有那些服务和系统版本,安装的模式也相关。
这里我总结的了一个简单的方法来删除不必要的服务:

首先:备份原始服务设置:
#chkconfig --list > chkconfig.orig

生成删除脚本:把所有在LEVEL 3启动的服务过滤出来,并生成chkconfig service off 这样的命令
#chkconfig --list | grep 3:on | awk '{print "chkconfig "$1" off"}'
chkconfig kudzu off
chkconfig syslog off
chkconfig netfs off
chkconfig network off
chkconfig random off
chkconfig rawdevices off
chkconfig pcmcia off
chkconfig keytable off
chkconfig apmd off
chkconfig atd off
chkconfig gpm off
chkconfig autofs off
chkconfig iptables off
chkconfig isdn off
chkconfig sshd off
chkconfig portmap off
chkconfig nfslock off
chkconfig sendmail off
chkconfig rhnsd off
chkconfig crond off
chkconfig anacron off
chkconfig xfs off
chkconfig xinetd off

我们把需要保留的服务从这个列表中删除:
一般WEB服务器只留network sshd crond atd syslog

删掉相应的行以后就生成了不需要的服务删除脚本:
chkconfig kudzu off
chkconfig syslog off
chkconfig netfs off
chkconfig rawdevices off
chkconfig pcmcia off
chkconfig keytable off
chkconfig apmd off
chkconfig gpm off
chkconfig autofs off
chkconfig iptables off
chkconfig isdn off
chkconfig portmap off
chkconfig nfslock off
chkconfig sendmail off
chkconfig rhnsd off
chkconfig xfs off
chkconfig xinetd off

2台机器上都安装的服务:SSH FTP DHCP服务

SSH

基本的登陆服务,对于内部分开发来说一般用缺省的就可以了,但是建议将/etc/ssh/sshd_config中的:
PermitRootLogin yes改成PermitRootLogin no

FTP

建议用proftpd代替原有的ftp服务:http://www.proftpd.org/ 当然如果是vsftpd就不用换了
安装:tar zxf proftpd-version.tar.gz; cd proftpd-version/; ./configure; make; make install
缺省配置/usr/local/etc/proftpd.conf

ServerName "ProFTPD"
ServerType standalone
DefaultServer on
AllowOverwrite on
Port 21
Umask 022

UseReverseDNS off
MaxInstances 30
User apache
Group apache
  1. 不反相解析登陆机器的域名 UseReverseDNS off
  2. 使用了系统缺省的apache用户/组运行服务
  3. 使用AuthUserFile把一些虚拟用户映射成系统帐户是一种更安全的方式,可以把多个只需要FTP权限的开发者用虚拟帐号映射成一个系统用户。这些虚拟用户的认证密码在ftpd.passwd中设置,从而实现了于系统认证的分离:
    ftpasswd是一个perl脚本,下载即可使用: ftpasswd --passwd --name=test --uid=501 --gid=501 --home=/home/test --shell=/sbin/nologin --file=/etc/ftpd.passwd
    然后在proftpd.conf配置中增加:DefaultRoot ~ 让用户只能在自己的目录下工作,不能通过cd ..转向更上级目录进行操作
    AuthUserFile /etc/ftpd.passwd
    DefaultRoot  ~

    DHCP

    为了更方便的管理在同一个局域网中开发者的IP地址和服务器的IP地址,最好将服务器安排在一定范围内的静态IP内(比如 192.168.0.200以上),将(192.168.0.10-200)范围内为开发机客户端提供动态IP。假设我们的主服务器 (192.168.0.200)和辅助开发服务器(192.168.0.201)使用静态IP,同时为网段内提供192.168.0.10-200动态 IP分配服务。DHCP服务在2台服务器上都安装,一个做主DHCP服务,用于给子网IP池提供70%的IP,另外一台做备份,拥有IP池的30%。在例子中:200负责10-100,201负责110-150。缺省dhcpd没有安装的话,从安装盘上找到DHCP软件包安装或者从http://www.isc.org下载源文件编译即可(安装位置和配置文件可能有所不同)。缺省配置文件位于/etc/dhcpd.conf

    http://www.isc.org下载源文件编译即可(安装位置和配置文件可能有所不同)。缺省配置文件位于/etc/dhcpd.conf http://www.isc.org下载源文件编译即可(安装位置和配置文件可能有所不同)。缺省配置文件位于/etc/dhcpd.conf http://www.isc.org下载源文件编译即可(安装位置和配置文件可能有所不同)。缺省配置文件位于/etc/dhcpd.conf

DHCP

为了更方便的管理在同一个局域网中开发者的IP地址和服务器的IP地址,最好将服务器安排在一定范围内的静态IP内(比如 192.168.0.200以上),将(192.168.0.10-200)范围内为开发机客户端提供动态IP。假设我们的主服务器 (192.168.0.200)和辅助开发服务器(192.168.0.201)使用静态IP,同时为网段内提供192.168.0.10-200动态 IP分配服务。DHCP服务在2台服务器上都安装,一个做主DHCP服务,用于给子网IP池提供70%的IP,另外一台做备份,拥有IP池的30%。在例子中:200负责10-100,201负责110-150。缺省dhcpd没有安装的话,从安装盘上找到DHCP软件包安装或者从http://www.isc.org下载源文件编译即可(安装位置和配置文件可能有所不同)。缺省配置文件位于/etc/dhcpd.conf

缺省配置:主服务器上

ddns-update-style none;
default-lease-time 120000;
max-lease-time 920000;
option subnet-mask 255.255.255.0;
option broadcast-address 192.168.0.255;
option netbios-name-servers 192.168.0.200;
option routers 192.168.0.1;
option domain-name-servers 202.106.196.115,202.96.199.133;
option domain-name "example.com";

subnet 192.168.0.0 netmask 255.255.255.0{
range 192.168.0.10 192.168.0.100;
}

说明:
缺省每个IP租期2天: default-lease-time 120000;
最长租期: max-lease-time 920000;
缺省子网掩码:option subnet-mask 255.255.255.0;
缺省广播地址:option broadcast-address 192.168.0.255;
让192.168.0.200上的samba服务启用WINS服务:用于内部域名解析
option netbios-name-servers 192.168.0.200;
缺省网关 option routers 192.168.0.1;
缺省域名服务器 option domain-name-servers 202.106.196.115,202.96.199.133;
缺省域名 option domain-name "example.com";

#一个缺省的子网设置:
subnet 192.168.0.0 netmask 255.255.255.0{
#为子网动态分配0.10-100的IP
range 192.168.0.10 192.168.0.100;
}

辅DHCP服务器上唯一不同的地方是:为子网动态分配0.110-150的IP,主DHCP和附DHCP服务器的IP池不能相互重叠

subnet 192.168.0.0 netmask 255.255.255.0{ 
range 192.168.0.110 192.168.0.150;
}

注意:
如果主服务器是2块网卡并同时用作NAT服务,则外网IP是DHCP不能广播的,需要将外网IP地址屏蔽广播
加入:
subnet 202.102.34.102 netmask 255.255.255.255 {}

主服务器上的应用安装:

SAMBA服务:用于文件的共享和内部WINS解析

这里只做一个只读共享的简单配置,

[global]
#别人会通过"网上邻居"看到WORKGROUP组里名为的Linux机器,注释是:My Samba Server
workgroup = WORKGROUP
netbios name = Linux
server string = My Samba Server

#日志设置
log file = /var/log/samba/%m.log
max log size = 50

#安全设置
security = share

#用SAMBA的WINS服务支持,并且用/etc/hosts做内部域名解析
wins support = yes
name resolve order = hosts lmhosts wins bcast
dns proxy = yes

[public]
#一个共享设置
comment = Public Stuff
path = /home/share
public = yes
guest ok = yes
read only = yes
writable = no
printable = no

[docs] #一个需要密码验证的设置,密码通过#smbpasswd -a user password增加
       comment = Public Stuff security = user encrypt passwords = yes 
       smb passwd file = /etc/samba/smbpasswd 
       path = /home/docs public = yes guest ok = no read only = yes writable = no
在这里为了让大家能够在内部使用dev.example.com访问主服务器(192.168.0.200),
我用DHCP设置主服务器(192.168.0.200)同时也是是内部的WINS服务器,
而在200的SAMBA服务中,启用了WINS支持,并设置WINS用可以利用DNS做 NETBIOS名称解析。
这样如果DNS读取的是/etc/hosts文件中的设置的话,hosts文件就可以当作WINS域名配置文件了,在 /etc/hosts里设置了:
192.168.0.200 dev.example.com bbs.example.com dev bbs192.168.0.201 bak.example.com backup后,
通过DHCP获得IP的内网客户端就可以直接通过: dev.example.com访问开发服务器了。
所有的机器名前缀我都使用了缩写:dev, bbs bak之类的,原因是samba的NMBD实际上是NETBIOS名称的解析,
名称长度是16个字符(实际是15个)有限制的。因此,虽然 192.168.0.202 username.example.com虽然是
一个合法的DNS名称解析,但由于username.example.com长度超过了16个字符,所以通过SAMBA的WINS服务
解析仍然无法找到。dev.chedong.com相当于\\dev.chedong.com\这样的一台机器。当初用 SAMBA的WINS解析
在客户端总是ping不通testing.chedong.com这个问题困扰了我好一阵。

WEB服务:APACHE + php + resin

主要用作文件的WEB共享和一些应用的前端浏览(CVSWEB GNATSWEB PHPMYADMIN等),Apache,这里仍然使用了1.3,因为很多应用,比如PHP在2.0上运行还不是完整。

安装: http://httpd.apache.org下载最新版本:

编译选项:这样可以让所有的模块都通过配置文件动态加载,方便后面其他应用模块的添加删除:
./configure --prefix=/home/apache --enable-shared=max --enable-module=most
更多安装说明可以参考: APACHE安装笔记

重复如下:
apache:
diff httpd.h httpd.h.orig
314c314
< #define HARD_SERVER_LIMIT 2560
---
> #define HARD_SERVER_LIMIT 256

./configure --prefix=/home/apache --enable-shared=max --enable-module=most

删除过多的注释:
grep -v "#" httpd.conf.default >httpd.conf

php + mysql

mysql: innodb效率和ORACLE差不多,一般应用用不上
./configure --prefix=/home/mysql --without-innodb 

./configure --with-apxs=/home/apache/bin/apxs --enable-track-vars \
--with-mysql=/home/mysql \
--with-oci8=/home/oracle/product/8.1.7 \
--with-oracle=/home/oracle/product/8.1.7
make
#make install

修改httpd.conf

DirectoryIndex index.html index.php index.php3

在中加入:
AddType application/x-httpd-php .php .php3

resin
./configure --with-apxs=/home/apache/bin/apxs
make
make install

修改httpd.conf

CauchoConfigFile /home/resin/conf/resin.conf

文档共享技巧:
1 对于文档的共享来说,autoindex模块非常有用,让APACHE自动索引目录缺省是按文件/目录名排序的,而且文件名40个字符以上部分是被截断的,为了能显示完整的文件名,并且像资源管理器那样将目录排在前面,文件排在后面:
在模块设置中:
#增加NameWidth选项,并且文件名长度是*(自动适应当前目录下最长文件名)
#增加FoldersFirst选项,让目录列在前面(类似于资源管理器)
#增加了ScanHTMLTitles用HTML文件的TITLE做文件的描述,并设置描述长度是*(自适应最长)
IndexOptions FancyIndexing +NameWidth=* FoldersFirst ScanHTMLTitles +DescriptionWidth=*

2 如果是CGI开发,如何让用户在自己的目录下能够发布CGI程序,比如:http://192.168.0.200/~chedong/cgi- bin/my_cgi:在
模块设置中,添加正则表达式:
ScriptAliasMatch ~([a-z]+)/cgi-bin/(.*) /home/$1/cgi-bin/$2
意思是匹配~user_name/cgi-bin/cgi_name自动映射到/home/user_name/cgi-bin/cgi-name脚本

3 如果允许所有目录可以自动索引浏览autoindex,需要将
<===改成

版本控制:CVS

CVS缺省在服务器上几乎都安装好了,只要按照以下步骤初始化即可:

在/etc/profile里:
CVS库所在的主服务器设置:
export CVSROOT=/home/cvsroot
在其他开发服务器里设置:
export CVSROOT=:ext:$USER@192.168.0.200:/home/cvsroot
export CVS_RSH=ssh

然后在主服务器上cvs init初始化:

关于CVSWEB的设置,重复以下CVS常用命令手册中CVSWEB的内容:

CVSWEB的下载:CVSWEB从最初的版本已经演化出很多功能界面更丰富的版本,这个是个人感觉安装设置比较方便的:
http://www.spaghetti-code.de/software/linux/cvsweb/

下载解包:
tar zxf cvsweb.tgz
把配置文件cvsweb.conf放到安全的地方(比如和apache的配置放在同一个目录下),
修改:cvsweb.cgi让CGI找到配置文件:
$config = $ENV{'CVSWEB_CONFIG'} || '/path/to/apache/conf/cvsweb.conf';

转到/path/to/apache/conf下并修改cvsweb.conf:

  1. 修改CVSROOT路径设置:
    %CVSROOT = (
    'Development' => '/path/to/cvsroot', #<==修改指向本地的CVSROOT
    );
  2. 缺省不显示已经删除的文档:
    "hideattic" => "1",#<==缺省不显示已经删除的文档
  3. 在配置文件cvsweb.conf中还可以定制页头的描述信息,你可以修改$long_intro成你需要的文字

首先可以CVS进库里的就是以上系统的安装文档。

更多的关于CVS的扩展应用可以参考CVS常用命令手册CVSTRAC部分

多个服务之间的资源共享

一般可以通过链接解决,比如:

我希望匿名ftp共享的内容(比如在/var/ftp/pub目录下)都可以WEB发布,
ln -s /var/ftp/pub /home/apache/htdocs/pub

我希望/usr/share/doc里的文档大家可以通过WEB浏览:
ln -s /usr/share/doc /home/apache/htdocs/doc

我希望WEB发布的内容大家通过WINDOWS网络邻居也可以访问:假设/home/share是samba发布的只读共享路径
ln -s /home/apache/htdocs /home/share

服务的自动启动:
系统已经安装的服务一般可以通过setup的服务配置是否自动启动,否则就在/etc/rc.local里加一些启动脚本即可。
比如:

备份和日志统计

可以将以下脚本写在主服务器的ROOT的CRON里:

#time sync
0 5 * * 1 (/usr/bin/rdate -s YOUR_DATE_TIME_SERVER)

#backup cvsroot
5 3 * * * (cd /home; tar czf /home/backup/cvsroot.`date +\%w`.tgz cvsroot)

#backup apache
8 3 * * * (cd /home; tar czf /home/backup/apache.`date +\%w`.tgz apache)

#webalizer demo
3 5 * * * (/usr/local/bin/webalizer -c /home/apache/conf/webalizer.conf /home/apache/logs/`date -d yesterday +\
%w`/access_log)

#remove last week web log
3 4 * * * (find /home/apache/logs/ -name access_log -mtime +4 -exec rm -f {} ;)

这样,在/home/backup目录下会有按星期轮训的7个备份。然后通过在辅助服务器上设置CRON用wget的-m选项镜像主服务器上的 /home/backup目录或者用rsync做同步就可以了。后面的2条是关于使用webalzier做服务器的日志统计,APACHE的日志通过 cronolog进行了轮循。具体设置请参考:
注意:
在CRONTAB中 %需要转义\%,比如:tar czf /home/backup/apache.`date +\%w`.tgz apache
而命令行中需要转义的\; 在crontab 中不需要转义,比如:...-mtime +4 -exec rm -f {} ;

基于RSYNC的同步备份:

主服务器:设置启动rsync服务
/etc/rsyncd.conf
hosts allow 192.168.0.*
[ftp]
path = /home/apache/htdocs
comment = docs need backup

备份服务器:每天6点同步一次数据
2 6 * * * (/usr/bin/rsync -au --delete rsync://192.168.0.200/ftp /home/apache/htdocs )

如何给用户设置缺省密码:
/home/apache/bin/htpasswd -bmn chedong 123
chedong:$apr1$5hoi./..$XlpyjZk6rw7R9D5QPo6V6/
-b don't prompt
-m md5
-n print to stout

TODO:

基于WIKI的文档共享:twiki

打印服务;

参考资料:

O'Reilly在线手册:Using Samba
http://www.oreilly.com/catalog/samba/chapter/book/index.html

- 作者: BluEmOoNz 2004年12月1日, 星期三 20:54  回复(0) |  引用(0) 加入博采

转载:Apache学习笔记

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
http://www.chedong.com/tech/apache_install.html

关键词: apache install php resin mod_gzip mod_expire webalizer cronolog

内容摘要:

Apache是一个历史悠久并且功能十分强大的WEB服务器,但其丰富的功能对于一个新手来说往往不知道从何下手。我个人感觉Apache的设计充分体现了模块化设计的优势,通过在动态模块加载(DSO)模式下的安装,任何子应用模块都可以通过配置文件的简单修改进行积木式的灵活配置。安装的过程可以从简单的静态html服务开始,一个模块一个模块的学习使用。从单纯的HTML静态服务(core),到复杂的动态页面服务(core + php, core + resin, core + php + mod_gzip, core + resin + mod_expire)。

本文主要从简化安装==>性能调优==>维护方便的角度,介绍了WEB服务的规划、HTTPD安装/应用模块配置、升级/维护等过程。让Apache和PHP,Resin等应用模块的独立升级,完全互不影响。

  1. WEB应用容量规划:根据硬件配置和WEB应用的特点进行WEB服务的规划及一些简单的估算公式;
  2. Apache安装过程:apache的通用的简化安装选项,方便以后的应用的模块化配置;
    修改 HARD_SERVER_LIMIT:
    vi /path/to/apache_src/src/include/httpd.h
    #define HARD_SERVER_LIMIT 2560 <===将原来的 HARD_SERVER_LIMIT 256 后面加个"0"
    apache编译:
    ./configure --prefix=/home/apache --enable-shared=max --enable-module=most
  3. 可选应用模块/工具的安装:php resin mod_gzip mod_expire及各个模块之间的配合;
    mod_php安装:./configure --with-apxs=/home/apache/bin/apxs --enable-track-vars --with-mysql
    mod_resin安装:./configure --with-apxs=/home/apache/bin/apxs
    mod_gzip安装:修改Makefile中的 apxs路径:然后make make install
    工具:日志轮循工具cronolog安装:http://www.cronolog.org
  4. 升级/维护:看看通用和模块化的安装过程如何简化了日常的升级/维护工作;
    按照以上的方法:系统管理员和应用管理员的职责可以清楚的分开,互相独立。
    系统安装:系统管理员的职责就是安装好一台DSO模式的Apache,然后COLON即可,
    应用安装:由应用管理员负责具体应用所需要的模块,比如PHP Resin等,并设置httpd.conf中相关的配置。
    系统升级:系统管理员:升级操作系统/升级Apache
    应用升级:应用管理员:升级应用模块,PHP Resin等。

WEB应用的容量规划

Apache主要是一个内存消耗型的服务应用,我个人总结的经验公式:
apache_max_process_with_good_perfermance < (total_hardware_memory / apache_memory_per_process ) * 2
apache_max_process = apache_max_process_with_good_perfermance * 1.5

为什么会有一个apache_max_process_with_good_perfermance和apache_max_process呢?原因是在低负载下系统可以使用更多的内存用于文件系统的缓存,从而进一步提高单个请求的响应速度。在高负载下,系统的单个请求响应速度会慢不少,而超过 apache_max_process,系统会因为开始使用硬盘做虚拟内存交换空间而导致系统效率急剧下降。此外,同样的服务:2G内存的机器的 apache_max_process一般只设置到1G内存的1.7倍,因为Apache本身会因为进程过多导致性能下降。

例子1:
一个apache + mod_php的服务器:一个apache进程一般需要4M内存
因此在一个1G内存的机器上:apache_max_process_with_good_perfermance < (1g / 4m) * 2 = 500
apache_max_process = 500 * 1.5 = 750
所以规划你的应用让服务尽量跑在500个进程以下以保持比较高的效率,并设置Apache的软上限在800个。

例子2:
一个apache + mod_resin的服务器: 一个apache进程一般需要2M内存
在一个2G内存的机器上:
apache_max_process_with_good_perfermance < (2g / 2m ) * 2 = 2000
apache_max_process = 2000 * 1.5 = 3000

以上估算都是按小文件服务估算的(一个请求一般大小在20k以下)。对于文件下载类型站点,可能还会受其他因素:比如带宽等的影响。

Apache安装过程

服务器个数的硬上限HARD_SERVER_LIMIT的修改:
在Apache的源代码中缺省的最大进程数是256个,需要修改apache_1.3.xx/src/include/httpd.h
#ifndef HARD_SERVER_LIMIT
#ifdef WIN32
#define HARD_SERVER_LIMIT 1024
#elif defined(NETWARE)
#define HARD_SERVER_LIMIT 2048
#else
#define HARD_SERVER_LIMIT 2560 <===将原来的HARD_SERVER_LIMIT 256 后面加个"0"
#endif
#endif

解释:
Apache缺省的最大用户数是256个:这个配置对于服务器内存还是256M左右的时代是一个非常好的缺省设置,但随着内存成本的急剧下降,现在大型站点的服务器内存配置一般比当时要高一个数量级不止。所以256个进程的硬限制对于一台1G内存的机器来说是太浪费了,而且Apache的软上限 max_client是受限于HARD_SERVER_LIMIT的,因此如果WEB服务器内存大于256M,都应该调高Apache的 HARD_SERVER_LIMIT。根据个人的经验:2560已经可以满足大部分小于2G内存的服务器的容量规划了(Apache的软上限的规划请看后面)。

Apache的编译:以下通用的编译选项能满足以后任意模块的安装
./configure --prefix=/another_driver/apache/ --enable-shared=max --enable-module=most
比如:
./configure --prefix=/home/apache/ --enable-shared=max --enable-module=most

解释:
--prefix=/another_driver/apache/:建议将apache服务安装在另外一个驱动设备上的目的在于硬盘往往是一个系统使用寿命最低的设备,因此:将服务数据和系统完全分开,不仅能提高了数据的访问速度,更重要的,大大方便系统升级,应用备份和恢复过程。

--shared-module=max:使用动态加载方式载入子模块会带来5%的性能下降,但和带来的配置方便相比更本不算什么:比如模块升级方便,系统升级风险降低,安装过程标准化等

--enable-module=most:用most可以将一些不常用的module编译进来,比如后面讲到的mod_expire是就不在 apache的缺省常用模块中

如果不想build so, 也可以这样:
./configure \
"--with-layout=Apache" \
"--prefix=/path/to/apache" \
"--disable-module=access" \
"--disable-module=actions" \
"--disable-module=autoindex" \
"--disable-module=env" \
"--disable-module=imap" \
"--disable-module=negotiation" \
"--disable-module=setenvif" \
"--disable-module=status" \
"--disable-module=userdir" \
"--disable-module=cgi" \
"--disable-module=include" \
"--disable-module=auth" \
"--disable-module=asis"

但结果会发现,这样编译对服务性能只能有微小的提高(5%左右),但却失去了以后系统升级和模块升级的灵活性,无论是模块还是Apache本身升级都必须把Apache和PHP的SOURCE加在一起重新编译。

apache的缺省配置文件一般比较大:可以使用去掉注释的方法精简一下:然后再进入具体的培植过程能让你更快的定制出你所需要的。
grep -v "#" httpd.conf.default >httpd.conf

需要修改的通用项目有以下几个:

#服务端口,缺省是8080,建议将整个Apache配置调整好后再将服务端口改到正式服务的端口
Port 8080 => 80

#服务器名:缺省没有
ServerName name.example.com

#最大服务进程数:根据服务容量预测设置
MaxClients 256 => 800

#缺省启动服务后的服务进程数:等服务比较平稳后,按平均负载下的httpd个数设置就可以
StartServers 5 => 200

不要修改:
以前有建议说修改:
MinSpareServers 5 => 100
MaxSpareServers 10 => 200

但从我的经验看来:缺省值已经是非常优化的了,而且让Apache自己调整子共享进程个数还是比较好的。

特别修改:
在solaris或一些比较容易出现内存泄露的应用上:
MaxRequestsPerChild 0 =>3000

应用模块和工具的安装配置:

由于使用模块动态加载的模式,所以可以方便的通过简单的配置调整来把Apache定制成你需要的:最好把不常用模块全部清除(无论处于安全还是效率)。
比如:对于静态页面服务器:就什么其他子模块都不加载,对于PHP应用就加上PHP模块,对于JAVA应用就把Resin模块加载上。而且各种模块的插拔非常简单,这样调试过程中就可以简单的通过注释掉不需要的模块,而不用重新编译。

一般说来,可以不需要的模块包括:
#LoadModule env_module libexec/mod_env.so
#LoadModule negotiation_module libexec/mod_negotiation.so
#LoadModule status_module libexec/mod_status.so
#server side include已经过时了
#LoadModule includes_module libexec/mod_include.so
#不需要将没有缺省index文件的目录下所有文件列出
#LoadModule autoindex_module libexec/mod_autoindex.so
#尽量不使用CGI:一直是Apache安全问题最多的地方
#LoadModule cgi_module libexec/mod_cgi.so
#LoadModule asis_module libexec/mod_asis.so
#LoadModule imap_module libexec/mod_imap.so
#LoadModule action_module libexec/mod_actions.so
#不使用安全认证可以大大提高访问速度
#LoadModule access_module libexec/mod_access.so
#LoadModule auth_module libexec/mod_auth.so
#LoadModule setenvif_module libexec/mod_setenvif.so

最好保留的有:
#用于定制log格式
LoadModule config_log_module libexec/mod_log_config.so
#用于增加文件应用的关联
LoadModule mime_module libexec/mod_mime.so
#用于缺省index文件:index.php等
LoadModule dir_module libexec/mod_dir.so

可用可不用的有:
#比如:需要在~/username/下调试php可以将
LoadModule userdir_module libexec/mod_userdir.so
#比如:需要将以前的URL进行转向或者需要使用CGI script-alias
LoadModule alias_module libexec/mod_alias.so

常用的模块:
最常用的可能就是php和JAVA应用服务器的前端,此外,从性能上讲利用mod_gzip可以减少40%左右的流量,减少机器用于传输的负载,而 mod_expires可以减少10%左右的重复请求,让重复的用户对指定的页面请求结果都CACHE在本地,根本不向服务器发出请求。

建议将所有MODULE的配置都放到相应模块的配置内部:<IfModule some_module.c>some_module config </IfModule>

PHP的安装:
/path/to/php_src/configure --with-apxs=/path/to/apache/bin/apxs --with-other-modules-you-need
需要修改的配置:
AddType application/x-httpd-php .php .php3 .any_file_in_php

resin的安装设置:
/path/to/resin/src/configure --with-apxs=/path/to/apache/bin/apxs

具体的resin设置放在另外一个文件中:比如/home/resin/conf/resin.conf
<IfModule mod_caucho.c>
CauchoConfigFile /path/to/apache/conf/resin.conf
</IfModule>

mod_expires的安装配置:
<IfModule mod_expires.c>
    ExpiresActive on
    ExpiresByType image/gif "access plus 1 month"
    ExpiresByType text/css "now plus 1 month"
    ExpiresDefault "now plus 1 day"
</IfModule>

注释:
所有的.gif文件1个月以后过期
所有的文件缺省1天以后过期

mod_gzip的安装
http://www.chedong.com/tech/compress.html

日志的轮循:cronolog的安装和设置

cronolog可以非常整齐的将日志按天轮循存储
缺省编译安装到/usr/local/bin/下,只需要将配置改成:

CustomLog "|/usr/local/sbin/cronolog /home/apache/logs/%w/access_log" combined

日志将按天截断并存放在以星期为目录名的目录下:比如:log/1是周一,log/5是周五, log/0是周日

用gzip压缩每天的日志:
30 4 * * * /usr/bin/gzip -f /home/apache/logs/`date -d yesterday +%w`/access_log

日志的定期删除:
30 5 * * */usr/bin/find /home/apache/logs/ -name access_log.gz -mtime +3 |xargs -r /bin/rm -f

升级维护

由于使用动态模块加载方式(DSO模式)安装Apache,Apache的HTTPD核心服务和应用模块以及应用模块之间都变的非常灵活,建议将所有独立模块的配置都放在
<IfModule mod_name>
CONFIGURATIONS..
</IfModule>
里,这样配置非常容易通过屏蔽某个模块来进行功能调整:比如:
#AddModule mod_gzip.c
就屏蔽了mod_gzip,而其他模块不首任何影响。

安装和维护过程:

  • 系统安装:系统管理员的职责就是安装系统和一个按照DSO模式安装的Apache,然后COLON。
  • 应用安装:由应用管理员负责具体应用所需要的模块并设置HTTPD。
  • 系统升级:系统管理员:升级系统/升级Apache
  • 应用升级:应用管理员:升级应用模块:PHP CAUCHO等
  • 系统备份/恢复:如果Apache不在缺省的系统盘上,只需要将Apache目录备份就可以了,遇到系统分区的硬件问题直接使用预先准备好的系统COLON,再直接将Apache所在物理盘恢复就行了。
系统管理员:Apache的最简化安装OS + Apache (httpd core only)
应用管理员:应用模块定制纯静态页面服务
core
PHP动态页面
core+so
+php
JAVA应用
core+so
+caucho
+ssl
应用例子:www.example.com
image.example.com
bbs.example.commall.example.com


例子:Apache和PHP模块的独立升级。

如果Apache是按照以下方式安装:
./configure --prefix=/home/apache --enable-shared=max --enable-module=most
PHP是按照以下方式安装:
./configure --with-apxs=/home/apache/bin/apxs --enable-track-vars --with-mysql

以后单独升级Apache的时候,仍然是:
./configure --prefix=/home/apache --enable-shared=max --enable-module=most
make
su
#/home/apache/bin/apachectl stop
#make install

单独升级php时,仍然是:
./configure --with-apxs=/home/apache/bin/apxs --enable-track-vars --with-mysql
make
su
#/home/apache/bin/apachectl stop
#make install
#/home/apache/bin/apachectl start

基于反相代理的WEB加速:
squid和mod_proxy都可以实现反相代理加速。而基于缓存的代理加速比起原有WEB服务,速度会有数量级的提升。

小提示:

Apache安装后,缺省根目录下没有但很有用的2个文件:

  • favicon.ico: favicon.ico是一个16x16的站点图标文件,如果浏览器发现有这个文件,在地址栏中会用这个图标替换调浏览器的网页图标。IE6和 MOZILLA等主流浏览器都支持这个功能。
    例如: http://www.chedong.com/favicon.ico
  • robots.txt: 用于告诉搜索引擎的爬虫程序(spider)网站那些页面可以被索引,那些不可以。
    具体说明请参考:http://www.robotstxt.org/wc/robots.html

参考文档:

Apache项目
http://httpd.apache.org

PHP
http://www.php.net

Resin
http://www.caucho.com

mod_gzip
http://sourceforge.net/projects/mod-gzip/

Cronolog
http://www.cronolog.org

mod_expires
http://httpd.apache.org/docs/mod/mod_expires.html

面向搜索引擎的CMS设计:
http://www.chedong.com/tech/cms.html


- 作者: BluEmOoNz 2004年12月1日, 星期三 20:52  回复(0) |  引用(0) 加入博采

转载:ANT安装、配置

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
http://www.chedong.com/tech/ant.html

关键词:ant build.xml javac

内容摘要:
ant是一个基于JAVA的自动化脚本引擎,脚本格式为XML。除了做JAVA编译相关任务外,ANT还可以通过插件实现很多应用的调用。

  1. ANT的基本概念:
  2. ANT的安装:解包,设置路径
  3. ANT的使用:最好的学习只不过是一个简单实用的例子起步......

ANT的基本概念:Java的Makefile

当一个代码项目大了以后,每次重新编译,打包,测试等都会变得非常复杂而且重复,因此c语言中有make脚本来帮助这些工作的批量完成。在Java 中应用是平台无关性的,当然不会用平台相关的make脚本来完成这些批处理任务了,ANT本身就是这样一个流程脚本引擎,用于自动化调用程序完成项目的编译,打包,测试等。除了基于JAVA是平台无关的外,脚本的格式是基于XML的,比make脚本来说还要好维护一些。

每个ant脚本(缺省叫build.xml)中设置了一系列任务(target):比如对于一个一般的项目可能需要有以下任务。

  • 任务1:usage 打印本脚本的帮助信息(缺省)
  • 任务2:clean <-- init 清空初始化环境
  • 任务3:javadoc <-- build <-- init 生成JAVADOC
  • 任务4:jar <-- build <-- init 生成JAR
  • 任务5:all <-- jar + javadoc <-- build <-- init 完成以上所有任务:jar javadoc
而多个任务之间往往又包含了一定了依赖关系:比如把整个应用打包任务(jar)的这个依赖于编译任务(build),而编译任务又依赖于整个环境初始化任务(init)等。

注:我看到很多项目的ant脚本中的命名基本上都是一致的,比如:编译一般叫build或者compile;打包一般叫jar或war;生成文档一般命名为javadoc或javadocs;执行全部任务all。在每个任务的中,ANT会根据配置调用一些外部应用并配以相应参数执行。虽然ANT可调用的外部应用种类非常丰富,但其实最常用的就2,3个:比如javac javadoc jar等。

ANT的安装

解包后在系统可执行路径中加入指向ant的bin的路径就可以了,比如可以在GNU/Linux上把以下配置加入/etc/profile中:
export ANT_HOME=/home/ant
export JAVA_HOME=/usr/java/j2sdk1.4.1
export PATH=$PATH:$JAVA_HOME/bin:$ANT_HOME/bin

这样执行ant 后,如果不指定配置文件ant会缺省找build.xml这个配置文件,并根据配置文件执行任务,缺省的任务设置可以指向最常用的任务,比如: build,或指向打印帮助信息:usage,告诉用户有那些脚本选项可以使用。

ANT的使用

最好的学习过程就是看懂那些open source项目中的build.xml脚本,然后根据自己的需要简化成一个更简单的,ANT和APACHE上很多非常工程派的项目:简单易用,而且适应性非常强,因为这些项目的建立往往来源于开发人员日常最直接的需求。
以下是的一个WebLucene应用的例子:修改自JDOM的build.xml:

<project default="usage" basedir=".">

  <!-- =================================================================== -->
  <!-- Initialization target                                               -->
  <!-- =================================================================== -->
  <target name="init">
    <tstamp/>
    <property file="${basedir}/build.properties" />
    <property name="Name" value="ProjectFullName"/>
    <property name="name" value="project_name"/>
    <property name="version" value="0.2"/>
    <property name="year" value="2003"/>

    <echo message="----------- ${Name} ${version} [${year}] ------------"/>

    <property name="debug" value="off"/>
    <property name="optimize" value="on"/>
    <property name="deprecation" value="on"/>

    <property name="src.dir" value="./src/WEB-INF/src"/>
    <property name="lib.dir" value="./src/WEB-INF/lib"/>
    <property name="packages" value="com.chedong.*,org.apache.lucene.*"/>

    <property name="build.src" value="./src/WEB-INF/build"/>
    <property name="build.dest" value="./src/WEB-INF/classes"/>
    <property name="build.javadocs" value="./src/doc"/>
   
    <path id="classpath">
        <pathelement path="${jsdk_jar}"/>
        <fileset dir="${lib.dir}">
           <include name="**/*.jar"/>
        </fileset>
    </path>
   
    <filter token="year" value="${year}"/>
    <filter token="version" value="${version}"/>
    <filter token="date" value="${TODAY}"/>
    <filter token="log" value="true"/>
    <filter token="verbose" value="true"/>
  </target>

  <!-- =================================================================== -->
  <!-- Help on usage                                                       -->
  <!-- =================================================================== -->
  <target name="usage" depends="init">
    <echo message="${Name} Build file"/>
    <echo message="-------------------------------------------------------------"/>
    <echo message=""/>
    <echo message=" available targets are:"/>
    <echo message=""/>
    <echo message="   jar      --> generates the ${name}.jar file"/>
    <echo message="   build    --> compiles the source code"/>
    <echo message="   javadoc  --> generates the API documentation"/>
    <echo message="   clean    --> cleans up the directory"/>
    <echo message=""/>
    <echo message=" Please rename build.properties.default to build.properties"/>
    <echo message=" and edit build.properties to specify JSDK 2.3 classpath."/>
    <echo message=""/>
    <echo message=" See the comments inside the build.xml file for more details."/>
    <echo message="-------------------------------------------------------------"/>
    <echo message=""/>
    <echo message=""/>
  </target>

  <!-- =================================================================== -->
  <!-- Prepares the source code                                            -->
  <!-- =================================================================== -->
  <target name="prepare-src" depends="init">
    <!-- create directories -->
    <mkdir dir="${build.src}"/>
    <mkdir dir="${build.dest}"/>
   
    <!-- copy src files -->
    <copy todir="${build.src}">
      <fileset dir="${src.dir}"/>
    </copy>
  </target>

  <!-- =================================================================== -->
  <!-- Compiles the source directory                                       -->
  <!-- =================================================================== -->
  <target name="build" depends="prepare-src">
    <javac srcdir="${build.src}"
           destdir="${build.dest}"
           debug="${debug}"
           optimize="${optimize}">
      <classpath refid="classpath"/>
    </javac>
  </target>

  <!-- =================================================================== -->
  <!-- Creates the class package                                           -->
  <!-- =================================================================== -->
  <target name="jar" depends="build">
    <jar jarfile="${lib.dir}/${name}.jar"
         basedir="${build.dest}"
         includes="**"/>
  </target>

  <!-- =================================================================== -->
  <!-- Creates the API documentation                                       -->
  <!-- =================================================================== -->
  <target name="javadoc" depends="build">
    <mkdir dir="${build.javadocs}"/>
    <javadoc packagenames="${packages}"
             sourcepath="${build.src}"
             destdir="${build.javadocs}"
             author="true"
             version="true"
             use="true"
             splitindex="true"
             windowtitle="${Name} API"
             doctitle="${Name}">
      <classpath refid="classpath"/>
    </javadoc>
  </target>

  <!-- =================================================================== -->
  <!-- Clean targets                                                       -->
  <!-- =================================================================== -->
  <target name="clean" depends="init">
    <delete dir="${build.src}"/>
    <delete dir="${build.dest}/org"/>
    <delete dir="${build.dest}/com"/>
    <delete>
      <fileset dir="${build.dest}" includes="**/*.class"/>
    </delete>
  </target>
</project>
<!-- End of file -->

缺省任务:usage 打印帮助文档,告诉有那些任务选项:可用的有build, jar, javadoc和clean.

初始化环境变量:init
所有任务都基于一些基本环境变量的设置初始化完成,是后续其他任务的基础,在环境初始化过程中,有2点比较可以方便设置:

1 除了使用却缺省的property设置了JAVA源路径和输出路径外,引用了一个外部的build.properties文件中的设置,
<property file="${basedir}/build.properties" />
这样大部分简单配置用户只要会看懂build.properties就可以了,毕竟XML比起key value的属性文件还是要可读性差一些。用build.properties也可以方便其他用户从编译的细节中解放出来。

2 CLASSPATH设置:使用了其中的:
    <path id="classpath">
        <pathelement path="${jsdk_jar}"/>
        <fileset dir="${lib.dir}">
           <include name="**/*.jar"/>
        </fileset>
    </path>
则相当于设置了:CLASSPATH=/path/to/resin/lib/jsdk23.jar; /path/to/project/lib/*.jar;

文件复制:prepare-src
创建临时SRC存放目录和输出目录。
  <!-- =================================================================== -->
  <!-- Prepares the source code                                            -->
  <!-- =================================================================== -->
  <target name="prepare-src" depends="init">
    <!-- create directories -->
    <mkdir dir="${build.src}"/>
    <mkdir dir="${build.dest}"/>
   
    <!-- copy src files -->
    <copy todir="${build.src}">
      <fileset dir="${src.dir}"/>
    </copy>
  </target>

编译任务:build
编译时的CLASSPATH环境通过一下方式找到引用一个path对象
<classpath refid="classpath"/>

打包任务:jar
对应用打包生成项目所写名的.jar文件
  <!-- =================================================================== -->
  <!-- Creates the class package                                           -->
  <!-- =================================================================== -->
  <target name="jar" depends="build">
    <jar jarfile="${lib.dir}/${name}.jar"
         basedir="${build.dest}"
         includes="**"/>
  </target>

生成JAVADOC文档任务: javadoc
  <!-- =================================================================== -->
  <!-- Creates the API documentation                                       -->
  <!-- =================================================================== -->
  <target name="javadoc" depends="build">
    <mkdir dir="${build.javadocs}"/>
    <javadoc packagenames="${packages}"
             sourcepath="${build.src}"
             destdir="${build.javadocs}"
             author="true"
             version="true"
             use="true"
             splitindex="true"
             windowtitle="${Name} API"
             doctitle="${Name}">
      <classpath refid="classpath"/>
    </javadoc>
  </target>

清空临时编译文件:clean
  <!-- =================================================================== -->
  <!-- Clean targets                                                       -->
  <!-- =================================================================== -->
  <target name="clean" depends="init">
    <delete dir="${build.src}"/>
    <delete dir="${build.dest}/org"/>
    <delete dir="${build.dest}/com"/>
    <delete>
      <fileset dir="${build.dest}" includes="**/*.class"/>
    </delete>
  </target>

TODO:
更多任务/扩展:(样例)
  • 测试任务:JUnit测试
  • 代码风格检查任务:CheckStyle,Jalopy等
  • 邮件警报任务:可以把以上这些任务的输出警告发送到制定的用户列表中,这个任务可以设置每天自动运行。

参考资料:

Jakarta ANT:
http://ant.apache.org


- 作者: BluEmOoNz 2004年12月1日, 星期三 20:51  回复(0) |  引用(0) 加入博采

转载:CVS使用手册

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
http://www.chedong.com/tech/cvs_card.html

关键词:CVS CVSWeb CVSTrac WinCVS CVSROOT

内容摘要:

CVS是一个C/S系统,多个开发人员通过一个中心版本控制系统来记录文件版本,从而达到保证文件同步的目的。工作模式如下:

       CVS服务器(文件版本库)
/ | \
(版 本 同 步)
/ | \
开发者1 开发者2 开发者3

作为一般开发人员挑选2,6看就可以了,CVS的管理员则更需要懂的更多一些,最后还简单介绍了一些Windows下的cvs客户端使用,CVS远程用户认证的选择及与BUG跟踪系统等开发环境的集成问题。

  1. CVS环境初始化:CVS环境的搭建 管理员
  2. CVS的日常使用:日常开发中最常用的CVS命令, 开发人员 管理员
  3. CVS的分支开发:项目按照不同进度和目标并发进行 管理员
  4. CVS的用户认证:通过SSH的远程用户认证,安全,简单 管理员
  5. CVSWEB:CVS的WEB访问界面大大提高代码版本比较的效率 管理员
  6. CVS TAG:将$Id$ 加入代码注释中,方便开发过程的跟踪开发人员
  7. CVS vs VSS: CVS和Virsual SourceSafe的比较 开发人员 管理员
  8. WinCVS: 通过SSH认证的WinCVS认证设置
  9. 基于CVSTrac的小组开发环境搭建:通过CVSTrac实现web界面的CVS用户管理,集成的BUG跟踪和WIKI交流
  10. CVS中的用户权限管理:基于系统用户的CVS权限管理和基于CVSROOT/passwd的虚拟用户管理

一个系统20%的功能往往能够满足80%的需求,CVS也不例外,以下是CVS最常用的功能,可能还不到它全部命令选项的20%,作为一般开发人员平时会用cvs update和cvs commit就够了,更多的需求在实际应用过程中自然会出现,不时回头看看相关文档经常有意外的收获。


CVS环境初始化

环境设置:指定CVS库的路径CVSROOT

tcsh
setenv CVSROOT /path/to/cvsroot
bash
CVSROOT=/path/to/cvsroot ; export CVSROOT

后面还提到远程CVS服务器的设置:
CVSROOT=:ext:$USER@test.server.address#port:/path/to/cvsroot CVS_RSH=ssh; export CVSROOT CVS_RSH

初始化:CVS版本库的初始化。
cvs init

一个项目的首次导入
cvs import -m "write some comments here" project_name vendor_tag release_tag
执行后:会将所有源文件及目录导入到/path/to/cvsroot/project_name目录下
vender_tag: 开发商标记
release_tag: 版本发布标记

项目导出:将代码从CVS库里导出
cvs checkout project_name
cvs 将创建project_name目录,并将最新版本的源代码导出到相应目录中。这个checkout和Virvual SourceSafe中的check out不是一个概念,相对于Virvual SourceSafe的check out是cvs update, check in是cvs commit。

CVS的日常使用

 

注意:第一次导出以后,就不是通过cvs checkout来同步文件了,而是要进入刚才cvs checkout project_name导出的project_name目录下进行具体文件的版本同步(添加,修改,删除)操作。

将文件同步到最新的版本
cvs update
不制定文件名,cvs将同步所有子目录下的文件,也可以制定某个文件名/目录进行同步
cvs update file_name
最好每天开始工作前或将自己的工作导入到CVS库里前都要做一次,并养成"先同步 后修改"的习惯,和Virvual SourceSafe不同,CVS里没有文件锁定的概念,所有的冲突是在commit之前解决,如果你修改过程中,有其他人修改并commit到了CVS 库中,CVS会通知你文件冲突,并自动将冲突部分用
>>>>>>
content on cvs server
<<<<<<
content in your file
>>>>>>
标记出来,由你确认冲突内容的取舍。
版本冲突一般是在多个人修改一个文件造成的,但这种项目管理上的问题不应该指望由CVS来解决。

确认修改写入到CVS库里
cvs commit -m "write some comments here" file_name

注意:CVS的很多动作都是通过cvs commit进行最后确认并修改的,最好每次只修改一个文件。在确认的前,还需要用户填写修改注释,以帮助其他开发人员了解修改的原因。如果不用写-m "comments"而直接确认`cvs commit file_name` 的话,cvs会自动调用系统缺省的文字编辑器(一般是vi)要求你写入注释。
注释的质量很重要:所以不仅必须要写,而且必须写一些比较有意义的内容:以方便其他开发人员能够很好的理解
不好的注释,很难让其他的开发人员快速的理解:比如: -m "bug fixed" 甚至 -m ""
好的注释,甚至可以用中文: -m "在用户注册过程中加入了Email地址校验"


修改某个版本注释:每次只确认一个文件到CVS库里是一个很好的习惯,但难免有时候忘了指定文件名,把多个文件以同样注释commit到CVS库里了,以下命令可以允许你修改某个文件某个版本的注释:
cvs admin -m 1.3:"write some comments here" file_name

添加文件
创建好新文件后,比如:touch new_file
cvs add new_file
注意:对于图片,Word文档等非纯文本的项目,需要使用cvs add -kb选项按2进制文件方式导入(k表示扩展选项,b表示binary),否则有可能出现文件被破坏的情况
比如:
cvs add -kb new_file.gif
cvs add -kb readme.doc

如果关键词替换属性在首次导入时设置错了怎么办?
cvs admin -kkv new_file.css

然后确认修改并注释
cvs ci -m "write some comments here"

删除文件
将某个源文件物理删除后,比如:rm file_name
cvs rm file_name
然后确认修改并注释
cvs ci -m "write some comments here"
以上面前2步合并的方法为:
cvs rm -f file_name
cvs ci -m "why delete file"
注意:很多cvs命令都有缩写形式:commit=>ci; update=>up; checkout=>co/get; remove=>rm;

添加目录
cvs add dir_name

查看修改历史
cvs log file_name
cvs history file_name

查看当前文件不同版本的区别
cvs diff -r1.3 -r1.5 file_name
查看当前文件(可能已经修改了)和库中相应文件的区别
cvs diff file_name
cvs的web界面提供了更方便的定位文件修改和比较版本区别的方法,具体安装设置请看后面的cvsweb使用

正确的通过CVS恢复旧版本的方法
如果用cvs update -r1.2 file.name
这个命令是给file.name加一个STICK TAG: "1.2" ,虽然你的本意只是想将它恢复到1.2版本
正确的恢复版本的方法是:cvs update -p -r1.2 file_name >file_name
如果不小心已经加成STICK TAG的话:用cvs update -A 解决

移动文件/文件重命名
cvs里没有cvs move或cvs rename,因为这两个操作是可以由先cvs remove old_file_name,然后cvs add new_file_name实现的。

删除/移动目录
最方便的方法是让管理员直接移动,删除CVSROOT里相应目录(因为CVS一个项目下的子目录都是独立的,移动到$CVSROOT目录下都可以作为新的独立项目:好比一颗树,其实砍下任意一枝都能独立存活),对目录进行了修改后,要求其开发人员重新导出项目cvs checkout project_name 或者用cvs update -dP同步。

项目发布导出不带CVS目录的源文件
做开发的时候你可能注意到了,每个开发目录下,CVS都创建了一个CVS/目录。里面有文件用于记录当前目录和CVS库之间的对应信息。但项目发布的时候你一般不希望把文件目录还带着含有CVS信息的CVS目录吧,这个一次性的导出过程使用cvs export命令,不过export只能针对一个TAG或者日期导出,比如:
cvs export -r release1 project_name
cvs export -D 20021023 project_name
cvs export -D now project_name

CVS Branch:项目多分支同步开发

确认版本里程碑:多个文件各自版本号不一样,项目到一定阶段,可以给所有文件统一指定一个阶段里程碑版本号,方便以后按照这个阶段里程碑版本号导出项目,同时也是项目的多个分支开发的基础。

cvs tag release_1_0

开始一个新的里程碑
cvs commit -r 2 标记所有文件开始进入2.x的开发

注意:CVS里的revsion和软件包的发布版本可以没有直接的关系。但所有文件使用和发布版本一致的版本号比较有助于维护。

版本分支的建立
在开发项目的2.x版本的时候发现1.x有问题,但2.x又不敢用,则从先前标记的里程碑:release_1_0导出一个分支 release_1_0_patch
cvs rtag -b -r release_1_0 release_1_0_patch proj_dir

一些人先在另外一个目录下导出release_1_0_patch这个分支:解决1.0中的紧急问题,
cvs checkout -r release_1_0_patch
而其他人员仍旧在项目的主干分支2.x上开发

在release_1_0_patch上修正错误后,标记一个1.0的错误修正版本号
cvs tag release_1_0_patch_1

如果2.0认为这些错误修改在2.0里也需要,也可以在2.0的开发目录下合并release_1_0_patch_1中的修改到当前代码中:
cvs update -j release_1_0_patch_1

CVS的远程认证通过SSH远程访问CVS

使用cvs本身基于pserver的远程认证很麻烦,需要定义服务器和用户组,用户名,设置密码等,

常见的登陆格式如下:
cvs -d :pserver:cvs_user_name@cvs.server.address:/path/to/cvsroot login
例子:
cvs -d :pserver:cvs@samba.org:/cvsroot login

不是很安全,因此一般是作为匿名只读CVS访问的方式。从安全考虑,通过系统本地帐号认证并通过SSH传输是比较好的办法,通过在客户机的 /etc/profile里设置一下内容:
CVSROOT=:ext:$USER@cvs.server.address#port:/path/to/cvsroot CVS_RSH=ssh; export CVSROOT CVS_RSH
所有客户机所有本地用户都可以映射到CVS服务器相应同名帐号了。

比如:

CVS服务器是192.168.0.3,上面CVSROOT路径是/home/cvsroot,另外一台开发客户机是192.168.0.4,如果 tom在2台机器上都有同名的帐号,那么从192.168.0.4上设置了:
export CVSROOT=:ext:tom@192.168.0.3:/home/cvsroot
export CVS_RSH=ssh
tom就可以直接在192.168.0.4上对192.168.0.3的cvsroot进行访问了(如果有权限的话)
cvs checkout project_name
cd project_name
cvs update
...
cvs commit

如果CVS所在服务器的SSH端口不在缺省的22,或者和客户端与CVS服务器端SSH缺省端口不一致,有时候设置了:
:ext:$USER@test.server.address#port:/path/to/cvsroot

仍然不行,比如有以下错误信息:
ssh: test.server.address#port: Name or service not known
cvs [checkout aborted]: end of file from server (consult above messages if any)

解决的方法是做一个脚本指定端口转向(不能使用alias,会出找不到文件错误):
创建一个/usr/bin/ssh_cvs文件,假设远程服务器的SSH端口是非缺省端口:34567
#!/bin/sh
/usr/bin/ssh -p 34567 "$@"
然后:chmod +x /usr/bin/ssh_cvs
并CVS_RSH=ssh_cvs; export CVS_RSH

注意:port是指相应服务器SSH的端口,不是指cvs专用的pserver的端口

CVSWEB:提高文件浏览效率

CVSWEB就是CVS的WEB界面,可以大大提高程序员定位修改的效率:

使用的样例可以看:http://www.freebsd.org/cgi/cvsweb.cgi

CVSWEB的下载:CVSWEB从最初的版本已经演化出很多功能界面更丰富的版本,这个是我个人感觉安装设置比较方便的:
原先在:http://www.spaghetti-code.de/software/linux/cvsweb/,但目前已经删除,目前仍可以在本站下载CVSWEB,其实最近2年FreeBSD的CVSWeb项目已经有了更好的发展吧,而当初没有用FreeBSD那个版本主要就是因为没有彩色的文件Diff功能。
下载解包:
tar zxf cvsweb.tgz
把配置文件cvsweb.conf放到安全的地方(比如和apache的配置放在同一个目录下),
修改:cvsweb.cgi让CGI找到配置文件:
$config = $ENV{'CVSWEB_CONFIG'} || '/path/to/apache/conf/cvsweb.conf';

转到/path/to/apache/conf下并修改cvsweb.conf:

  1. 修改CVSROOT路径设置:
    %CVSROOT = (
    'Development' => '/path/to/cvsroot', #<==修改指向本地的CVSROOT
    );
  2. 缺省不显示已经删除的文档:
    "hideattic" => "1",#<==缺省不显示已经删除的文档
  3. 在配置文件cvsweb.conf中还可以定制页头的描述信息,你可以修改$long_intro成你需要的文字

CVSWEB可不能随便开放给所有用户,因此需要使用WEB用户认证:
先生成 passwd:
/path/to/apache/bin/htpasswd -c cvsweb.passwd user

修改httpd.conf: 增加
<Directory "/path/to/apache/cgi-bin/cvsweb/">
AuthName "CVS Authorization"
AuthType Basic
AuthUserFile /path/to/cvsweb.passwd
require valid-user
</Directory>

CVS TAGS: $Id: cvs_card.html,v 1.5 2003/03/09 08:41:46 chedong Exp $

将$Id: cvs_card.html,v 1.9 2003/11/09 07:57:11 chedong Exp $ 加在程序文件开头的注释里是一个很好的习惯,cvs能够自动解释更新其中的内容成:file_name version time user_name 的格式,比如:cvs_card.txt,v 1.1 2002/04/05 04:24:12 chedong Exp,可以这些信息了解文件的最后修改人和修改时间


几个常用的缺省文件:
default.php
<?php
/*
* Copyright (c) 2002 Company Name.
* $Header: /home/cvsroot/tech/cvs_card.html,v 1.9 2003/11/09 07:57:11 chedong Exp $
*/

?>
====================================
Default.java: 注意文件头一般注释用 /* 开始 JAVADOC注释用 /** 开始的区别
/*
* Copyright (c) 2002 MyCompany Name.
* $Header: /home/cvsroot/tech/cvs_card.html,v 1.9 2003/11/09 07:57:11 chedong Exp $
*/

package com.mycompany;

import java.;

/**
* comments here
*/
public class Default {
/**
* Comments here
* @param
* @return
*/
public toString() {

}
}
====================================
default.pl:
#!/usr/bin/perl -w
# Copyright (c) 2002 Company Name.
# $Header: /home/cvsroot/tech/cvs_card.html,v 1.9 2003/11/09 07:57:11 chedong Exp $

# file comments here

use strict;

CVS vs VSS

CVS没有文件锁定模式,VSS在check out同时,同时记录了文件被导出者锁定。

CVS的update和commit, VSS是get_lastest_version和check in

对应VSS的check out/undo check out的CVS里是edit和unedit

在CVS中,标记自动更新功能缺省是打开的,这样也带来一个潜在的问题,就是不用-kb方式添加binary文件的话在cvs自动更新时可能会导致文件失效。

$Header: /home/cvsroot/tech/cvs_card.html,v 1.5 2003/03/09 08:41:46 chedong Exp $ $Date: 2003/11/09 07:57:11 $这样的标记在Virsual SourceSafe中称之为Keyword Explaination,缺省是关闭的,需要通过OPITION打开,并指定需要进行源文件关键词扫描的文件类型:*.txt,*.java, *.html...

对于Virsual SourceSafe和CVS都通用的TAG有:
$Header: /home/cvsroot/tech/cvs_card.html,v 1.5 2003/03/09 08:41:46 chedong Exp $
$Author: chedong $
$Date: 2003/11/09 07:57:11 $
$Revision: 1.9 $

我建议尽量使用通用的关键词保证代码在CVS和VSS都能方便的跟踪。

WinCVS

下载:

cvs Windows客户端:目前稳定版本为1.2
http://cvsgui.sourceforge.net
ssh Windows客户端
http://www.networksimplicity.com/openssh/

安装好以上2个软件以后:
WinCVS客户端的admin==>preference设置
1 在general选单里
设置CVSROOT: username@192.168.0.123:/home/cvsroot
设置Authorization: 选择SSH server

2 Port选单里
钩上:check for alternate rsh name
并设置ssh.exe的路径,缺省是装在 C:\Program Files\NetworkSimplicity\ssh\ssh.exe

然后就可以使用WinCVS进行cvs操作了,所有操作都会跳出命令行窗口要求你输入服务器端的认证密码。

当然,如果你觉得这样很烦的话,还有一个办法就是生成一个没有密码的公钥/私钥对,并设置CVS使用基于公钥/私钥的SSH认证(在general 选单里)。

可以选择的diff工具:examdiff
下载:
http://www.prestosoft.com/examdiff/examdiff.htm
还是在WinCVS菜单admin==>preference的WinCVS选单里
选上:Externel diff program
并设置diff工具的路径,比如:C:\Program Files\ed16i\ExamDiff.exe
在对文件进行版本diff时,第一次需要将窗口右下角的use externel diff选上。

基于CVSTrac的小组开发环境搭建

作为一个小组级的开发环境,版本控制系统和BUG跟踪系统等都涉及到用户认证部分。如何方便的将这些系统集成起来是一个非常困难的事情,毕竟我们不能指望 Linux下有像Source Offsite那样集成度很高的版本控制/BUG跟踪集成系统。

我个人是很反对使用pserver模式的远程用户认证的,但如果大部分组员使用WINDOWS客户端进行开发的话,总体来说使用 CVSROOT/passwd认证还是很难避免的,但CVS本身用户的管理比较麻烦。本来我打算自己用perl写一个管理界面的,直到我发现了 CVSTrac:一个基于WEB界面的BUG跟踪系统,它外挂在CVS系统上的BUG跟踪系统,其中就包括了WEB界面的CVSROOT/passwd文件的管理,甚至还集成了WIKIWIKI讨论组功能。

这里首先说一下CVS的pserver模式下的用户认证,CVS的用户认证服务是基于inetd中的:
cvspserver stream tcp nowait apache /usr/bin/cvs cvs --allow-root=/home/cvsroot pserver
一般在2401端口(这个端口号很好记:49的平方)

CVS用户数据库是基于CVSROOT/passwd文件,文件格式:
[username]:[crypt_password]:[mapping_system_user]
由于密码都用的是UNIX标准的CRYPT加密,这个passwd文件的格式基本上是apache的htpasswd格式的扩展(比APACHE的 PASSWD文件多一个系统用户映射字段),所以这个文件最简单的方法可以用
apache/bin/htpasswd -b myname mypassword
创建。注意:通过htpasswd创建出来的文件会没有映射系统用户的字段
例如:
new:geBvosup/zKl2
setup:aISQuNAAoY3qw
test:hwEpz/BX.rEDU

映射系统用户的目的在于:你可以创建一个专门的CVS服务帐号,比如用apache的运行用户apache,并将/home/cvsroot目录下的所有权限赋予这个用户,然后在passwd文件里创建不同的开发用户帐号,但开发用户帐号最后的文件读写权限都映射为apache用户,在SSH模式下多个系统开发用户需要在同一个组中才可以相互读写CVS库中的文件。

进一步的,你可以将用户分别映射到apache这个系统用户上。
new:geBvosup/zKl2:apache
setup:aISQuNAAoY3qw:apache
test:hwEpz/BX.rEDU:apache

CVSTrac很好的解决了CVSROOT/passwd的管理问题,而且包含了BUG跟踪报告系统和集成WIKIWIKI交流功能等,使用的 CGI方式的安装,并且基于GNU Public License

在inetd里加入cvspserver服务:
cvspserver stream tcp nowait apache /usr/bin/cvs cvs --allow-root=/home/cvsroot pserver

xietd的配置文件:%cat cvspserver
service cvspserver
{
disable = no
socket_type = stream
wait = no
user = apache
server = /usr/bin/cvs
server_args = -f --allow-root=/home/cvsroot pserver
log_on_failure += USERID
}

注意:这里的用户设置成apache目的是和/home/cvsroot的所有用户一致,并且必须让这个这个用户对/home/cvsroot/下的 CVSROOT/passwd和cvstrac初始化生成的myproj.db有读取权限。

 

安装过程

  1. 下载:可以从http://www.cvstrac.org 下载
    我用的是已经在Linux上编译好的应用程序包:cvstrac-1.1.2.bin.gz,
    %gzip -d cvstrac-1.1.2.bin.gz
    %chmod +x cvstrac-1.1.2.bin
    #mv cvstarc-1.1.1.bin /usr/bin/cvstrac
    如果是从源代码编译:
    从 http://www.sqlite.org/download.html 下载SQLITE的rpm包:
    rpm -i sqlite-devel-2.8.6-1.i386.rpm
    从 ftp://ftp.cvstrac.org/cvstrac/ 下载软件包
    解包,假设解包到/home/chedong/cvstrac-1.1.2下,并规划将cvstrac安装到/usr/local/bin目录下, cd /home/chedong/cvstrac-1.1.2 编辑linux-gcc.mk:
    修改:
    SRCDIR = /home/chedong/cvstrac-1.1.2
    INSTALLDIR = /usr/local/bin
    然后
    mv linux-gcc.mk Makefile
    make
    #make install

  2. 初始化cvstrac数据库:假设数据库名是 myproj
    在已经装好的CVS服务器上(CVS库这时候应该已经是初始化好了,比如:cvs init初始化在/home/cvsroot里),运行一下
    %cvstrac init /home/cvsroot myproj
    运行后,/home/cvsroot里会有一个的myproj.db库,使用CVSTRAC服务,/home/cvsroot/myproj.db /home/cvsroot/CVSROOT/readers /home/cvsroot/CVSROOT/writers /home/cvsroot/CVSROOT/passwd这几个文件对于web服务的运行用户应该是可写的,在RedHat8上,缺省就有一个叫 apache用户和一个apache组,所以在httpd.conf文件中设置了用apache用户运行web服务:
    User apache
    Group apache,
    然后设置属于apache用户和apache组
    #chown -R apache:apache /home/cvsroot
    -rw-r--r-- 1 apache apache 55296 Jan 5 19:40 myproj.db
    drwxrwxr-x 3 apache apache 4096 Oct 24 13:04 CVSROOT/
    drwxrwxr-x 2 apache apache 4096 Aug 30 19:47 some_proj/
    此外还在/home/cvsroot/CVSROOT中设置了:
    chmod 664 readers writers passwd
  3. 在apche/cgi-bin目录中创建脚本cvstrac:
    #!/bin/sh
    /usr/bin/cvstrac cgi /home/cvsroot
    设置脚本可执行:
    chmod +x /home/apache/cgi-bin/cvstrac
  4. 从 http://cvs.server.address/cgi-bin/cvstrac/myproj 进入管理界面
    缺省登录名:setup 密码 setup
    对于一般用户可以从:
    http://cvs.server.address/cgi-bin/cvstrac/myproj
  5. 在setup中重新设置了CVSROOT的路径后,/home/cvsroot
    如果是初次使用需要在/home/cvsroot/CVSROOT下创建passwd, readers, writers文件
    touch passwd readers writers
    然后设置属于apache用户,
    chown apache.apache passwd readers writers
    这样使用setup用户创建新用户后会同步更新CVSROOT/passwd下的帐号

修改登录密码,进行BUG报告等,
更多使用细节可以在使用中慢慢了解。

对于前面提到的WinCVS在perference里设置:
CVSROOT栏输入:username@ip.address.of.cvs:/home/cvsroot
Authenitication选择:use passwd file on server side
就可以了从服务器上进行CVS操作了。

CVS的用户权限管理

CVS的权限管理分2种策略:

  • 基于系统文件权限的系统用户管理:适合多个在Linux上使用系统帐号的开发人员进行开发。
  • 基于CVSROOT/passwd的虚拟用户管理:适合多个在Windows平台上的开发人员将帐号映射成系统帐号使用。
为什么使用apache/apache用户?首先RedHat8中缺省就有了,而且使用这个用户可以方便通过cvstrac进行WEB管理。
chown -R apache.apache /home/cvsroot
chmod 775 /home/cvsroot

Linux上通过ssh连接CVS服务器的多个开发人员:通过都属于apache组实现文件的共享读写
开发人员有开发服务器上的系统帐号:sysuser1 sysuser2,设置让他们都属于apache组,因为通过cvs新导入的项目都是对组开放的:664权限的,这样无论那个系统用户导入的项目文件,只要文件的组宿主是apache,所有其他同组系统开发用户就都可以读写;基于ssh远程认证的也是一样。

   apache(system group)
/            |           \
sysuser1   sysuser2     sysuser3

Windows上通过cvspserver连接CVS服务器的多个开发人员:通过在passwd文件种映射成 apache用户实现文件的共享读写
他们的帐号通过CVSROOT/passwd和readers writers这几个文件管理;通过cvstrac设置所有虚拟用户都映射到apache用户上即可。

   apache(system user)
/            |            \
windev1     windev2      windev3             

 

 

利用cvs + (WinCVS/cvsweb/cvstrac),构成了一个相对完善的跨平台工作组开发版本控制环境。

相关资源:

CVS HOME:
http://www.cvshome.org

CVS FAQ:
http://www.loria.fr/~molli/cvs-index.html

相关网站:
http://directory.google.com/Top/Computers/Software/Configuration_Management/Tools/Concurrent_Versions_System/

CVS--并行版本系统
http://www.soforge.com/cvsdoc/zh_CN/book1.html

CVS 免费书:
http://cvsbook.red-bean.com/

CVS 命令的速查卡片:
http://www.refcards.com/about/cvs.html

WinCVS:
http://cvsgui.sourceforge.net/

CVSTrac: A Web-Based Bug And Patch-Set Tracking System For CVS
http://www.cvstrac.org

StatCVS:基于CVS的代码统计工具:按代码量,按开发者的统计表等
http://sourceforge.net/projects/statcvs

如何在WEB开发中规划CVS上:在Google上查 "cvs web development"
http://ccm.redhat.com/bboard-archive/cvs_for_web_development/index.html

一些集成了CVS的IDE环境:
Eclipse
Magic C++


- 作者: BluEmOoNz 2004年12月1日, 星期三 20:48  回复(0) |  引用(0) 加入博采