批处理文件(Batch File)里使用当前时间

一直使用批处理文件备份文件,以前使用RAR压缩的时候,可以使用-ag参数,以当前日期与时间生成压缩文件名,但换用7z以后,没有这个功能,每次备份完之后都要手工修改文件名,很不方便。现在从http://blog.joycode.com/mvm/archive/2005/05/10/50624.aspx找到了在批处理文件中根据当前时间生成一个变量,然后截取它的一个子字符串的方法,然后就可以在命令中使用这个变量了。

批处理中可以用%date%调用当前时间,但%date:~0,4%则可以生成当前时间(转换成字符串以后)从第0位起取4个字符的子字符串,第一位从0计。其中0、4位置的数字还可以是负值,应该是代表了从字符串末尾、向前取字符。现在我的批处理中可以使用如下命令了:

7za a backup.%date:~0,4%%date:~5,2%%date:~8,2%.7z -r * -ms=off -mmt=on

这样就能每天生成一个名如backup.20050630.7z的文件了。

有人还说,利用下面的命令也可以取出当前时间,试了一下,是可以echo出来,但如何加以利用就不知道了。

for /f "tokens=1,2,3 delims=- " %a in (‘date /t’) do @echo "%a-%b-%c"

上面这个命令中,date /t必须用单引号包含,双引号不行。

不知道这样取substring的方法对其它变量是否适用。

cvs2svn转换Repository时,中文更新记录乱码的问题

使用使用cvs2svn转换Repository的时候,发现转换过来的更新记录中,所有的中文都是乱码,不是显示方块,就是问号,原来是没有加上–encoding参数的缘故,原来使用的命令如下:

c:/python23/python h:/cvs2svn-1.2.1/cvs2svn -s h:/svn/repo h:/cvsroot/repo

–encoding参数的含义是“所采用的编码,默认为ascii”,但我加上这个参数“–encoding=gb2312”之后,转换却出了问题,提示

LookupError: unknown encoding: gb2312

原来cvs2svn在转换的时候使用 的是Python的字符集,而Python 2.3好像不支持gb2312字符集,因此更新到Python 2.4.1并使用如下命令进行转换

c:/python24/python h:/cvs2svn-1.2.1/cvs2svn –encoding=gb2312 -s h:/svn/repo h:/cvsroot/repo

就一切正常了,转换很顺利,更新记录中的中文也没有乱码。

这里有Python 2.4支持的所有字符集列表。

subversion起步

SVN服务器也建好了,Tortoisesvn客户端也安装好了,下面就可以开始使用SVN了。通过cvs2svn转过来的Repository可以直接用,但如果要新建一个Repository,导入现有的项目,就要稍微麻烦一些了,甚至有些绕,大致步骤如下:

  1. 在服务端的SVN parent目录下,建立一个空的repository,可以使用svnadmin create –fs-type fsfs MyNewRepository命令,也可以使用Tortoisesvn的TortoiseSVN->Create Repository Here …命令。
  2. 在客户端建立一个repo目录,并且在下面建三个空目录,分别是branches、tags、trunk,其中branches用来保存分支,tags用来保存标签(?不知道这个叫法是否正确),trunk用来保存当前工作状态的文件。这个目录结构也可以采用其它方式建立,详细的说明在TortoiseSVN的帮助的“5.2. Importing Data Into A Repository ”中有更详细的解释。
  3. 使用TortoiseSVN客户端工具,把repo目录Import(导入)到服务端,服务端地址为domain.com/svnparentpath/MyNewRepository。这样我们就建立了这个Repository的目录层次。Revision编号为0。
  4. 删除repo目录下的三个空目录,把要导入的项目文件拷贝到这个目录下,当然也可以直接使用其它的目录。
  5. 使用TortoiseSVN客户端工具,把repo目录下的内容(已有项目文件)Import(导入)到服务端,和上次导入不同的是,上次是建立目录结构,而这次是导入项目文件,因此服务端地址为domain.com/svnparentpath/MyNewRepository/trunk,注意最后多了个trunk,也就是说现在导入的内容是作为工作状态的文件存在的,以后才可以根据需要在这个基础上建立tags或branches。
  6. checkout服务端的domain.com/svnparentpath/MyNewRepository/trunk到某个目录,我们就可以开始工作了。

在这里有一个比较绕圈的概念,那就是SVN的branches和tags是用“copy”的方式建立的,给用户的感觉就是拷贝了一个副本,所以我们分别建立了三个目录来保存他们,而日常的工作都在trunk下进行。而在CVS中,branches和tags都是附加在现有文件之上的,你的文件只“保存”一份,至少感觉上是这样的。

subversion和module_rewrite的小冲突?

我的Apache上同时挂有SVN和rewrite module,SVN配置都没有问题,通过HTTP访问正常,但通过Toroisesvn客户端访问总是不行,错误信息如下:

