Zeal Blog - 泽欧里
  WWW Zeal Blog
梦想 就像鸡蛋
要么孵化 要么臭掉
+ 0 - 0 | §SQL Server数据库复制

很少摸 Windows 环境下的东西,最近被个 MS SQL Server 的数据库搞得头大。实在不像 MySQL 那样用起来轻车熟路, OrZ ...

本来以为企业管理器里面既然提供了 DTS 数据导入/导出 的功能,直接使用 DTS 指定源和目标库就可以完全复制数据库到远程服务器上了。结果发现除了表的基本结构和数据,字段约束、键值、默认值等都没过去。最终还是要靠直接磁盘拷贝数据文件了事。

如果数据库服务可以停下来的话,最快的方法是直接拷贝对应的 .mdf 和 .ldf 文件(在企业管理器选择数据库右键看属性的“数据文件”项确定文件名);然后执行T-SQL命令(比如新的目标数据库名为 test ):

-- 如果 test 数据库已经存在,需要先把其分离。
-- 如果已经有应用连接到该数据库的话,就需要使用企业管理器
-- "所有任务"中的"分离数据库"功能强制断开现有连接后再分离
EXEC sp_detach_db
      @dbname = 'test',
      @skipchecks = 'true'

-- 把拷贝出来的 .mdf 文件和 .ldf 文件作为 test 数据库的数据文件挂上去
EXEC sp_attach_db
      @dbname = 'test',
      @filename1 = 'e:\db\test.mdf',
      @filename2 = 'e:\db\test.ldf'

-- 如果不想使用原来的 .ldf 文件,也可以单独挂 .mdf 文件
EXEC sp_attach_single_file_db
      @dbname = 'test',
      @physname = 'e:\db\test.mdf'

如果当前数据库处于生产环境不允许关闭服务的话,可以使用 BACKUP / RESTORE 的方法来完成复制工作:

-- 把数据库名为realdb的数据库备份到指定的磁盘文件
BACKUP DATABASE realdb TO DISK = 'E:\db\BAK_FOR_realdb.bak'
-- 用 RESTORE FILELISTONLY 命令查看数据库备份文件里面的
-- 数据文件和日志文件的逻辑名称,用于下一步的命令
RESTORE FILELISTONLY FROM DISK = 'E:\db\BAK_FOR_realdb.bak'

-- 使用备份文件创建一个新的数据库, realdb_dat 和 realdb_log
-- 分别是上面使用 RESTORE FILELISTONLY 命令查出的数据文件逻辑
-- 名称
RESTORE DATABASE test
    FROM DISK = 'E:\db\BAK_FOR_realdb.bak'
    WITH MOVE 'realdb_dat' TO 'E:\db\test.mdf',
    MOVE 'realdb_log' TO 'E:\db\test.ldf'
GO

标签 ( Tags ) : ,

+ 0 - 0 | §rsync时自动创建目录

一直以来都习惯用 rsync + ssh 作服务器文件同步,但之前都没有在命令参数里面找到类似 mkdir -p 的功能,可以在同步某个指定文件的时候自动在目标服务器上根据需要创建完整的父级目录。比如某些按年月日自动生成的目录型文件需要在文件生成的时候即时同步:

rsync -lprztW --rsh="/usr/bin/ssh -l rsyncuser" /var/2007/12/13/1001.gif 10.0.0.1:/var/2007/12/13/1001.gif

如果/var/2007/12/13目录没有预先在目标服务器上创建的话,该同步操作将报错:rsync: push_dir#3 "/var/2007/12/13" failed: No such file or directory (2)

之前的解决方法是在目标服务器上预先先创建所有可能产生的新目录结构,或者在源服务器上创建新目录的时候即时把目录rsync到目标服务器上。

偶然看到其实 rsync 有个 -R 参数(-R, --relative  use relative path names),用来把相对目录下的整个目录结构同步到目标服务器指定目录下。利用这个参数就可以自动达到 mkdir -p 的效果,只需要把同步命令改成:

cd /var
rsync -lprRztW --rsh="/usr/bin/ssh -l rsyncuser" 2007/12/13/1001.gif 10.0.0.1:/var/

标签 ( Tags ) : ,

+ 0 - 0 | §SVN错误“Cannot replace ...”

打算从 svn 服务器上 export 出来一个单独的文件(https方式),结果发现若干台 CentOS server 中有一台无法正常导出,提示错误:

svn: REPORT request failed on '/!svn/vcc/default'
svn:
Cannot replace a directory from within

从 apache 的 error_log 看,有两条错误信息:

