10年06月19日 Saturday , 168 次点击 , 2 条评论

昨天发现wordpress3.0已经发布,就顺手升级了。

略看了一下更新内容,几乎没什么让我感兴趣的,但与MU版本的合并堪称WP历史上的一个里程碑,从此一套WP可以支持创建多个博客了,这会使WP作为博客程序中的王者的地位无可撼动。

但我最近几度都想把博客换到dokuwiki下。

自从开始用dokuwiki来组织知识和GTD以来,我对wiki产生了越来越深的痴迷,最主要的原因就是它可以用很简单的语法写出格式规整的文章,我几乎可以不用考虑排版布局而只需把注意力放在文章内容上就行了。而将wiki上的文章发到博客上时,还需要重写,比较浪费时间。

但我最终放弃这个想法,最主要的原因是博客文章太多了,截至现在已经有五百多篇且大多是用HTML写的,难以转换。何况WP作为一个博客系统较wiki有着天生的优势,使用较为方便,如果用wiki来做博客,要做不少工作。

分类 : 青梅煮酒
Top
10年06月14日 Monday , 136 次点击 , 3 条评论

昨天发现feedburner的订阅数图片又不显示了,以下略去文明用语若干。遂咬指为笔,草一血诏,藏于美帝服务器上:

PHP:
  1. <?php
  2. /*
  3.  * 将$fburl替换为自己的feedburner订阅数图片地址,然后将博客中的图片地址换成此脚本的URL即可
  4.  */
  5. $fburl = 'http://feeds.feedburner.com/~fc/leninlee?bg=99CCFF&amp;fg=444444&amp;anim=0';
  6. $fbfl = 'fb.gif';
  7. $fp = fopen($fburl, 'rb');
  8. if ($fp) {
  9.     $fp_local = fopen($fbfl, 'wb');
  10.     if ($fp_local) {
  11.         while (!feof($fp)) {
  12.             fwrite($fp_local, fread($fp, 1024*8), 1024*8);
  13.         }
  14.         fclose($fp_local);
  15.     }
  16.     fclose($fp);
  17. }
  18. header('Location: '.$fbfl);
  19. ?>

煌煌天朝,竟然容不下几十象素……

2010-06-15 更新:

Dongsheng Cai童鞋提供了一种更好的方法:

PHP:
  1. <?php
  2. header('Content-Type: image/gif');
  3. readfile('http://feeds.feedburner.com/~fc/leninlee?bg=99CCFF&fg=444444&anim=0');
  4. ?>

分类 : 编程
Top
10年06月11日 Friday , 180 次点击 , 评论

cpufrequtils可以根据不同的方案自动调节CPU的频率,从而达到在系统空闲时降低CPU温度、节省电力的目的。

Archlinux官方wiki已经介绍得很明白了:http://wiki.archlinux.org/index.php/Cpufrequtils_(简体中文)

使用后效果明显,CPU温度有所下降,下面是cpufrequtils在archer上的工作情况:

[lenin@archer ~]$ cpufreq-info
cpufrequtils 007: cpufreq-info (C) Dominik Brodowski 2004-2009
Report errors and bugs to cpufreq@vger.kernel.org, please.
analyzing CPU 0:
driver: acpi-cpufreq
CPUs which run at the same hardware frequency: 0 1
CPUs which need to have their frequency coordinated by software: 0
maximum transition latency: 10.0 us.
hardware limits: 800 MHz - 2.53 GHz
available frequency steps: 2.53 GHz, 2.53 GHz, 1.60 GHz, 800 MHz
available cpufreq governors: ondemand, performance
current policy: frequency should be within 800 MHz and 1.60 GHz.
The governor "ondemand" may decide which speed to use
within this range.
current CPU frequency is 800 MHz.
analyzing CPU 1:
driver: acpi-cpufreq
CPUs which run at the same hardware frequency: 0 1
CPUs which need to have their frequency coordinated by software: 1
maximum transition latency: 10.0 us.
hardware limits: 800 MHz - 2.53 GHz
available frequency steps: 2.53 GHz, 2.53 GHz, 1.60 GHz, 800 MHz
available cpufreq governors: ondemand, performance
current policy: frequency should be within 800 MHz and 1.60 GHz.
The governor "performance" may decide which speed to use
within this range.
current CPU frequency is 1.60 GHz.