Error: PROPFIND request failed on ‘/svn/svntest’
Error: PROPFIND of ‘/svn/svntest’: 302 Found (http://www.domain.com)

经查,如果我去掉Apache的httpd.conf中的这两句,就可以正常使用了:

RewriteRule (.+)\/(\w+[^\/])$ $1/$2/ [R]
RewriteRule \/(\w+[^\/])$ /$1/ [R]

这两句RewriteRule是为了添加URL地址末尾的斜杠的,看来这两句对SVN的调用起了影响,原因大概是访问SVN的地址,比如是“/svn/svntest”时,RewriteRule会将其改写为“/svn/svntest/”,多了一个斜杠,然后SVN就不知所综了。

原来Apache 2.0的mod-dir已经有了自动添加斜杠的功能:

A "trailing slash" redirect is issued when the server receives a request for a URL http://servername/foo/dirname where dirname is a directory. Directories require a trailing slash, so mod_dir issues a redirect to http://servername/foo/dirname/.

不用劳烦RewriteRule了。

话又说回来,不管是mod_dir也好,RewriteRule也好,使用反向代理(ProxyPass)的时候还是有些问题,比如说,domain1.com/d2地址贝配置为转向到domain2.com,那么访问地址domain1.com/d2/subdir时,如果subdir时确实存在的,而输入地址的时候最后又没有输入斜杠/,那么你将会得到一个404错误页面,并且地址栏显示的是domain1.com/subdir,这个问题遇到很久了,一直不知道如何解决。通过端口进行反向代理好像同样存在这样的问题。

所以,使用反向代理时,一是老老实实的加上斜杠,二就是最好尽量采用如下的反向代理方式:domain1.com/subdir1定向到domain2.com/subdir2,并且subdir1和subdir2同名,这样就不会出现上面说到的问题了。

Subversion的Repository列表完美解决方案

我的SVN项目都放在h:/svn下,在Apache中只是把这个目录设置成了虚拟目录,这样我可以方便的通过http://localhost/svn/project1访问这个目录下的所有Repository,但如果我想访问http://localhost/svn/,是得不到所有Repository列表的,只是一个403 Forbidden错误,在TortorseSVN的帮助中有这么一篇文章中提到了解决的方法,下面是我的具体实施和一点心得。

SVN在Apache中的配置段一般都用<Location>,我尝试过使用<Directory>,好像也可以,但不管用那个,在配置中无法使用AllowOverride指令,也就是说.htaccess文件无法使用。因此,若想把http://localhost/svn/转向到调用其它文件,只能使用Rewrite module,并且必须写在<Location>段之外。我就是在这里试了N久 :(。

(Apache一般配置和PHP、Rewrite module安装略过)

为了方便管理,用于显示Repository列表的PHP文件放在了h:/svn/svntools/目录,也就是在SVN的根目录下 :-)。因此,Apache中的这段配置如下:

Alias /svntools "h:/svn/svntools"
RewriteEngine on
RewriteRule ^/svn/$ /svntools/svn_index.php [PT]
<Location /svn>
DAV svn
SVNParentPath h:/svn
</Location>

先用Alias定义到h:/svn/svntools的虚拟目录,这样就可以访问到svn_index.php文件了,然后打开RewriteEngine,使用RewriteRule将到/svn/的访问重定向到/svntools/svn_index.php文件,通过执行这个文件就会产生Repository列表了;最后是SVN虚拟目录的配置。

Subversion初体验

Subversion是新一代的版本控制系统,其设计目的是为了替代CVS,并且同样是免费的协议,贡献给开源社区。

The goal of the Subversion project is to build a version control system that is a compelling replacement for CVS in the open source community. The software is released under an Apache/BSD-style open source license.

现在正在使用CVS,计划转移到Subversion下,因此要先试一试。和它配套的客户端软件不再是Wincvs了,而是TortoiseSVN,从官方网站的域名看,似乎是一家人。

目前的最新版本是Subversion 1.2.0,TortoiseSVN 1.2.0.3602,我的安装平台是WinXP sp2。

安装前需要安装Apache和Python,这些我好像都有了:-)。

安装Subversion

这里下载了Win下ZIP版的文件,直接解压到h盘。解压就OK了?没几个文件啊,看了看安装说明,应该是这样,说明中还讲了如何更新svn:

svn co http://svn.collab.net/repos/svn/trunk svn

这个命令会将最新的svn源文件下载到svn目录中。试着更新了一次,下来很多文件,我的水平是看不懂了,只知道里面有Python、C、Html文件什么的。

创建Subversion服务器

建立Repository目录

md h:/svn

创建Repository

svnadmin create h:/svn/Fwolf

接下来就可以导入、导出项目了

svn import h:/temp/project file:///h:/svn/Fwolf -m "项目初始化"

svn checkout file:///h:/svn/Fwolf h:/project

这个是针对h:/temp/project目录下的所有项目(一个目录一个项目)的导入、导出,而我则想从CVS导入项目。