[error] A failure occurred while driving the update report editor 
[error] [ Cannot replace a directory from within 

奇怪的是所有的服务器配置应该都是一样的,之前 export 整个工程目录的时候也没发生过任何错误。这次单单有一台死活拉不下来那单个文件。从 Google 上能搜到的原因说是可能指定了一个不存在的目标文件或者需要用svn switch 命令重新定位一次工作副本的位置;但显然这两种都不是我碰到的状况。

抱着死马当活马医的想法查看了一下几台服务器的 svn 版本,居然发现除了这台问题机器装的是 1.1.4 之外,其他都是 1.4.4 的版本!同样都是用 yum install subversion 安装的东西竟然出现这等怪事,郁闷ing。更想不同的是把那台服务器的 yum repo 配置改到一致重新装,抓下来的版本还是老掉牙的 1.1.4 。没办法只好用最原始的方法把 1.4.4 装上,再执行 svn export ,一切OK!

标签 ( Tags ) : ,

+ 0 - 0 | §Apache编译libexpat.so错误

编译Apache时出错:fixed: /usr/lib/libexpat.so: could not read symbols: File in wrong format

解决方法:编译时增加编译参数 --with-expat=builtin 。貌似在64位服务器下编译脚本在定位系统 expat 支持时有些问题。使用自带的expat来编译就不存在这个问题了。

标签 ( Tags ) : ,

+ 1 - 0 | §scp拷贝文件失败问题

当在 shell startup script (比如 profile , bashrc)自动执行过程中产生了任何内容输出时, scp / sftp 会把这些 echo 回来的东西认作协议包进行解析,结果自然是无法读懂这些内容,最终导致文件拷贝失败。

如果能够明确知道在自己的 /etc/bashrc 等文件里面哪些语句会产生 echo 的内容的话,可以通过条件判断进行 echo :

if [ $(expr index "$-" i) -ne 0 ]; then
    echo "welcome to interactive shell , Current is"
    date +'%Y-%m-%d %T'
fi

这样只有在真正交互登录的时候才会 echo 信息, scp 的时候自动忽略。

标签 ( Tags ) : ,,

+ 0 - 0 | §ERROR 2013 (HY000) of MySQL

当通过 TCP/IP 连接 MySQL 远程主机时,出现 ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 104

如果是在linux shell命令行中直接打 mysql 命令,能够顺利连上 MySQL,执行查询语句也比较正常,但如果执行 STOP SLAVE; 命令时就随机出现 ERROR 2013 (HY000): Lost connection to MySQL server during query 问题。而如果把操作命令写到脚本文件再去执行该脚本文件的话,则必然出现 Lost connection to MySQL server at 'reading initial communication packet', system error: 111

要是无论通过什么途径远程访问都出现错误可以认为是系统有防火墙之类的限制,但现在这种奇怪的抽筋现象让人百思不得其解。最后找到的解决方法是在 my.cnf 里面的 [mysqld] 段增加一个启动参数

skip-name-resolve

问题消失。但原因还是想不出所以然。

标签 ( Tags ) : ,

+ 0 - 0 | §svn post-commit中文转码

svn hooks 目录下缺省的 post-commit 脚本模板通过调用 commit-email.pl 来分析当次提交的内容并根据参数设置把修改信息 email 给项目相关人员。脚本支持使用 -m 参数进行正则过滤,当修改不同目录的内容时可以分别 email 给不同的邮件地址。

不过当项目中存在中文文件名的时候,由于 svn 会把非ascii码字符转义成形如 ?\325 的格式,所以在发出来的 email 里面这些中文都变成了不可读的数字。

要把这些编码转回原来的字符,只需要在 commit-email.pl 脚本处理 email body 信息的地方加上一段转码处理即可。比如在 my @difflines; (行487) 的前面加上:

for (my $i=0; $i<@body; ++$i){
    my @rsa = split( /\?\\/, $body[$i] );
    $body[$i] = "";
    foreach my $val (@rsa) {
        $val =~ /(^[0-9]{3})(.*)/;
        if(defined $1 and $1 gt 0){
            #print "\n[".$1 . "," . $2."]";
            $body[$i] .= chr($1) . $2;
        }
        else{
            $body[$i] .= $val;
        }
    }
}

把之前 push 到 @body 变量的所有内容重新进行处理,发现 ?\ 后面跟三个数字就替换为相应的字符。

另外在 post-commit 模板脚本中没有写 commit-email.pl 的绝对路径,需要写上才能正常被调用。

标签 ( Tags ) : ,,

+ 1 - 0 | §svn pre-commit hook 的加载

SVN 服务如果是配合 apache 通过 http/https 提供的话,可以通过配置AuthzSVNAccessFile文件来控制每一个项目目录的访问权限;但如果是通过内置的 svnserve 提供服务的话,就必须自己编写权限控制脚本作为 pre-commit hook 挂到版本库下面才能做到针对子目录和文件的访问权限控制。另一个最常在 pre-commit hook 中实现的功能是检查提交信息是否为空,可以养成自己每次提交都写说明信息的好习惯。

pre-commit hook 的脚本可以是 shell, perl, python, exe 等多种格式,相应的功能实现在网上也能很容易搜到。比如一个简单的防止提交说明信息为空的 shell 脚本

#!/bin/sh
REPOS="$1"
TXN="$2"
RES="OK"

# Make sure that the log message contains some text.
SVNLOOK=svnlook

$SVNLOOK log -t "$TXN" "$REPOS" \
| egrep  "[^[:space:]]+" >/dev/null  || unset RES
if [ "$RES" != "OK" ] ; then
 echo "You must input some comments for you commit" 1>&2
 exit 1
fi
# All checks passed, so allow the commit.
exit 0

把写好的脚本文件放置到相应的版本库目录下的 hooks 文件夹中即可(在 hooks 目录下也已经有各种 hook 脚本的模板供参考)。

需要注意的两点

  1. echo 错误提示信息的时候必须重定向到 stderr ,即 1>&2
  2. pre-commit 文件拷贝到 hooks 目录之后,需要 chmod 0755 pre-commit ,给 pre-commit 文件增加可执行权限(或者至少把文件owner改为 svn 服务运行用户并加上ownerx权限)

没做这两步的话,当你在客户端提交空信息的时候,相应的错误提示信息并不会被输出反馈到客户端上。

标签 ( Tags ) : ,,,

+ 0 - 0 | §SSL自签署证书生成脚本
启用 apache 的 mod_ssl 之后需要有证书才能正常运作。写了个脚本来操作。首先要确定机器上已经有 openssl 。  查看全文

标签 ( Tags ) : ,,,,,

+ 0 - 0 | §Avoid Unwanted Copies 问题

  OracleAS Web Cache 里面可以设置 Global URL Parameters to Ignore 来让 webcache 把多个带不同参数的 URL 作为同一个对象来缓存。比如说当利用 Dynamic Javascript 来进行跨域的数据调用的时候,对于 Firefox 来说不存在浏览器缓存过时数据的问题,但对于 IE 来说就会在多次动态加载某个 js URL 的时候总是缓存老的数据内容。

  这时候如果服务端提供 js 数据输出的 URL 是纯动态页面的话,可以设置 header 来强制客户端不缓存数据;如果是纯静态页面的话,可以在 URL 后面添加一个随机的字符串(比如 sURL+'?'+((new Date()).getTime()) ,不过对于这样的静态内容来说浏览器做本地缓存也很应该)。

  但如果你提供服务的是经过 Web Cache 做了 Cache 的内容,只有在内容发生变化的时候才通知 Oracle Web Cache 清除当前缓存,这时候想让 IE 浏览器即时抓到变化的内容就有点麻烦了。如果在 URL 后面增加一个随机的字符串参数的话, IE 固然不会错误的进行缓存,但 Web Cache 内存中就保留了无数个不同的 URL 对象,而实际上这些对象都是相同的东西。

  好在 Web Cache 控制台可以通过设置 Global URL Parameters to Ignore 来 Avoid unwanted copies ,让 Web Cache 在遇到 URL 中特定的 query 参数时进行忽略,以便把这些URL过滤成相同的一个。

  挺好用的一个功能,但似乎应用了这个过滤规则以后似乎无法即时清除指定的 URL cache 了。到后台查看 web cache 里面的对象,原来这个过滤规则的处理方法是把指定的参数的值用 @ 符号代替(比如 myservice.php?a=1&sid=45&rnd=4837281828 , 如果把 rnd 设置为 Global URL Parameters to Ignore 的话,过滤之后的 URL 就变成 myservice.php?a=1&rnd=@&sid=45),并且会对所有的参数按字母重新排序( sid 参数被放到了 rnd 参数的后面)。因此如果按照假定的 URL 来写清除规则( myservice.php\?a=1&sid=.* )的话就无法正确定位 cache 对象,需要把清除规则的参数也进行相应的调整才行。

标签 ( Tags ) : ,,

+ 1 - 0 | §删除超大目录下所有文件

Linux 系统中当单个目录中文件数过多时,试图用 rm * 来删除所有文件会报错 /bin/rm: Argument list too long.

据说这是因为 Linux 内核中所有 exec 系函数(execl, execlp, execle 等)最终调用的都是 execve() , 而 execve 是通过一块 128k 的内存空间来保存用以传递给新进程的命令参数和环境变量。当像 rm 这些命令产生的命令行参数超过 128k 的时候, Linux kernel 就报 E2BIG 错误了。

解决方法是用 find 命令先找出希望删除的文件名再用管道批次传递给 rm 去删除。比如要删除 sendmail 堆积起来的 mqueue 目录下的文件:

find /var/spool/mqueue/ -type f -name '*' -print0 | xargs -0 rm

(-0 参数防止文件名中有空格导致被 rm 认作是两个不同的文件。)

标签 ( Tags ) : ,,

+ 0 - 0 | §Google Gears让你离线冲浪

Google 刚推出一款 Firefox 1.5+ / Internet Explorer 6.0+ 开源浏览器插件  Google Gears ( Google Gears API Blog ) ,以帮助开发人员通过 JavaScript API 创建具有离线浏览功能的web应用。现在 Google Reader 主界面上已经出现了新增加的 Offline 功能链接。

在万维网的静态页面时代,各种离线浏览器曾经风行一时。发展到现在站点的互动性越来越高,单纯通过整站抓取根本就达不到离线浏览的目地了。 Google 这次又玩起老树开新花的招数,最终目标是离线/在线的无缝结合,比起 Adobe Apollo 所构想的纯桌面应用框架来显得圆滑得多,应该也更容易被目前的 web 开发人员所接受吧。

标签 ( Tags ) : ,,,

+ 0 - 0 | §10大已死(将死)的电脑技能

Computerworld的一篇文章列出了计算机领域已经消亡或正走向消亡的10种技术。对于里面提及的几种计算机语言,想必每个人心中都有一个TOP10,就像 Computerworld 读者的质疑声一样。从 TIOBE 五月份的编程语言排名来看,这几种语言的热度确实不高。但适用领域的多寡自然会造成流行程度的不同,会不会消亡谁说得准? Ruby 要不是搭了 Rails 的快车,也不见得有多少人知道。

1. Cobol
    虽然写起来挺折磨人的,但还是存在于不少健壮性要求高的系统里面。想必会在以后的系统升级中逐渐被其他实现方式所替代。

2. Nonrelational DBMS
    大学里面学的课程就已经是RDBMS了,非关系型的数据库管理系统只是在教材的第一章浮光掠影介绍了一下。

3. Non-IP networks

4. cc:Mail

5. ColdFusion
    在我看来属于比较小众的语言类型,但小众和消亡应该不能划等号。就像金属朋克,再小众也自有一片天空。

6. C programming
    这个好像有点不可思议。据我所知还是有大把的程序员在写C代码 -- 尤其是彪悍的程序员们。。

7. PowerBuilder
    毕业后第一份工作就是在PowerBuilder里面画数据窗口,现在似乎确实没什么人在谈这个东西了。谁让 Sybase 转型了呢。

8. Certified NetWare Engineers

9. PC network administrators

10.OS/2
    传说中的操作系统,从来没接触过。

标签 ( Tags ) : ,

+ 0 - 0 | §我习惯加在.bash_profile的10个alias
echo "1. myos 查看本机操作系统、内核信息"
alias myos="cat /proc/version && cat /etc/redhat-release && cat /etc/issue"
echo "2. myip 查看本机ip地址信息"
alias myip="/sbin/ifconfig | grep -a 'inet addr' | sed -e '/127\\.0\\.0\\.1/d;s/.*inet addr:\\([0-9\\.]\\+\\).*/\\1/'"
echo "3. myps 查看系统中运行的进程完整命令行信息"
alias myps="ps -A -eo pid,ppid,args --width=2048"
echo "4. mydate 按照格式显示当前日期及时间戳"
alias mydate="date +'%Y-%m-%d %H:%M:%S , tp=%s'"
echo "5. myls 列出当前目录内容,按时间排序"
alias myls="ls -althr"
echo "6. mybf 查找当前目录下大于100M的文件"
alias mybf="find . -size +102400k -printf '%kk\t%p\n'"
echo "7. mynf 查找当前目录下最近5分钟内修改过的文件"
alias mynf="find . -mmin -5 -printf '%TY-%Tm-%Td %TH:%TM:%TS\t%p\n'"
echo "8. mydf 查看磁盘空间和inode使用情况"
alias mydf="df -h && df -ih"
echo "9. mymd 快速创建多层目录"
alias mymd="mkdir -p"
echo "10.rmsvn 删除当前目录下所有的 .svn 目录"
alias rmsvn="find . -type d -name '.svn' -exec rm -rf {} \\; 2>/dev/null"

标签 ( Tags ) : ,,

+ 0 - 0 | §获得Shell脚本所在目录的绝对路径

要得到正在执行的程序/脚本自身所存放的绝对路径,在 PHP 里面可以用 dirname(realpath(__FILE__)) ; C# 则有 System.Windows.Forms.Application.StartupPath ; java 似乎没有什么比较直接的方法,只能利用 CodeSource 来间接获取 。而在 linux shell 脚本里面如果想得到当前脚本文件存放的绝对路径,也没有太现成的命令可以调用,不过可以通过下面的语句来获取:

baseDirForScriptSelf=$(cd "$(dirname "$0")"; pwd)
echo "full path to currently executed script is : ${baseDirForScriptSelf}"

虽说大部分情况下我们并不需要这样的绝对路径来完成工作;但如果要把多个脚本、数据文件等内容打包作为一个整体来交付别人使用,又希望不论用户拷贝到哪个目录下执行脚本都能够正确的找到这个包里面的其他内容的话,用这样的脚本来自动定位包的根目录应该是个比较鲁棒的做法。

标签 ( Tags ) : ,

+ 1 - 0 | §UNIX Timestamp in C#
C# 中的 DateTime 值类型表示值范围在公元(基督纪元)0001 年 1 月 1 日午夜 12:00:00 到公元 (C.E.) 9999 年 12 月 31 日晚上 11:59:59 之间的日期和时间;而 Unix 的时间戳则表示的是自从 Unix 纪元(格林威治时间 1970 年 1 月 1 日 00:00:00)到当前时间的秒数。 C# 中似乎并没有内置的方法来完成两者之间的转换。  查看全文

标签 ( Tags ) : ,,

+ 0 - 0 | §在C#中解析JavaScript代码
大部分的解释型脚本语言都提供 eval 方法来完成动态代码的解释执行, C# 却并不提供(向 Java 学习)。不过在 .NET Framework 类库里面提供的 Microsoft.JScript 命名空间倒是包含了支持使用JScript 语言编译和生成代码的类。  查看全文

标签 ( Tags ) : ,,

+ 0 - 0 | §No space left on device的原因

  看到这个错误,第一个反应是磁盘空间满了;但 df 一看,每个分区的空间都还富余的很。从 munin 的监控图表上看 Filesystem usage 也很平稳,但下面的 Inode usage 就有问题了,其中一个分区的 usage 已经到了100%。赶紧跑到服务器上 df -i 检查,果然是 Inode 耗尽。原来这个分区是用来扔各种日志和临时文件的,其中有某个程序产生的临时文件又小又多,又没有进行定时回滚,造成在磁盘空间耗尽之前文件系统的 Inode 就被用光了。

  Linux/Unix like OS 的文件系统中每个目录树中的节点并不是像 Windows 那样直接包含文件的具体信息,而只包含了文件名和 Inode number 。通过 Inode number 所找到对应于文件名的 Inode 节点中才真正记录了文件的大小/物理地址/所有者/访问权限/时间戳/被硬链接的次数等实际的 metadata 。因此你可以在 Linux 系统中通过硬链接( hard link ) 的方式给某个文件创建无数个位于不同目录下的文件名,而实际的文件数据只需要一份拷贝。

  但也正因为这种文件系统的结构,当你在 Linux 中进行 IO 操作的时候,需要的资源除了磁盘空间以外,还要有剩余的 Inode 才行。缺省情况下, Linux 在系统安装过程中按照1个 Inode 对应 2k 磁盘空间来计算每个分区的最大 Inode 数。一旦文件系统创建之后,每个分区可用 Inode 数就无法进行动态调整。

  正常来说,一般不太会出现某个分区的 Inode 耗尽而磁盘空间尚余的情况,除非像我碰到的这样垃圾小文件疯长而又没进行有效的清理。但如果确实需要的话,可以在创建文件系统(比如用 mke2fs )的时候根据实际需要来调整这个参数(比如分区如果用于存放超大视频文件的话 Inode 的数量可以少一些;如果打算存放的文件是大量小于 2k 的迷你文件的话就要考虑多创建一些 Inode)。

  附:Inode Definition by The Linux Information Project

  其它人碰到的 No space left on device 原因:

  超出系统中同时运行的最大 message queue 个数限制 : 在 root 下用 sysctl kernel.msgmni 检查该参数, sysctl -w kernel.msgmni=XXX 重新设定即可。

  cvs 异常断开的连接在 /tmp 目录下留下大量的临时文件导致 /tmp 目录满

标签 ( Tags ) : ,,

+ 0 - 0 | §RunAsUser for MSP ignored 错误

sendmail 不知道啥时候又不工作了,上次是 unknown user smmsp ,这回是 RunAsUser for MSP ignored

WARNING: RunAsUser for MSP ignored, check group ids (egid=502, want=51)
can not chdir(/var/spool/clientmqueue/): Permission denied
Program mode requires special privileges, e.g., root or TrustedUser.

据说是因为 sendmail 有时候会在对用户/组名进行对应的时候出错,所以需要把 /etc/mail/submit.cf 里面缺省的配置行

O RunAsUser=smmsp

改成直接使用 smmsp 对应的用户/组 ID的形式:

O RunAsUser=51:51

照方抓药,结果是错误依旧。看来这个问题应该是老版本 sendmail 的问题 ... OrZ

Google 来 Google 去,终于找到个新鲜的说法

It would be worth a careful examination of ${SOURCE}/sendmail/SECURITY,
especially the recommended perms :

--- begin quote ---
-r-xr-sr-x root  smmsp ... /PATH/TO/sendmail
drwxrwx--- smmsp smmsp ... /var/spool/clientmqueue
drwx------ root  wheel ... /var/spool/mqueue
-r--r--r-- root  wheel ... /etc/mail/sendmail.cf
-r--r--r-- root  wheel ... /etc/mail/submit.cf


[Notice: On some OS "wheel" is not used but "bin" or "root" instead,
however, this is not important here.]

That is, the owner of sendmail is root, the group is smmsp, and the binary
is set-group-ID. The client mail queue is owned by smmsp with group smmsp
and is group writable. The client mail queue directory must be writable by
smmsp, but it must not be accessible for others. That is, do not use world
read or execute permissions. In submit.cf the option UseMSP must be set,
and QueueFileMode must be set to 0660
.
--- end quote ---

检查下来,clientmqueuemqueue 目录的权限都没问题,唯独 sendmail 的主程序经过了几次 link :

which sendmail
/usr/sbin/sendmail    -> /etc/alternatives/mta
/etc/alternatives/mta -> /usr/sbin/sendmail.sendmail

而这个 /usr/sbin/sendmail.sendmail 的权限竟然是

-rwxr-xr-x  1 root root ... /usr/sbin/sendmail.sendmail

于是

chown root.smmsp /usr/sbin/sendmail.sendmail
chmod g+s /usr/sbin/sendmail.sendmail
/etc/init.d/sendmail stop
/etc/init.d/sendmail start

再尝试发邮件,搞定。

标签 ( Tags ) : ,,

+ 0 - 0 | §C#调用VC++.net托管库程序集DLL
Could not load file or assembly '... ...' or one of its dependencies. 由于应用程序配置不正确,应用程序未能启动 ...  查看全文

标签 ( Tags ) : ,

+ 0 - 0 | §Windows下以其他用户身份运行程序

  从 Windows 2000 开始,微软的视窗操作系统开始提供给当前登录用户以不同的用户身份来运行程序的功能。前提是系统的 RunAs 服务(Windows 2000 下) / Secondary Logon 服务(Windows XP 下)没有被禁用并处于已启动状态。

  在必需的 RunAs / Secondary Logon 服务已经启动之后,就可以为程序设定用户身份。对于一般的可执行程序来说,只需要创建指向该可执行文件的快捷方式,然后在按住 Shift 键的同时鼠标右键单击快捷方式,然后单击“运行方式 ...”,在弹出的对话框中设置指定的用户及密码信息即可。这里是微软官方的 HOW TO 指南。

  但对于某些特殊类型的快捷方式来说,用 Shift + 鼠标右键 唤出的菜单中并没有“运行方式 ...”的设置选项,比如说一些批处理文件 (.bat)等有缺省文件类型打开方式的快捷连接。对于这种文件如果需要使用到 RunAs 的功能,可以新建一个空的快捷方式,在快捷方式向导对话框中键入项目的位置为 runas /savecred /usr:administrator "command line to the real application" 即可。其中 /usr: 后面的 administrator 表示以 administrator 用户身份运行程序;command line to the real application 填写实际程序的执行命令; /savecred 参数将自动保存输入的密码,这样在下一次运行快捷方式的时候就不需要再输入密码(该参数在 XP Home Edition 版本中无效),如果不希望系统保存密码去掉该参数即可。

标签 ( Tags ) : ,

+ 1 - 0 | §批处理控制VMWare虚拟机
VMWare 确实是好东西,不过安装之后会增加四个自动启动的服务以及两个虚拟的网络连接。我是比较讨厌这种没事就占着系统资源的东西,何况也不是经常要用着 VMWare ,所以写了个批处理脚本来自动启动/关闭 VMWare 虚拟机以及相关的服务和网络连接。  查看全文

标签 ( Tags ) : ,,

+ 1 - 1 | §在MySQL查询结果集中得到记录行号

如果需要在查询语句返回的列中包含一列表示该条记录在整个结果集中的行号, ISO SQL:2003 标准提出的方法是提供 ROW_NUMBER() / RANK() 函数。 Oracle 中可以使用标准方法(8i版本以上),也可以使用非标准的 ROWNUM ; MS SQL Server 则在 2005 版本中提供了 ROW_NUMBER() 函数;但在 MySQL 中似乎还没有这样的系统自带功能。虽然 LIMIT 可以很方便的对返回的结果集数量和位置进行过滤,但过滤出来的记录的行号却没办法被 SELECT 到。据说 MySQL 是早就想增加这个功能了,但我是还没找到。

解决方法是通过预定义用户变量来实现:

set @mycnt = 0;
select (@mycnt := @mycnt + 1) as ROWNUM , othercol from tblname order by othercol;

这样查询出来的结果集中 ROWNUM 就保存了行编号信息。这个行编号信息的某种用途在于当你需要根据需要对数据按照某种规则排序并取出排序之后的某一行数据,并且希望知道这行数据在之前排序中的位置时就用得着了。比如:

set @mycnt = 0;
select * from (
    select (@mycnt := @mycnt + 1) as ROWNUM , othercol
     from tblname order by othercol
) as A where othercol=OneKeyID;

当然你也可以通过创建临时表的方法把查询结果写到某个拥有 auto_increment 字段的临时表中再做查询,但考虑到临时表在 MySQL master / slave 模式下可能产生的问题,用这样临时用户定义变量的方式来计算查询结果集每一行对应的行号还是更为简洁 -- 除非你愿意在 PHP 或其他语言脚本中对返回的整个结果集再作处理。

标签 ( Tags ) : ,,

+ 0 - 0 | §在Modal Dialog中操作Modless Form

当使用 form.ShowDialog(); 创建一个模式对话框的时候,如果在这个 Modal Dialog Form 的构造函数又创建了一个新的 Form 并调用 form.Show() 来显示它,然后在 模式对话框的 Load 事件或其它后续的事件触发时把新创建的 modless form 给 Close 掉的话(比如当对话框创建过程中需要比较长的数据加载过程而调用了一个进度条窗口来体现数据加载的进度),会发现当这个由 modal dialog 自己创建的 form 被 Close 的时候, modal dialog 本身也同时被 Close 掉了。

导致模式对话框被自动 Close 的原因是 form.ShowDialog() 的行为模式是将当前活动窗口设置为它的所有者( Owner ),这在一般情况下自然就是调用 ShowDialog 方法的那个 Form 。但如果在这个模式对话框的构造函数里面又创建了一个新的 Form 并 Show 出来的话,当前活动窗口就变成这个新创建的子 Form 而不是事实上希望的那个 Form 了。这就使得 Modal Dialog 所创建的子 Form 变成了它的 Owner ,Owner 一旦被关闭,这个 Modal Dialog 自然也就被销毁了。

所以更为保险的调用方法是显式的指出该模式对话框的所有者: form.ShowDialog(this); 把调用窗口的引用作为参数传递,防止在模式对话框被构建之前有其他的窗体变成活动窗体。

标签 ( Tags ) : ,

+ 1 - 0 | §[存]VS2005无法启动调试问题

在 Visual Studio 2005 里面试图调试项目的时候出现错误信息:“无法启动调试 绑定句柄无效”。

有三种解决方法:

  1. 开启 Terminal Services 服务。天知道为什么调试器还需要这个服务?我向来都是禁用此服务的。
  2. 在项目属性的 “Debug” (调试) 一项里,把 “Enable the Visual Studio hosting process” (启用Visual Studio 宿主进程) 选项禁掉(该项缺省是被启用的,用于提供经过优化的调试)。
  3. 在项目属性的 “Debug” (调试) 一项里,把 “启动非托管代码调试” 选项选中。

标签 ( Tags ) : ,

+ 0 - 0 | §[存] 如何乱序排列文件内容
洗牌问题:洗一副扑克,有什么好办法?既能洗得均匀,又能洗得快?即相对于一个文件来说怎样高效率的实现乱序排列?  查看全文

标签 ( Tags ) : ,,

+ 1 - 0 | §升级Linux Kernel导致fork异常

实践再次证明“永远不要轻易去升级系统”这句至理名言的正确性。然而原有系统的不稳定使得我们不得不尝试如此做。

继几个还算可以能够接受的升级后遗症之后,又发现一个用 c 写的服务程序出了异常。这个接受客户端连接请求的服务程序理论上来说 fork 出来的处理子进程不会超过个位数;但现在跑了一段时间后 fork 出来的进程会突然线性增加,直到资源耗尽。

本来以为是恶意程序在攻击端口,但查看日志并没有发现任何异常的ip连入。在找不到问题的情况下,只好在服务器上把源代码重新编译连接了一次,结果这个疯狂的 fork 居然就消失了!

虽然在这里很多人对于 “Each version of the kernel requires applications to be compiled specifically for it” 的说话嗤之以鼻,但我现在好像就碰到了类似的现象。谁来告诉我这是为什么?

标签 ( Tags ) : ,

+ 0 - 0 | §CentOS下su的提示信息问题

  最近重装服务器,顺便把系统换成了 CentOS 4.3 。结果发现终端登录的时候如果想 su 到 root 用户的时候会出现一段要求用户交互的文字:

$ su -
Password:
Your default context is root:system_r:unconfined_t.
Do you want to choose a different one? [n]

  这是因为安装的时候启用了 SELinux ;而 CentOS 新版本对于 su 的处理除了要求输入 root 的密码之外,还要求确认 SELinux 的上下文信息。这句确认信息虽然基本上可以直接按回车忽略过去,但对于一些需要 su 的自动脚本来说就是不必要的麻烦了。

  解决方法是修改 /etc/pam.d/su 文件,把其中的

session    required     /lib/security/$ISA/pam_selinux.so open multiple
  这行改成
session    required     /lib/security/$ISA/pam_selinux.so open

  也就是去掉 multiple 选项即可。当然如果觉得完全不需要 SELinux 提供的内核保护的话,也可以修改 /etc/selinux/config 配置文件,把 SELLINUX 参数改为:

SELINUX=disabled

  该配置文件将被 init 读取,当你重启系统之后使用 getenforce 命令查看 SELinux 的状态应该就可以看到已经是 disabled 了。据说也可以把 SELINUXTYPE 参数改为 SELINUXTYPE=strict 来解决。

  这个问题似乎在 CentOS 4 / RHEL4 的某些版本上都存在。之前用的老版系统则不需要修改任何配置。

  附: Introducing SELinux , rhel4-tut , Think before deploying Security-Enhanced Linux in RHEL 4

标签 ( Tags ) : ,,

+ 1 - 0 | §SVN PROPFIND Request Failed

PROPFIND Request Failed - Error 405 HTTP Method Not Allowed

This message comes in different flavours. You might be seeing this error when:

  • PROPFIND Request Failed
    You tried to browse the parent path of a repository instead of the repository itself using an older version of TortoiseSVN. Try appending the name of the repository you wish to access, or upgrade TortoiseSVN to 1.2.3 or newer.
  • PROPFIND Request Failed
    You forgot to append a '/' slash to the end of the URL you entered. Older versions of TSVN requires that there be a '/' after the repository name. If you forget this, TSVN will strip the repository name from the URL and therefore try to access the parent directory.
  • Lock Request Failed
    You tried to lock a file in your working copy which no longer exists in the repository. Update your working copy before trying to lock files.

For more information about what actually caused the error, seek out the Apache error log.

这是 TortoiseSVN 对于 PROPFIND Request Failed 错误的说明。 实际上,除了上面提到的几个与 TortoiseSVN 版本有关的原因之外,也可能是你根本就敲错了 repository 所在的路径。理论上来说返回的错误码如果是 404 Not Found 更容易让人理解一些,但确实就是返回 405 的错误。一个小小的键盘键入错误也许就会让你误以为是 svn 的服务器出了什么问题。。

标签 ( Tags ) : ,

+ 0 - 1 | §[存] Scripting.Decoder 代码
Windows Script Encoder 对 asp / vbscript / jscript 等脚本进行编码混淆。收集些解码相关的资料。  查看全文

标签 ( Tags ) : ,,

+ 1 - 0 | §Links 2006-08-29: myisamchk
  • Checking and repairing MySQL tables
  • 使用myisamchk进行崩溃恢复
  • MySQL 5.1 Table Maintenance Statements
  • MySQL 5.1 Table Maintenance and Crash Recovery
    MySQL 虽然提供了 myisamchk 工具和 CHECK/REPAIR/ANALYZE/OPTIMIZE TABLE 命令来完成大部分的数据库表修复操作,但却没有把这些功能给自动化。这大概也算是开源软件与商业软件之间的差别之一吧。越是成熟的商业软件对用户来说越傻瓜式;开源软件则把主动权都扔在使用者手里,再好的功能也需要使用者自己去编写更多的脚本才能全面的利用。先 Mark 一把,等忙完了手头的工作,早晚得把 MySQL Table 的自动修复和优化脚本给整出来,不然冷不丁半夜三更给叫醒实在受不了。

标签 ( Tags ) : ,

+ 1 - 0 | §[z]SHMMAX and SHMALL

On Linux, the default shared memory limit (both SHMMAX and SHMALL) is 32 MB in 2.2 kernels, but it can be changed in the proc file system (without reboot). For example, to allow 128 MB run these commands:

$ echo 134217728 >/proc/sys/kernel/shmall
$ echo 134217728 >/proc/sys/kernel/shmmax


These commands could also be put into a script to run at boot-time.

Alternatively, sysctl can be used, if available, to control these parameters. Look for a file called /etc/sysctl.conf and add the following lines to it:

kernel.shmall = 134217728
kernel.shmmax = 134217728


The sysctl.conf file is usually processed at system boot-up, but sysctl can also be called explicitly.

标签 ( Tags ) : ,

+ 0 - 0 | §MySQL启动失败的另类原因

  毫无预兆的, MySQL 罢工了。 用 mysql.server 启动脚本启动之后,没有任何提示信息就结束,mysqld进程自然是没有起来。

  把 mysql.server 里面 $bindir/mysqld_safe --datadir=$datadir --pid-file=$server_pid_file >/dev/null 2>&1 这句的输出重定向去掉后运行,结果发现报错: File size limit exceedednohup ... ...

  这样看来自然是有文件太大了。但查看了 mysql 数据目录下相关的数据库文件和日志文件,最大的也就几百兆。 ulimit -a 查看也没有对文件大小做任何限制。

  经过 N 分钟的郁闷之后,决定用 find / -size +2048000k 查找整个硬盘上面的可疑文件。结果是: /var/log/pacct 这个2G多的大文件冒了出来。很显然,这是 SA 激活了 accton 之后产生的日志文件,没给做回滚。二话不说,清空 /var/log/pacct 再启动一次 MySQL ,一切恢复正常!

  搞不懂的是为什么 mysql 的启动脚本会受这样一个无关痛痒的进程统计日志的影响而导致 mysqld 进程完全无法启动。估计还是 mysql.server / mysqld_safe 脚本逻辑的问题。。

标签 ( Tags ) : ,

+ 0 - 0 | §sendmail Error: unknown user smmsp

sendmail突然不能用了。错误信息:

/etc/mail/submit.cf: line 423: readcf: option RunAsUser: unknown user smmsp
/etc/mail/submit.cf: line 442: readcf: option TrustedUser: unknown user smmsp
Mail submission program must have RunAsUser set to non root user

原来 sendmail 用来查询排队邮件目录的用户/组给删掉了。yjnet 在 sendmail 安装笔记中说: sendmail 必须有一个set-group-id(默认是smmsp组)的程序来在一个组可写的目录中查询 排队邮件。所以我们要建立一个smmsp用户和组。并建立如下目录并设置相应的权限,具体设置要求可查询源码目录树下sendmail/SECURITY文档。
# groupadd smmsp 
# useradd smmsp -d /var/spool/clientmqueue -s /dev/null
# mkdir /var/spool/clientmqueue
# chown -R smmsp:smmsp /var/spool/clientmqueue  
# chmod -R 770 /var/spool/clientmqueue  
# mkdir /etc/mail
# mkdir /var/spool/mqueue
# chmod go-w / /etc /etc/mail /usr /var /var/spool /var/spool/mqueue
# chown root / /etc /etc/mail /usr /var /var/spool /var/spool/mqueue

把用户和相应的组加回去在之后,问题解决。

标签 ( Tags ) : ,

+ 0 - 0 | §Oracle Web Cache 进程监控
OracleAS Web Cache 有个 Auto-restart 的功能,可以自动监控 web cache 进程的状态,发现异常自动重启。但在 Web Cache Manager 管理界面配置好了以后就发现 web cache 进程会被 auto-restart 进程不断的重启,发疯了一样。  查看全文

标签 ( Tags ) : ,,,

+ 0 - 1 | §Links 2006-06-01: svn DB Format
  • How FSFS is Better
    如果你打算开始使用 svn 来进行源代码版本控制,那么除了需要了解 svn 的一般特性之外,还需要决定到底采用 FSFS 还是 Berkeley DB 作为 svn repositories 的存储格式。由于历史原因, svn 开发团队最初使用了比较大众化的 Berkeley DB 。直到2004年以后,才引入了基于文本文件的 FSFS系统。相比而言, FSFS 似乎具有更多的优点。

标签 ( Tags ) : ,

+ 1 - 1 | §ftok 函数的 Shell 脚本实现
“古老的 Sys IPC 仍然有好几种有效的用途。三种 IPC 对象是共享内存,信号灯和消息。”当使用到 IPC 的这些对象时,你需要为每个对象创建一个 Key。虽然理论上来说我们在定义一个 IPC Key 的时候可以使用任意自己喜欢的 Key ,但为了避免与其他的程序产生定义重复,在 UNIX/Linux 中一般会使用 key_t ftok(const char *path, int id) 函数来生成一个比较唯一的 Key 值。然而,“每个人都讨厌 System V IPC。它比打孔纸带还慢,使用与文件系统完全无关少得可怜的名字空间,使用人类讨厌的数字给它的对象命名,并且还常常自己忘记自己的对象,你的系统管理员经常需要用 ipcs(1) 查找那些丢失了的对象并且用 ipcrm(1) 删除它们,还得求老天保佑不要在用光内存以后才发现问题。” 对于来实现进程监控/自动重启Bash Shell 脚本来说,在脚本里面硬编码进当前程序用到的 Key 值肯定不是个好办法,最好是实现相同算法的 ftok 函数。  查看全文

标签 ( Tags ) : ,,,

+ 1 - 0 | §Links 2006-05-26: 语言革命
  • How to Love a Framework You've Never Used
    以前的编程语言把大量的工作留给程序员,那是因为当时的电脑是非常昂贵的设备,只有最重要的东西才可以交给它去处理。随着技术的发展,编程语言的智能化程度越来越高,程序员需要做的工作则越来越少。所有的这些语言上的革命只有一个目的:经济利益最大化。或许有一天,程序完全可以自动完成所有的工作,程序员这个职业随之成为历史。
  • Rails-inspired PHP frameworks
  • XML for <SCRIPT> Cross Platform XML Parser in JavaScript
    Powerful, standards-compliant JavaScript XML parser that is designed to help web application designers implement cross platform applications that take advantage of client-side manipulation of XML data.
  • 几个有用的音频文件处理软件

标签 ( Tags ) : ,

+ 1 - 0 | §修改 Linux 的 LANG 环境变量

一般来说要设置 Linux 系统的环境变量只需要在 /etc/profile (全局) 或者 ~/.bashrc (单个用户) 即可。但是对于 LANG 变量来说,有时候你即使在所有这些初始化脚本里面 export 过了,LANG 的值还是纹丝不动。实际上,你需要去修改 /etc/sysconfig/i18n 文件里面的内容。

标签 ( Tags ) : ,

+ 0 - 0 | §Linux 下的 Oracle 启动脚本
Usage: sh oracled [start|stop|restart] SIDs 其中SIDs是数据库名,多个名称之间用逗号分隔。缺省的操作是 restart ,也可以指定需要进行的操作( start | stop | restart )  查看全文

标签 ( Tags ) : ,,

+ 1 - 1 | §MySQL的大小写敏感性

在 MySQL 中,数据库和表对就于那些目录下的目录和文件。因而,操作系统的敏感性决定数据库和表命名的大小写敏感。这就意味着数据库和表名在 Windows 中是大小写不敏感的,而在大多数类型的 Unix 系统中是大小写敏感的。

奇怪的是列名与列的别名在所有的情况下均是忽略大小写的,而表的别名又是区分大小写的。

要避免这个问题,你最好在定义数据库命名规则的时候就全部采用小写字母加下划线的组合,而不使用任何的大写字母。

或者也可以强制以 -O lower_case_table_names=1 参数启动 mysqld(如果使用 --defaults-file=...\my.cnf 参数来读取指定的配置文件启动 mysqld 的话,你需要在配置文件的 [mysqld] 区段下增加一行 lower_case_table_names=1)。这样MySQL 将在创建与查找时将所有的表名自动转换为小写字符(这个选项缺省地在 Windows 中为 1 ,在 Unix 中为 0。从 MySQL 4.0.2 开始,这个选项同样适用于数据库名)。

当你更改这个选项时,你必须在启动 mysqld 前首先将老的表名转换为小写字母。

换句话说,如果你希望在数据库里面创建表的时候保留大小写字符状态,则应该把这个参数置0: lower_case_table_names=1 。否则的话你会发现同样的sqldump脚本在不同的操作系统下最终导入的结果不一样(在Windows下所有的大写字符都变成小写了)。

标签 ( Tags ) :

+ 2 - 0 | §SVN 初体验

要在新服务器上装版本控制系统了。本来打算和以前一样用 CVS 来进行源代码管理,碰巧看到 duduwolf 对 SVN 大力推荐,加上这篇文章对于各种版本控制系统功能的完整比较,一直为 CVS 的各种缺陷感到郁闷的我自然毫不犹豫投奔了 SVN 的怀抱。

安装过程算不上一帆风顺,但我不打算在这里写出一篇完整的安装手册来,只简单记录几点体会。

服务模式

SVN 可以通过内置的 svnserve 提供服务,也可以和 Apache 配合通过标准的 http/https 来提供服务。用 svnserve 的好处是配置相对简单,但不足是 svnserve 所能提供的权限管理最小粒度只能到版本库(和 CVS 一样)。这对于开源软件的开发使用可能问题不大,但对于用作公司内部源代码控制来说就太简单了。所以我选择用 Apache + SSL + SVN 。

当初使用 CVS 最让我觉得美中不足的就是它的目录权限控制。因为针对每个用户只能控制其访问整个版本库的读写权限,以至于我不得不创建了N个独立的版本库。即便这样,每个版本库下面还是有许多项目是希望能分别控制权限的。当时采用的方法是禁用了CVS的目录浏览功能,并对每个项目目录名增加随机编号。只有知道确切的目录名称才可以访问到该项目。现在既然改用 SVN ,如果还是无法对版本库里面的每一个子目录进行精确的权限控制的话,还不如用 CVS 。通过配置AuthzSVNAccessFile文件来控制每一个项目目录的访问权限虽然算不上特别方便,但总比 CVS 那样完全没办法好。

数据存储

SVN 同样可以使用两种数据存储方式: Berkeley DB 和 FSFS 。在我看来, Berkeley DB 的优势在于其成熟性,但需要更多的日常管理和维护,并且是平台依赖的。所以我选择更简便的 FSFS 。

APR libraries

安装 SVN 的时候最好指定 --with-apr=  和 --with-apr-util= 参数到 Apache 安装的根目录(ServerRoot)下,而不是使用缺省的 SVN 安装包中自带的 apr 。否则如果你安装的 Apache 版本不同有可能导致 APR 库不匹配,出现类似 Can't set position pointer in file '/svn/test/db/revs/1': Invalid argument 的错误。Updated 2006-04-20 16:30 -- 比如说如果你安装的是apache 2.2.0版本,就需要在编译安装svn的时候指定--with-apxs和--with-apr参数到你的apache2.2.0安装目录下:
./configure --prefix=${subversionInstallFolder} /
--with-apxs=${apacheInstallFolder}/bin/apxs /
--with-apr=${apacheInstallFolder} /
--with-apr-util=${apacheInstallFolder} /
--with-ssl /
--with-zlib /
--enable-maintainer-mode

make clean && make && make install

签署证书

既然是公司内部的源码控制系统,通过 SSL 来加密保护登录信息还是很有必要的。证书的制作所填写的信息其他都关系不大,只要注意生成根证书和服务器请求签证文件时的两次 Common Name 不能一样(理论上Common Name 应该是用户将会用来访问的完整域名字符串),否则会导致证书生成的时候出现 error 18 at 0 depth lookup:self signed certificate 错误。

Updated 2006-06-29 12:52 -- 似乎还是有不少朋友在安装svn的时候碰到各种各样的问题,所以我把自己用来进行 svn server 恢复的完整脚本提供给大家下载( 点击下载 svn_recover.rar 13,473 字节),仅供大家参考。需要说明的几点:

  1. 不要直接运行 reinstall.sh 脚本。因为这个脚本是针对我自己的 svn 服务器的情况来写的,目的是在重装服务器的时候可以完全实现自动化。所以如果你不去了解脚本的实际工作就放服务器上执行,由此造成的任何后果我可不负责 :)
  2. 我的 svn server 不需要提供其他的服务,所以我的安装脚本是完全以 svn 服务为中心的,如果你的服务器还需要提供 php / mysql 等服务的话,这个脚本可能并不适合你。
  3. 为了 recover 的方便,我把 svn 所需要的一些关键文件放在了 resource 目录下面,安装脚本自动从 resource 目录下读取相关的文件拷贝到对应的目标目录下。你如果想用这个脚本,需要在 resource 目录下提供你自己服务器环境下的真实文件。本压缩包中的资源文件仅作示例。

