分類彙整: 電腦資訊

踩到 FreeBSD 6.1 的地雷…

昨天裝了台機器,由於有兩台相同容量的 18G 硬碟,此裝好之後順手替 root partition 加上了 Software RAID….

沒想到一時疏忽,修改 fstab 時忘了加上 /mirror/ …

/dev/mirror/gm0s1b none swap sw 0 0
/dev/mirror/gm0s1a / ufs rw 1 1

所以重開機時開不起來了…
原本根據 這篇 的說明,只要在 mountroot> prompt 下,重新指定 root partition 位置就可以進去修正了…

但是,沒想到好像踩到 FreeBSD 6.1 的地雷了:
kern/98910: [kbd] keyboard not working at mountroot prompt on IBM T42P

也就是 mountroot> 下鍵盤不能動了…. 我用的是研華的伺服器,問題跟上面這個 PR 一模一樣…

偏偏我這台機器的光碟和軟碟又都壞了…. 只好很苦命的再把機器搬出機櫃來拆開,外接光碟重新修正了事….

svndumpfilter with wildcards support ?

Subversion 的 svnadmin obliterate 功能一直沒有實作出來,這實在是有點麻煩,尤其是當負責管理一個 repository 時,常常就會有人把 *.exe, *.obj, *.lib, *.a 統統給 commit 進去了….

然後你就會發現整個 repository 長大的速度越來越快,就算事後用 svn delete 把它砍掉還是無濟於事,因為那已經成為無法抹滅的歷史了

雖然可以事先設定 svn:ignore 來解決,不過偶而還是會有漏網之魚,官方提供的解決方法是使用 svndumpfiler 來把不要的檔案徹底從歷史記憶中濾除

# svnadmin create REPOS2
# svnadmin dump REPOS1 | svndumpfilter exclude XX.exe | svnadmin load REPOS2

這方法當然沒有 svnadmin obliterate 好,不過也是目前狀況下不得不的作法

但是這個方法最大的問題在於 svndumpfilter 無法接受 wildcards (萬用字元),也就是你無法指定 svndumpfilter exclude ‘*.exe’

所以,萬一不小心遇上了機車的狀況,你可能要一個一個把檔名找出來濾掉 XD

所以不久前就想辦法修改了 svndumpfilter 的程式,把它加上直接濾除特定副檔名檔案的功能…

[patch to subversion/svndumpfilter/main.c]
(the filename with leading dot will be matched against filename extension)

--- subversion/svndumpfilter/main.c.orig
+++ subversion/svndumpfilter/main.c
@@ -111,7 +111,12 @@
       pfx_len = strlen(pfx);
       if (path_len < pfx_len)
         continue;
-      if (strncmp(path, pfx, pfx_len) == 0)
+      if( pfx[0] == '.' )
+      {
+        if( strncmp( path+path_len-pfx_len, pfx, pfx_len ) == 0 )
+          return TRUE;
+      }
+      else if (strncmp (path, pfx, pfx_len) == 0)
         return TRUE;
     }
 
@@ -1257,7 +1262,8 @@
             style, and absolute. */
        SVN_INT_ERR(svn_utf_cstring_to_utf8(&prefix, os->argv[i], pool));
        prefix = svn_path_internal_style(prefix, pool);
-       prefix = svn_path_join("/", prefix, pool);
+       if( prefix[0] != '.' )
+          prefix = svn_path_join("/", prefix, pool);
        APR_ARRAY_PUSH(opt_state.prefixes, const char *) = prefix;
      }
  }

--- subversion/svndumpfilter/main.c.orig +++ subversion/svndumpfilter/main.c @@ -111,7 +111,12 @@ pfx_len = strlen(pfx); if (path_len < pfx_len) continue; - if (strncmp(path, pfx, pfx_len) == 0) + if( pfx[0] == '.' ) + { + if( strncmp( path+path_len-pfx_len, pfx, pfx_len ) == 0 ) + return TRUE; + } + else if (strncmp (path, pfx, pfx_len) == 0) return TRUE; } @@ -1257,7 +1262,8 @@ style, and absolute. */ SVN_INT_ERR(svn_utf_cstring_to_utf8(&prefix, os->argv[i], pool)); prefix = svn_path_internal_style(prefix, pool); - prefix = svn_path_join("/", prefix, pool); + if( prefix[0] != '.' ) + prefix = svn_path_join("/", prefix, pool); APR_ARRAY_PUSH(opt_state.prefixes, const char *) = prefix; } }

這個 patch 有點投機取巧,因為我懶得真的去實作 wildcards,我需要的功能只要能濾除指定的副檔名就可以了…

所以這個 patch 把原來 svndumpfilter include/exclude 後面接的檔名參數作特殊判斷,只要第一字元是小數點,就當作要去 match 的副檔名,因此,要濾除 *.exe 只要這樣作就可以了:

# svnadmin create REPOS2
# svnadmin dump REPOS1 | svndumpfilter exclude .exe | svnadmin load REPOS2

剛好看到前幾天也有人寫了個 PATCH 讓 svndumpfilter 完全支援 wildcards… 不過我沒試過,相信不久的將來應該會被整合進正式版本中

當然最希望還是 svmadmin obliterate 能早日被支援,就不用這麼辛苦了

使用 bcompiler 來編譯(加密)您的 PHP 原始碼

Using bcomipler to compile (encode) your PHP script (in FreeBSD)

eAccelerator 的 encoder 在 PHP 5.1 以後就無法運作了,使是最新的版本 0.9.5 也不行,因此如果您還想用 eAccelerator 的 encoder,乖乖待在 PHP 4.x or PHP 5.0 吧,相關資訊可參考之前的兩篇文章:

根據 mailing list 上面作者最新的說法,短期內應該都還不會修復,甚至有可能還會放棄支援 encoder 部份,作者還推薦大家改用 bcompiler … orz
所以如果你跟我一樣必須要用 PHP 5.1 的話,就跟我一起來玩看看 bcompiler 囉

附帶一提,原本是要買 ionCube 公司開發的 PHP Encoder 的,這看來是目前編譯(加密)PHP 原始碼最好的選擇,價格也不算貴,而且花的是公司的錢,不過還是先試用看看 bcompiler 好了,真的不好用的話,再來買囉

以下的安裝與使用說明均以 FreeBSD 為範例,其他作業系統應該也差不多,請自己試看看吧

在正式安裝之前提醒你,bcompiler 會用到 bzip2 這個 extension,所以先安裝一下 php5-bz2:

# cd /usr/ports/archivers/php5-bz2
# make install clean

bcompiler 是一個收容於 PECL 的 PHP extension,您可以直接使用 pecl 這個命令來安裝,而 pecl 的使用方法與 pear 相同,因此你必須先安裝 pear :

# cd /usr/ports/devel/pear
# make install clean

pear 安裝好後,同時會有一個 pecl 命令可用 (/usr/locel/bin/pecl),可用它來安裝 bcompiler

pecl install channel://pecl.php.net/bcompiler-0.8

不過呢,我發現直接執行 pecl 會發生錯誤(至少在 FreeBSD 下是如此):

# pecl
Fatal error: Call to undefined function preg_match() in ...

問題出在 /usr/local/bin/pecl 這個 script 的最後一行:

exec $PHP -C -n -q $INCARG -d output_buffering=1 -d safe_mode=0 ...

這一行的 -n 這個選項代表不載入 php.ini 設定檔,因此 pcre.so 就沒有被載入,
然後你就看到上面的錯誤了,所以自己去改一下程式把 -n 拿掉吧….

拿掉之後,安裝程式應該就可以正常運作了了:

pecl install channel://pecl.php.net/bcompiler-0.8

安裝好後,記得要改設定把 bcompiler 這個 extension 載入

# echo "extension=bcompiler.so" >> /usr/local/etc/php/extensions.ini

bcompiler 全名是 PHP bytecode Compiler,詳細的使用方法可以參考 PHP 網站上的詳細說明: PHP bytecode Compiler: http://www.php.net/manual/en/ref.bcompiler.php

看不懂的話,bcompiler_write_file() 這個 function 的說明裡面有範例:

$fh = fopen("example.phb", "w");
bcompiler_write_header($fh);
bcompiler_write_file($fh, "example.php");
bcompiler_write_footer($fh);
fclose($fh);

為了易於使用,我寫了一個簡單的 script,使用方法如下:

BENCODER v1.3 - Encode your PHP script using bcompiler

Usage: bencoder [-f] [-q] -o FILE    file1.php
       bencoder [-f] [-q] -o OUTDIR  file1.php file2.php ...
       bencoder [-f] [-q] -o OUTDIR  -s SRCDIR  [-e SUFFIX] [-r] [-c] [-l]

  -o FILE   : the file name to write the encoded script
              (default to '-encoded.XXX' suffix)
  -o OUTDIR : the directory to write all encoded files

  -a SRCDIR
  -s SRCDIR : encode all files in this source directory

  -r        : encode directories recursively (no by default)
  -f        : force overwriting even if the target exists
  -e SUFFIX : encode the files with the SUFFIX extension only (default: php)
              (regular expression allowed, ex: "php|inc")
  -c        : copy files those shouldn't be encoded (no by default)
  -l        : follow symbolic link (no by default)
  -q        : do not print the file name while encoding or copying
  -b
  -bz2      : compress the encoded files with bz2 (needs bzip2-extension)

想用的人到 這邊 自己抓回去玩玩看吧

# wget http://bencoder.urdada.net/bencoder
# chmod 755 bencoder
# mv bencoder /usr/local/bin/

在把程式使用 bcompiler 編碼之後,執行的時候發覺 $_SERVER 以及 $_ENV 的變數都不見了,後來查了資料,才發現要把 auto_globals_jit 關掉 (Off) 才行,請直接修改您的 php.ini :