Tags :
分类 : 计算机
Top
10年05月17日 Monday , 385 次点击 , 3 条评论

作为和NSIS并立的、两个最流行的免费Windows应用程序安装包制作工具之一,Inno在学习难度上相对要低一些,非常适合对一些简单的桌面程序打包。但对于较复杂的安装过程,或者Web应用程序来说,我个人觉得不是Inno的强项。当然,既然Inno内嵌了Pascal语言用以扩展功能,理论上不是不可以应付复杂的安装过程,但实现起来要复杂一些。

比如对于在安装过程中连接数据库并执行SQL脚本这样的需求,使用InstallShield应该会简单地多,而Inno却不支持直接操作数据库,并且相关的资料说明少之又少,还不如NSIS丰富,以至于我踏破铁鞋无觅处,最终却在NSIS的资料中找到了思路。

主要的思路是,在安装过程中,调用数据库客户端连接数据库并执行SQL脚本,然后将执行结果或错误信息输出到文件中,最后通过分析这个文件来判断命令执行的结果。但是,既然是调用特定的客户端,那么对不同数据库的操作自然就有所区别,具体情况如下所述。

首先在打包脚本的[Files]段将必需的文件包含进来:

INI:
  1. [Files]
  2. Source: "D:\Development\MyDemoApp\code\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
  3. Source: "D:\Development\MyDemoApp\sqlcmd.exe"; Flags: dontcopy
  4. Source: "D:\Development\MyDemoApp\sqlcmd.rll"; Flags: dontcopy
  5. Source: "D:\Development\MyDemoApp\mysql.exe"; Flags: dontcopy
  6. Source: "D:\Development\MyDemoApp\script_mssql.sql"; Flags: dontcopy
  7. Source: "D:\Development\MyDemoApp\script_mysql.sql"; Flags: dontcopy
  8. Source: "D:\Development\MyDemoApp\script_oracle.sql"; Flags: dontcopy

在SQL Server中执行脚本的代码片断:

PASCAL:
  1. function ExecScriptInMSSQL(DBHost, DBLogin, DBPass, DBName: String): Boolean;
  2. var
  3.     ConnectExe: String;
  4.     ConnectParam: String;
  5. begin
  6.     {解压临时文件}
  7.     ExtractTemporaryFile('sqlcmd.exe');
  8.     ExtractTemporaryFile('sqlcmd.rll');
  9.     ExtractTemporaryFile('script_mssql.sql');
  10.     {构造数据库连接字符串}
  11.     ConnectExe := ExpandConstant('{tmp}') + '\sqlcmd.exe';
  12.     ConnectParam := ' -S ' + DBHost
  13.         + ' -U ' + DBLogin
  14.         + ' -P ' + DBPass
  15.         + ' -d ' + DBName
  16.         + ' -i script_mssql.sql -o '
  17.         + ExpandConstant('{tmp}') + '\dbstatus.txt';
  18.     {建立数据库连接并执行脚本}
  19.     if Exec(ConnectExe, ConnectParam, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then begin
  20.         Result := ResultCode = 0;
  21.         LoadStringFromFile(ExpandConstant('{tmp}') + '\dbstatus.txt', StatusString);
  22.         if StatusString <> '' then begin
  23.             MsgBox(StatusString, mbError, MB_OK);
  24.             Result := False;
  25.         end else begin
  26.             Result := True;
  27.         end;
  28.     end else begin
  29.         MsgBox('Database update failed:'#10#10 + SysErrorMessage(ResultCode), mbError, MB_OK);
  30.         Result := False;
  31.     end;
  32. end;

在MySQL中执行脚本的代码片断:

PASCAL:
  1. function ExecScriptInMYSQL(DBHost, DBLogin, DBPass, DBName: String): Boolean;
  2. var
  3.     ConnectExe: String;
  4.     ConnectParam: String;
  5. begin
  6.     {解压临时文件}
  7.     ExtractTemporaryFile('mysql.exe');
  8.     ExtractTemporaryFile('script_mysql.sql');
  9.     {构造数据库连接字符串}
  10.     ConnectExe := ExpandConstant('cmd');
  11.     ConnectParam := ' /c "' + ExpandConstant('{tmp}') + '\mysql.exe'
  12.         + ' -h' + DBHost
  13.         + ' -u' + DBLogin
  14.         + ' -p' + DBPass
  15.         + ' -D' + DBName
  16.         + ' -e "source ' + ExpandConstant('{tmp}') + '\script_mysql.sql""> ' + ExpandConstant('{tmp}') + '\dbstatus.txt 2>&1';
  17.     {建立数据库连接并执行脚本}
  18.     if Exec(ConnectExe, ConnectParam, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then begin
  19.         Result := ResultCode = 0;
  20.         LoadStringFromFile(ExpandConstant('{tmp}') + '\dbstatus.txt', StatusString);
  21.         if StatusString <> '' then begin
  22.             MsgBox(StatusString, mbError, MB_OK);
  23.             Result := False;
  24.         end else begin
  25.             Result := True;
  26.         end;
  27.     end else begin
  28.         MsgBox('Database update failed:'#10#10 + SysErrorMessage(ResultCode), mbError, MB_OK);
  29.         Result := False;
  30.     end;
  31. end;

由于mysql.exe没有输出结果到文件的参数,故需要使用cmd.exe来运行mysql.exe以便将其输出重定向到文件dbstatus.txt中。此外,在命令的最后加上参数2>&1,将标准错误输出设备也重定向到文件上,否则命令执行的错误信息不会输出到文件中。

在Oracle中执行脚本的代码片断:

PASCAL:
  1. function ExecScriptInORACLE(ClientPath, DBInstance, DBLogin, DBPass: String): Boolean;
  2. begin
  3.     {解压临时文件}
  4.     ExtractTemporaryFile('script_oracle.sql');
  5.     {连接数据库并执行脚本}
  6.     if Exec(ExpandConstant('cmd'), ' /c "' + ClientPath + ' -L -S ' + DBLogin
  7.         + '/' + DBPass
  8.         + '@' + DBInstance
  9.         + ' @' + ExpandConstant('{tmp}') + '\script_oracle.sql> ' + ExpandConstant('{tmp}') + '\dbstatus.txt 2>&1',
  10.         '',
  11.         SW_HIDE, ewWaitUntilTerminated, ResultCode)
  12.     then begin
  13.         Result := ResultCode = 0;
  14.         LoadStringFromFile(ExpandConstant('{tmp}') + '\dbstatus.txt', StatusString);
  15.         if Pos('holytail', StatusString) <> 0 then begin
  16.             {若输出信息中有“holytail”的子串,则表示脚本成功执行}
  17.             {若执行有误,提示用户打开日志文件}
  18.             if Pos('ORA-', StatusString) <> 0 then begin
  19.                 {提示用户脚本执行出错}
  20.                 if MsgBox('数据库更新出错,是否打开日志文件?', mbConfirmation, MB_YESNO) = IDYES then begin
  21.                     {打开日志}
  22.                     if not ShellExec('', ExpandConstant('{tmp}') + '\dbstatus.txt', '', '', SW_SHOW, ewNoWait, ErrorCode) then begin
  23.                         MsgBox('日志文件打开错误!', mbError, MB_OK);
  24.                     end;
  25.                 end;
  26.                 Result := False;
  27.             {若执行无误,返回True}
  28.             end else begin
  29.                 Result := True;
  30.             end;
  31.         end else if StatusString <> '' then begin
  32.             MsgBox(StatusString, mbError, MB_OK);
  33.             Result := False;
  34.         end else begin
  35.             Result := True;
  36.         end;
  37.     end else begin
  38.         MsgBox('Database update failed:'#10#10 + SysErrorMessage(ResultCode), mbError, MB_OK);
  39.         Result := False;
  40.     end;
  41. end;

Oracle的客户端太大,不能集成到安装包中,应使用一个TInputFileWizardPage由用户选择sqlplus.exe的安装位置。同时,由于sqlplus.exe也没有输出结果到文件的参数,也须使用cmd.exe来运行它并重定向输出到文件。此外,由于sqlplus.exe执行脚本时无论成功还是失败,都会输出信息,故无法像使用sqlcmd.exe和mysql.exe那样简单地判断脚本是否执行成功,需要在脚本的最后通过select语句输出一个特殊的字符串到文件中,然后通过判断dbstatus.txt中是否存在该字符串来判断脚本的执行情况;且由于sqlplus.exe执行完脚本后不会自动退出,还要在脚本最后加上exit语句;故script_oracle.sql的最后必须是如下内容:

SQL:
  1. SELECT 'holytail' FROM dual;
  2. exit;

分类 : 编程
Top
10年05月09日 Sunday , 324 次点击 , 4 条评论

FreeArc的特点在于它在压缩比率与效率上取得了一个很好的平衡。传统的压缩程序则多偏重一点,要么占用系统资源低、速度快,但压缩比率小,如ZIP、RAR;要么压缩比率高,但占用系统资源大、速度慢,如7z。

把RAR归于前者只是相对而言,除了WinZip,没有哪个压缩工具能取得像WinRAR那样的成功。之所以能做到这一点,是因为WinRAR不但继承了WinZip易用的优点,还具有对多种压缩算法广泛的兼容度,最重要的是,RAR压缩算法在效率与比率之间取得了一个非常好的平衡。凭借这些优势,WinRAR一举推翻了WinZip的王座,直到现在,它都是这个领域值得学习的榜样。

早在7-Zip刚刚推出的时候,我就用过它。在压缩比率上,7z较RAR有着明显的优势,但在系统资源占用和压缩速度上,7z的表现非常不理想。最糟糕的是,如果你的机器配置较低,再加上你使用Windows系统,并且尤其喜欢使用图形界面的压缩工具,那7-zip对你来说就是一场恶梦,我曾经有过压缩一个较大的文件时进度条半天都不移动的经历。当然,在Windows命令行或Linux的终端中使用7-zip情况要好很多。此外,随着7-zip自身的完善和电脑配置的更新换代,这些劣势对7-zip普及的限制正逐渐弱化,事实上,我倾向于推荐用7-zip取代WinRAR,因为前者免费且有较大的压缩比率,而后者是收费的。

上周偶然发现的FreeArc,它的主页上居然宣称比最好的压缩工具都快1.5到3倍,并且同时拥有超高的压缩比率。于是我拿7-zip与之作了几个粗略的对比测试,发现虽然没有宣称的那么夸张,但在压缩同样的文件并使用同样的压缩级别时,FreeArc均比7-zip快一些,而压缩比率却要稍高于后者。甚至对于某些格式的文件,FreeArc的“普通”级别的压缩比率都比7-zip“最高”级别的大。

鉴于7-zip是资源占用大户,我非常怀疑在效率上FreeArc较WinRAR会有什么优势,更遑论快上1.5到3倍,但它的效率高于7-zip却是一个不争的事实,何况还有更高的压缩比率。此外,这次的测试中使用的操作系统和7-zip都是64位的,而FreeArc却是32位的,因此在效率的比试上会有不公平的地方。

当然,FreeArc自身的缺点也很大:

  1. 尚无64位版本
  2. 只支持Windows和Linux系统
  3. 不支持多卷压缩(分割压缩)
  4. 其它一些问题

如果能在较短的时间内解决这些问题,我认为FreeArc还是很有前景的。

Tags :
分类 : 计算机
Top