标签 ( Tags ) :

+ 0 - 1 | §开始招人

如果你拥有以下特长之一,同时愿意与我们同甘共苦共同发展,或者凑巧对体育有着狂热的爱好,请联系我(工作地点:上海)。

  1. 熟悉LAMP环境下的web应用开发 + Ajax + PHP frameworks
  2. C/C++/Java + 网络编程 + Linux Shell
  3. C# GUI + MySQL
我的联系方式
+ 0 - 0 | §用BAT批处理快速删除CVS目录
Windows 下的 BAT 批处理命令行脚本虽然不像 Linux Shell 那样灵活强大,不过在某些情况下你还是可以利用它来完成一些事情。比如用 来对项目源代码进行控制的时候。  查看全文

标签 ( Tags ) : ,

+ 0 - 0 | §[转]用Erwin进行MySQL数据建模

为了能够使用 ERWin 能够进行基于 MYSQL 数据库的物理设计,可以采用以下方法步骤(假定你已经有了一个设计好的LOGICAL MODEL):

  1. 安装MYSQL的ODBC DRIVER,可以去MYSQL.COM,有链接可以下载。
  2. 在ODBC的管理程序中建立一个连接你的MYSQL数据库的USER DSN。
  3. 从已建立好的LOGICAL MODEL生成一个基于ODBC 2.0的PHYSICAL MODEL。
  4. 这步是重点:
      因为基于ODBC生成的数据库脚本并不完全兼容MYSQL的SQL语法,所以还需要做些其他的工作。
      例如,有时候需要用到DATETIME TYPE,但是只能生成DATE TYPE,我们可以采用SQL脚本来完成。
      ERWIN支持的脚本有两种:MODEL-LEVEL, TABLE-LEVEL.前者是针对整个PHYSICAL MODEL,而后者可以用于1个或多个TABLE。根据运行顺序,又分两种:Pre Script, Post Script。看名字就知道意思了。
      如果我们想把表里的"CREATE_ON"的TYPE设置为DATETIME,可以生成一个TABLE-LEVEL SCRIPT:
    ALTER TABLE %TableName MODIFY CREATE_ON DATETIME
      %TableName是ERWIN自带的宏,还有许多其他的宏,关于这方面的,可以看帮助。你也可以根据自己的需要,定义不同的SCRIPT(例如,需要设置一个字段为AUTO_INCREMENT)。
  5. 在FORWARD ENGINEER里根据实际情况选择Pre Script/Post Script,然后生成即可。