导入CVS服务器的内容

这里下载cvs2svn,这是一个Python编写的工具,用于把CVS的Repository转换成SVN的Repository,但并非是在两者之间进行同步。目前的版本是1.2.1。

cvs2svn有多种转换方式,在这里我选择全盘转换。其它的使用方式还有诸如不转换TAG和BRANCH、不要LOG等等。

cvs2svn需要RCS `co`或者CVS才能正常工作,谁知道这两个是什么东西,看起来好像和CVS采用的文档格式解析有关系,我选用了RCS,它也有Windows下的Bin包(里面的一个rcslib.dll文件也要解压,co.exe需要这个文件)。还需要GNU sort,刚开始我不知道,结果在pass 3就出现了错误:

—– pass 3 —–
Sorting CVS revisions…
输入文件指定了两次。

Command failed: "sort -T . ./cvs2svn-data.c-revs > ./cvs2svn-data.s-revs"

GNU sort的Win32二进制版本可以在http://unxutils.sourceforge.net/找到。sort.exe只有38k,但为了下载它却需要下载3M多的UnxUtils.zip。

执行以下命令进行Repository的转换:

c:/python23/python h:/cvs2svn-1.2.1/cvs2svn –existing-svnrepos -s h:/svn/Fwolf h:/cvsroot/Fwolf

需要注意的是,在原CVS的Repository中不能有中文的文件名,否则转换会出错。–encoding=ENC参数是解决这个问题的,但不知道怎么用,也不知道是否支持中文。经过一段时间的等待,转换终于成功完成了:

cvs2svn Statistics:
——————
Total CVS Files: 650
Total CVS Revisions: 2343
Total Unique Tags: 11
Total Unique Branches: 3
CVS Repos Size in KB: 445396
Total SVN Commits: 794
First Revision Date: Wed Apr 02 16:14:39 2003
Last Revision Date: Mon Jun 13 22:27:01 2005
——————
Timings:
——————
pass 1: 3 seconds
pass 2: 0 seconds
pass 3: 0 seconds
pass 4: 0 seconds
pass 5: 2 seconds
pass 6: 0 seconds
pass 7: 0 seconds
pass 8: 192 seconds
total: 199 seconds

接下来,要把SVN配置到Apache中

拷贝mod_dav_svn.so、mod_authz_svn.so、libdb43.dll、libeay32.dll、intl3_svn.dll、ssleay32.dll到Apache的modules目录,在httpd.conf中增加:

LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so

然后重启Apache,注意前两句涉及的模块是Apache的自带模块。我在这里的时候一开始总是Apache重启出错,提示

The Apache service named reported the following error:
>>> Cannot load H:/server/Apache2/modules/mod_dav_svn.so into server: 找不到指定的程序。

The Apache service named reported the following error:
>>> Cannot load H:/server/Apache2/modules/mod_dav_svn.so into server: xd5xd2xb2xbbxb5xbdxd6xb8xb6xa8xb5xc4xb3xccxd0xf2xa1xa3

在这么炎热的夏天,我鼓捣了一下午才发现问题之所在,第一个错误信息是Apache 2.0.48的,第二个错误信息是Apache 2.0.52的,这两个版本的mod_dav.so可能有些问题,更新到2.0.54就可以了,当然那几个DLL文件也要复制的。如果还提示缺少 libhttpd.dll,这个文件在Apache的bin目录下,自己找就可以了。相信很多人和我一样卡在这里:-(。

(后来又想,是否还有另外一种可能导致Apache出错,那就是前两个版本我都是直接复制的文件,而最后那个是使用MSI进行安装的,是否由于这个原因导致mod_dav出了问题呢?)

在Apache中添加虚拟目录的映射

在httpd.conf中增加:

<Location /svn/project1>
DAV svn
SVNPath h:/svn/project1
</Location>

其中project1是一个Repository的目录名,这样就可以使用网址http://localhost/svn/project1/来访 问SVN文件了。还有一种方式是直接将SVN的根目录定义为Apache的虚拟目录,这样它下面的每个Repository都可以通过类似上面的URL来 访问了,不用一个一个的重复定义,类似:

<Location /svn>
DAV svn
SVNParentPath h:/svn
</Location>

这样我同样可以使用http://localhost/svn/project1/来访问Repository。(但这样的话,http://localhost/svn/无法访问,403 Forbidden错误,不知如何解决。)

“DAV svn”不能变,它是用来说明“说明Apache会使用svn这个module来解析这个虚拟目录”,其余的可以根据具体情况调整。

这篇就到这里吧,关于SVN的使用、虚拟目录的权限设定网上都有很多文章了。

另外一点就是,由于在Repository中每个Revision都会形成一个文件,所以我担心Revision多了之后,存取文件的效率会降低,因此,我认为采用每个项目在单独的一个Repository中存储的方式会更好些。

(pLog无法输入反斜杠,因此在DOS命令中我只能输入/来代替)