; When enabled, the SERVER and ENV variables are created when they're first
; used (Just In Time) instead of when the script starts. If these variables
; are not used within a script, having this directive on will result in a
; performance gain. The PHP directives register_globals, register_long_arrays,
; and register_argc_argv must be disabled for this directive to have any affect.
auto_globals_jit = Off

FreeBSD Software RAID-1 (gmirror)

手邊某台伺服器的 root 硬碟太小了(只有 8GB),然後上面又丟了很多重要的東西,所以一直想把它給換成大一點的,剛好手邊有一些換下來的 18GB 硬碟備品,就決定來換一下,並玩玩 Software RAID-1 (Mirror)

首先是把系統碟先換到比較大顆的硬碟,步驟請參考:

FreeBSD Handbook: How do I move my system over to my huge new disk?

接下來就要玩玩 Software RAID-1 (Mirror) 了

過去 FreeBSD 下面 Software RAID 的作法大多使用 vinum,但 vinum 的用法比較複雜,而且似乎只能適用新的分割區,無法對原有的硬碟直接建立一份 Mirror。

GEOM Mirror (gmirror) 是一種從 FreeBSD 5.3 開始支援的新 Software RAID-1,尤其適用於系統碟 (root partition)。

關於 FreeBSD 下面幾種 Disk Mirroring 的作法,可參考:

FreeBSD System Disk Mirroring – How to establish a RAID-1 for the system partitions

詳細的作法可參考這篇文章:

ONLamp.com: Using Software RAID-1 with FreeBSD

對舊硬碟設定一下,然後重開機後,把新硬碟加上去,再稍微設定一下,十分鐘內就搞定了!

最方便的是,使用 GEOM Mirror 建立的系統碟在系統內部並不會有特殊設定檔,所有的設定是直接放在硬碟最後一個磁區的 metadata 內,而且使用 gmirror RAID-1 的系統碟可以隨時切換用任何一顆開機,不會有任何問題

除了 gmirror 提供 RAID-1 之外,同樣採用 GEOM 架構的程式還有 gstripe (RAID-0) 及 graid3 (RAID-3),有興趣的人可以玩看看…

eAccelerator 無法使用於 PHP 5.1

上個月 PHP 5.1 正式發表了

昨天一時興起,把 PHP 5.0 利用 portupgrade 升級成 PHP 5.1,過程沒遇到什麼阻礙
安裝完後也覺得應該沒什麼問題,但是後來卻發現 eAccelerator 無法使用了

不管是 eAccelerator 0.9.3 或者 0.9.4-rc1 都一樣不能使用(連編譯都會發生錯誤)

根據 討論區 上面的說法,要修復這個問題似乎還需要一段時間

即使是將要發表的 0.9.4 版本,也不會支援 PHP 5.1

因此,有重度依賴 eAccelerator 的使用者,請乖乖先待在 PHP 4.4 或者 PHP 5.0 吧

Ref: eAccelerator – PHP 網頁加速及編碼

在 Dell PE 2850 上面安裝 FreeBSD 6.0

公司最近進了一些 Dell PowerEdge 2850 的伺服器…

今天第一次嚐試在 Dell PowerEdge 2850 上面安裝 FreeBSD 6.0

安裝過程並沒有甚麼問題,但是安裝完成、並重新開機之後,發現 console 的鍵盤竟然不能動了!

同樣的情況似乎也存在於 FreeBSD 5.3 及 FreeBSD 5.4 的樣子(不確定,有人說 FreeBSD 5.3 沒這問題)

經過一番搜尋,發覺是因為這台機器上面有一張 “Dell Remote Access Card (DRAC)”,這個裝置會被系統辨識成一個 USB Keyboard,所以導致開完機之後,正常的 PS/2 鍵盤反而不能動了!

解決方式如下:

  1. 先以 Single User Mode 進入系統
  2. 在命令列模式下,先執行下列命令:
    # fsck -y  /
    # mount -u  /
  3. 然後編輯 /etc/devd.conf,把對於 USB Keyboard 的支援暫時拿掉,也就是把下面幾行開頭加上 #
    # When a USB keyboard arrives, attach it as the console keyboard ...
    #attach 100 {
    #       device-name "ukbd0";
    #       action "kbdcontrol -k /dev/ukbd0 < /dev/console ...
    #};
    #detach 100 {
    #       device-name "ukbd0";
    #       action "kbdcontrol -k /dev/kbd0 < /dev/console";
    #};
  4. 然後輸入 exit 離開 Single User Mode 之後,就可以順利進入系統,而且 console 鍵盤也可以正常運作,下次開機也不會有問題!

目前看起來,Dell PE-2850 使用 FreeBSD 6.0 當作業系統,除了上面這個 console 鍵盤問題之外,還沒遇到其他問題,系統也還算穩定