标签 ( Tags ) : ,,

+ 1 - 1 | §高效程序员应该养成的七个习惯

对于软件工程师来说,工作也许意味着许多东西 -- 稳定的收入、做自己感兴趣的项目、找一份更好工作的跳板,或者你只是喜欢与其他程序员共事。但说到“效率”,强调的是在一定时间内按质完成项目的能力。Phil Chu根据自己的经验提出了高效程序员应该养成的七个习惯。建议去看看作者的原文(可能需要代理才能正常访问)。

  • 理解你的需求
    成为一个有效率的程序员首先要知道如何正确的支配自己的时间。对时间最大的浪费莫过于去做那些没有用处或者永远不会上线的项目。而导致这种结果的根源往往是对需求理解的偏差。
    要最大程度避免这种情况的发生,最好的办法是快速建模,尽可能让演示系统早点出来。对于客户来说,只有看得到摸得着的产品摆在面前,他们才会有兴趣去试用观察,才会在实际的操作中发现供需双方在需求理解上的偏差。否则即使你写上几百页的需求分析文档也只能是自己的一面之词,客户可没耐心去检查这些文档写的是否准确。
    另一方面,你应该让每一个阶段的开发成果都能够尽早的提交给客户。让他们以完全不考虑操作合理性和业务逻辑性的傻瓜级操作来发现程序员编程中的固有思维局限。尤其必须让QA尽早的介入到项目开发中来。如果能够每天提交一份测试版本给QA自然是最理想的了,但大多数项目开发做不到这样的粒度,那么就争取每周提交一份可测试版本。重要的是应该让QA和开发能够保持交错并行状态。只有这样,才能让QA尽早发现bug,降低每个bug的修复成本,同时缩减独立测试周期的跨度。
    程序员往往不愿意把半成品代码交付给测试人员,相反他们更喜欢在所有代码都完工,达到自己满意的程度之后再让别人来测试。因为在这之前的代码往往存在很多程序员自己知道需要修改(或者故意留待后续补全)的流程缺失和Bug,测试人员并不知道哪些是真正的Bug,哪些只是临时性的运行错误,每次都会一股脑儿作为Bug反馈给程序员。这往往让程序员们心烦。同时测试人员有时候也不喜欢测试这种很多分支都走不通的中间版本。
    但不管喜不喜欢,测试并发现问题是测试人员的工作;程序员则应该认识到,Bug反馈得越早就越是件好事情。QA和开发之间的关系往往很敌对,可实际上双方的目标是一致的。“忠言逆耳”古训有之,对于程序员来说就应该“有则改之,无则加勉”。总好过项目完成之后才发现一堆的问题,到那时候再要做修改,基本上都会牵一发而动全身,痛苦的还是程序员自己。
  • 保持真实性
    尽可能让你的系统运行在最接近真实环境配置下面,使用有实际意义的数据和真实的编译版本,并经常性进行模块整合。如果你的测试环境使用的数据都是些胡乱添加的东西,那么将来和测试数据大相径庭的真实数据这块大冰山早晚会撞沉你的程序。另一方面如果你只在开发环境来编译运行测试,会发现正式发布之后有各种各样莫名其妙的问题产生,到最后原来都是因为环境配置与开发环境有些不起眼的差异所导致。把所有模块整合进行编译联调,看上去应该是最后作的一项附加工作,但实际上这是一项需要在开发过程中经常性进行的工作。只有这样QA才能有最完整的东西拿来测试,得到更多的Bug反馈,同时降低模块整合的难度。
  • 理解你的代码
    书写规范的代码,并保持代码的整洁。Coding是一门艺术。正如写作一样,同样的文字在文豪的笔下就能够熠熠生辉,读起来赏心悦目;在普通人的笔下大概就只是词能达意的效果了;在某些人的笔下或许就需要研究半天才能猜出个大概来。当然不可能人人都成为艺术家,但至少你可以学会欣赏艺术、学习艺术。书写漂亮的代码是对自己工作的尊重,也是对其他程序员的尊重。如果你的代码中间充斥着大段过时的注释、可读性差的变量/函数,怎么去要求别人或者自己以后能够理解它们?
  • 最优编程
    把你的时间花在代码的功能上, 而不是去把现有的代码改得对自己胃口(尤其对于那些copy/paste过来的代码);要找到系统的瓶颈进行优化,而不是对那些无益于系统整体性能提高的地方做无用功。
  • 管理好你自己
    也许有人会说计划和进度控制是PM的事情,但一个好的程序员应该比PM更了解自己目前工作的进度。不论上头给的进度计划是否合理,你都应该有自己的原则和概念,清楚知道每天该做什么怎么去做。
  • 持续教育
    只有不断的学习、实践、犯错误,你才会真正有所提高。在我看来,对于程序员来说最好的老师不在学校,而在书本、网络、社区。学会自我学习才能保持与时俱进。
  • R-E-S-P-E-C-T
    互相尊重是一切的基础。

标签 ( Tags ) : ,

+ 0 - 0 | §项目开发的内部竞标机制

之前开发上碰到的问题:

需求过多,开发人员疲于应付
开发效率低
缺乏项目后期跟踪,很多项目做完之后变得无人问津

尝试过的解决方案:

项目外包 - 验收和后续维护上出现不少问题。进行需求的沟通也花费了大量的精力。
控制需求量 - 由于所有的商务内容提需求的时候都认为这个项目非常重要,往往造成需求控制失效。

一方面,开发人员抱怨需求像雪片一样飘过来,到最后却被证明做的不少项目都是无用功;
另一方面,市场、内容方面的策划人员抱怨提出来的需求没人来做,做出来的东西又质量不高。

现在想来,采用公司内部的项目竞标机制可以比较折衷的解决这些矛盾。

内部竞标机制:

需求方提供项目需求、开发周期与项目报酬等信息提出竞标;
开发人员自愿组合或者由高级分析设计人员点将组成项目小组来接受项目任务;

由于开发人员来自公司内部,对业务需求更加熟悉,同时限以公司统一的开发规范,有利于验收维护。
组队接受项目争取项目报酬的方式更能激发开发人员的创造力和主动性。

对于需求方来说,要考虑项目报酬成本,会更加谨慎的考虑需求的提出是否合理。

对于绩效考察来说,开发人员的能力贡献更加一目了然。

标签 ( Tags ) :

+ 0 - 0 | §Links 2006-01-15: engineer

标签 ( Tags ) :

+ 0 - 0 | §自动生成代码的可维护性

  slashdot上kale77in提出一个问题:“Ruby on Rails的自动代码生成(scaffolding)机制是否会使以后的代码变得难以维护?”

  实际上问题的关键并不在于RoR。看看Black Parrot的反问:“Do you have a beef with compilers and assemblers?”当我们使用C/C++/Java等各种语言的编译器把高级语言进行编译之后交付机器运行解释的时候,并不会去担心编译之后的东西是否具有“可维护性”,因为没几个程序员会去阅读这些汇编语言的内容。这样一个事实建立的基础在于各种编译器已经足够鲁棒,能够准确地翻译我们所使用的高级语言。kale77in之所以有那样的疑问,在于他对这些自动代码的不信任,基于可能会出问题的假设之上才会有需要去维护的担忧。

  这种担心当然是有理由存在的。毕竟RoR也才刚刚发布了1.0版本,功能缺陷不可避免。也许不久的将来会出现真正的“高高级语言”,将目前手工实现的大部分编码工作自动化(程序员们要么学习新语言,要么失业 ^_^);但在目前来说,正如不少回复者所提到的那样:scaffolding在Rails中并未占据着举足轻重的地位,你完全可以不去使用这项功能。

  在Rails之前,类似或者不似的代码生成功能在各种IDE之中并不鲜见。VC++的那些项目向导也曾经让我颇感迷茫:一个字还没写目录下面已经有成堆的源文件了;直到后来理解了MFC的来龙去脉,摒弃向导去白手起家完成整个VC++项目的编写,才明白原来那些大段大段的自动生成代码也就那么回事而已。甚至你使用UltraEdit/EditPlus之类的文本编辑器也可以设置自己的文件模板,从某种角度来说Rails的自动代码生成和这些没太大区别。而数据建模中应用到的代码生成更是广泛(ROSE, Erwin, PowerDesigner)。

  对于不成熟的东西,可以去尝试、促进,但不要依赖。目前来说,Rails的scaffolding充其量也只是一个辅助工具 -- 帮助新手热身或者用来创建那些临时性、生命周期很短的Web应用 -- 只要使用得当,完全谈不上会否影响项目代码的可维护性。

  说到可维护性,不得不提一句:人类的破坏力绝对要比任何机器强,手写代码难以维护的可能性远比程序自动生成的要高 &g