2008/12/09

snow.js 雪花效果

聖誕節快到了,為了應景客戶希望網站上增加雪花效果。
參考網址:
http://www.dynamicdrive.com/dynamicindex3/snow.htm
http://www.dynamicdrive.com/dynamicindex3/snownoimages.htm
使用上只要注意將 script 放在 body 區塊內就行了。

2008/11/02

硬碟 WD 5000AACS 入手, 1GB 不到 4 塊新台幣

雖然家裡已經有 NAS 跑 RAID 0,但一直想再買顆硬碟把 NAS 裡的資料不定時備份出來,免得哪天 NAS 掛掉甚麼都沒了。這兩天剛好要將 NAS 的韌體更新,就趁此機會來買硬碟、備份 NAS 的資料。
上 PChome 查了一下硬碟的價格,目前的行情如下:
規格型號單價每 GB 價格
WD 1TBWD 10EACS3,988.3.89.
WD 750GBWD7500AACS/P3,625.4.83.
WD 640GBWD6400AAKS/P2,499.3.90.
WD 640GBWD6400AACS/P2,578.4.03.
WD 500GBWD5000AACS1,980.3.96.
價格單位:新台幣
除了 WD 750GB 以外,每 GB 單價都已經跌到 4 塊左右。

2008/10/19

get_class() in PHP 4 & PHP 5

get_class() 函式可以取得物件的名稱,但是在 PHP 4 和 PHP 5,回傳的物件名稱一個是小寫、一個是有分大小寫。

class Foo {}
$aa = new Foo();
echo get_class($aa);
// in PHP 4.4.8 --> foo (全小寫)
// in PHP 5.2.6 --> Foo (分大小寫)

2008/09/28

瀏覽器差異: 標籤的預設行為

<button> 是 form 元素之一,其中的屬性 type 可用的值有 submit、reset、button,預設值是 submit,其效果等同於 <input>:
1. <button type="submit">submit</button> 等同於 <input type="submit">
2. <button type="reset">reset</button> 等同於 <input type="reset">
3. <button type="button">abc</button> 等同於 <input type="button" value="abc">

可是當 <button> 沒有指定 type 時,依據 W3C 的規範,預設等同於 submit,但是在 IE7 下,卻是等同於 button。

for Internet Explorer 7
<button>abc</button> 等同於 <input type="button" value="abc">

for Mozilla Firefox 3
<button>abc</button> 等同於 <input type="submit" value="abc">

因此,如下的表單在 IE 7 與 FF 3 下會有全然不同的行為:






原本預期按下 <button> check 之後,會執行 NameCheck() 函式。
在 IE 7 下會如期運作,但在 FF 3 下,這個表單會直接送出。

因此在使用 <button> 時,建議要指定 type 屬性,以免效果不如預期。

2008/09/27

Javascript 使用 parseInt() 時務必指定進位基數

parseInt() 的第二個參數是指定進位基數,若不指定,parseInt 會依據第一個參數自動判斷。
如果開頭是 0x 或 0X,則視為 16 進位;若開頭是 0,則視為 8 進位;其餘則視為 10 進位。

var e = '1234';
alert(parseInt(e)); // 1234
var f = '01234';
alert(parseInt(f)); // 668, 八進位制的 1234 轉成十進位是 668
alert(parseInt(f, 10)); // 1234, 指定成十進位。

因此在使用 parseInt() 時,除非真的要使用到預設的自動判斷機制,否則請指定進位基數,免得造成自己的困擾。

Ref 1: JavaScript網頁設計師手札
Ref 2: JavaScript parseInt() Function

Javascript 字串轉數值

方法一: Number constructor function

var e = '123';
e = Number(e); // 123

方法二: parseInt() 或 parseFloat()

var e = '123.45abc';
var e1 = parseInt(e, 10); // 123
var e2 = parseFloat(e); // 123.45

若無法轉換成數值時,會回傳 NaN (Not A Number)。

var f = 'abc123';
var f1 = Number(f); // NaN
var f2 = parseInt(f, 10); // NaN
var f3 = parseFloat(f); // NaN


Ref: JavaScript網頁設計師手札

Javascript - 數值轉字串

方法一: String constructor function

var e = 123;
e = String(e);

方法二: toString method

var e = 123;
e = e.toString();

方法三: string concatenation

var e = 123;
var ee = e + '';


Ref: JavaScript網頁設計師手札

2008/09/25

iconv 與 NULL

今天在處理一個文字檔匯入的工作,遇到了 iconv 與 NULL 的小狀況,值得留意一下。

由於網頁是 utf-8,而匯入檔是 big5,因此利用 iconv 來做編碼轉換:

$name = iconv('big5', 'utf-8', $name);

這是再標準不過的寫法了。

但是實際執行匯入時,資料有四萬多筆,卻只匯入了一萬多筆就停了。
打開 log 瞧瞧,發現 MySQL 有錯誤訊息:

Column 'name' cannot be null

原來是有的資料 iconv 轉不出來,就回傳 false,然後欄位 name 又設定不可為 NULL,因此 MySQL 就回傳錯誤訊息。

本來想說,把欄位 name 設定成可接受 NULL 就好,
但這樣又會影響到其他程式,如果其他程式沒有考慮到會有 NULL 的狀況,可能會造成錯誤。
因此最好的做法就是改變匯入時的寫法,遇到 false 就賦予空值,多個小步驟就能解決這個問題。

$name = iconv('big5', 'utf-8', $name);
$name = ($name) ? $name : '';

2008/06/24

MediaWiki 1.12.0 權限設定

用 MediaWiki 來管理個人資訊也有一段時間了,但 MediaWiki 預設是不管有沒有登入,都可以檢視、編輯各個頁面。
雖說我的 wiki 有鎖 IP、還有設定密碼,可是總是會擔心哪天程式搬家時,忘了去設定而讓所有資訊都曝了光,因此還是把預設的權限改掉比較安心。

MediaWiki 的所有設定參數都放在 ~/includes/DefaultSettings.php 內,大約在 1083 行可以看到關於權限的設定參數與說明: $wgGroupPermissions
這個檔案放的都是預設值,如果要改,要將設定值設定在另外一個檔案 ~/LocalSettings.php 內。
因為升級的時候 DefaultSettings.php 會被新版本的檔案覆蓋,如果把設定放在 DefaultSettings.php 內,升級之後設定值就不見了。

該死的 sosospider

正在做例行的伺服器維護時,突然系統變得超慢,用 vmstat 一看

procs memory page disk faults cpu
r b w avm fre flt re pi po fr sr ad0 in sy cs us sy id
136 29 0 1767964 30084 75528 6449 344 1952 19101 3716299 54 83147 0 120759 53 47 0
132 16 0 1690556 30944 39779 3063 309 224 9382 932991 30 71882 0 112895 53 47 0
153 20 0 1716916 41504 70373 6371 313 2848 20009 3229680 51 157679 0 277140 41 59 0


哇!正在跑的 process 竟然飆到 130 以上,難怪系統超慢。追查之後發現是從 124.115.0.xxx 與 124.115.4.xxx 來的 http request 把伺服器搞掛。Google 一下這幾個 IP,原來正是惡名昭彰的騰訊 sosospider。因此二話不說,直接把這兩個網段 ban 掉


ipfw add 100 deny tcp from 124.115.0.1/24 to any
ipfw add 100 deny tcp from 124.115.4.1/24 to any


再用 vmstat 觀察一下,馬上就恢復正常了

procs memory page disk faults cpu
r b w avm fre flt re pi po fr sr ad0 in sy cs us sy id
156 18 0 1721036 31456 44789 4409 340 736 6014 1109953 36 90724 0 157802 43 57 0
144 22 0 1738760 29972 50467 4974 437 1600 10285 1768221 57 81266 0 136508 46 54 0
39 34 0 1762924 33188 54962 2551 958 704 19168 971608 62 58070 0 92074 52 48 0
4 7 0 1650664 59108 23262 481 285 0 18632 0 50 17862 0 33268 39 61 0
0 1 0 1628484 65848 3535 10 98 0 4956 0 75 781 0 1926 27 58 15
0 1 0 1619168 69368 1420 18 0 0 1384 0 2 614 0 694 11 30 59


之後看一下封鎖的狀況: ipfw show

00100 165903 9944820 deny tcp from 124.115.0.0/24 to any
00100 59700 3579864 deny tcp from 124.115.4.0/24 to any

總共 try 了二十幾萬次,真是惡質...

2008/04/21

Seednet 廣告信判斷規則

突然接到 Seednet 的通知,說公司的某個 IP 一直狂發廣告信,要我盡快處理,不然會被擋掉。
但是這個 IP 就是專門用來發送會員電子報的伺服器,而且當初申請的就是企業專用的 ADSL,哪有叫企業不能寄送電子報的道理。
溝通了一會兒之後,Seednet 告知他們判定廣告信的方式,調整一下發送頻率就可以避免被擋信。
Seednet 的廣告信判斷規則:
  • 一個 IP 五分鐘內不可超過 250 次 connection。

  • 一個帳號五分鐘內不能超過 150 封信。

  • 如果超過上述的限制,就會被擋 20 分鐘,20 分鐘之後才會接受寄信。
    如果再超過上述限制,就再擋 20 分鐘(不會累加,一樣是 20 分鐘後再開放寄信)。

    2008/04/01

    strtotime() + month 要小心!

    因故需要找出當月的最後一天,一開始是用以下語法:
    $last_day_of_this_month = date("Y-m-d", (mktime(0, 0, 0, date("m", 
    strtotime("next month")), 1, date("Y", strtotime("next month")))) - 86400);


    由於每個月的天數不一樣,最後一天可能是 28、29、30、31,因此作法是先找出下個月第一天的 unix timestamp,然後減去 86400 秒(一天),再利用 date() 去調整成想要的日期格式。

    但是這寫法在今天 2008-03-31 卻出問題,跑出來的結果是 2008-04-30,不是預期的 2008-03-31。
    仔細追查,發現問題是出在 strtotime("next month") 這段程式碼。

    測試程式碼:

    echo date("Y-m-d", strtotime("today")); // 2008-03-31
    echo date("Y-m-d", strtotime("+1 month")); // 2008-05-01
    echo date("Y-m-d", strtotime("next month")); // 2008-05-01

    從這個結果來看,感覺 strtotime() 在處理 +1 month 時,是直接把月份 +1,像是 3 月 31 日就直接變成 4 月 31 日,由於 4 月只有 30 天,就變成 5 月 1 日。

    既然 strtotime() 不能用,就換個寫法:
    $last_day_of_this_month = date("Y-m-d", (mktime(0,0,0,
    (((date("n")+1)>12) ? 1 : date("n")+1),1,date("Y", strtotime("next month"))))-24*60*60);

    還是自己算月份比較保險...

    附帶一提,在官方手冊上有提到,在 PHP 4.4.0 以前的版本,next 會誤判成 +2,建議使用 +1 取代 next。但我在 4.4.8 和 5.2.5 下測試,結果都是一樣錯。

    2008/03/30

    常用 pf 指令

    最近在設定 pf(之前都是用 ipfw),紀錄一下 pf 指令:
    pfctl -f /etc/pf.conf

    載入設定檔 /etc/pf.conf

    pfctl -nf /etc/pf.conf

    檢查設定檔 /etc/pf.conf 語法

    pfctl -Nf /etc/pf.conf

    只載入設定檔 /etc/pf.conf 中的 NAT 規則

    pfctl -Rf /etc/pf.conf

    只載入設定檔 /etc/pf.conf 中的過濾規則

    pfctl -sn

    顯示目前的 NAT 規則

    pfctl -sr

    顯示目前的過濾規則

    pfctl -ss

    顯示目前的連線狀態

    pfctl -si

    顯示過濾的統計資訊

    pfctl -sT

    顯示目前的 tables

    pfctl -sa

    顯示除了網路介面與作業系統fingerprint以外的所有資訊

    pfctl -t TableName -T show

    顯示 TableName 的內容

    pfctl -t TableName -T flush

    清除 TableName 的內容


    kernel: NMI ISA 20, EISA ff

    才上線的伺服器又掛點了,這次的錯誤訊息是
    Mar 21 03:44:29 s0803 kernel: NMI ISA 20, EISA ff
    Mar 21 03:44:29 s0803 kernel: NMI ISA 30, EISA ff
    Mar 21 03:44:29 s0803 kernel: NMI ISA 20, EISA ff

    用 Google 上查到這訊息是來自 sys/i386/isa/nmi.c 的 isa_nmi(),通常是硬體的問題。

    記憶體才送修過、換了新品回來,研判應該是主機板的問題,畢竟這張板子已經用了四、五年,也可以汰換了。
    這台伺服器就給內部當測試機用,能用幾天是幾天...

    參考資料:
  • http://lists.freebsd.org/pipermail/freebsd-drivers/2006-February/000143.html

  • http://en.wikipedia.org/wiki/Non-Maskable_Interrupt
  • 2008/03/20

    連停電也有email通知?!台電 計劃性工作停電公告電子報

    晚上公司突然停電,趕忙打電話找台電問是怎麼回事?
    才剛上網查到電話(市話撥打 1911),電就來了。算了,就甭打了,省點力氣唄!

    倒是在台電的網站上發現了計畫性工作停電查詢這個功能,可以查詢各地區停電施工的時間表,而且這個頁面下方還有電子報通知的功能(計劃性工作停電公告電子報),對我這種天天收 email 的人還挺方便。

    No Power Email Notice
    不過訂閱還要填電號,得把電費單翻出來看(誰會去記那個),有點不方便。

    2008/03/18

    線上申請 HiNet DNS 反解

    今天要幫新伺服器申請 DNS 反解,才發現 HiNet DNS 反解已經改成線上申請就可以了,以前都要傳真申請。
    還不錯,有進步。

    http://hidomain.hinet.net/hidns.html

    2008/03/02

    Apache 2.2 + php 4.4.8 安裝問題

    前幾天 FreeBSD 7.0 終於釋出了,剛好有伺服器可以灌。想說 php 的部分不能升級成 php5,但至少 Apache 可以改裝 Apache 2.2。
    但沒想到一裝完 Apache 卻開不起來,執行 apachectl start 之後出現錯誤訊息:
    No such file or directory: Failed to enable the 'httpready' Accept Filter
    解法請見:
    1. http://jerome.anyday.com.tw/archives/64
    2. http://mlab.net/freebsd.php#apache

    之後執行 apachectl start 卻一點反應也沒有? Apache 還是沒起來。
    一看 httpd-error.log 卻看到以下訊息:
    [warn] Init: Session Cache is not configured [hint: SSLSessionCache]
    解法請見:
    http://mlab.net/freebsd.php#php


    2008/02/25

    AP #2 (PHY# 1) failed! panic y/n? [y]

    最近在整理汰換下來的伺服器,將一台 XEON 2.4GHz 雙 CPU 的伺服器重灌 FreeBSD 6.3 時,開機的時候偶而會出現此訊息:

    AP #2 (PHY# 1) failed!
    panic y/n? [y]


    然後直接按 y 或 enter,系統馬上會重開,重開之後又能正常開機。

    2008/02/17

    怪事?檔案莫名其妙被改?

    中午接到客戶反應系統無法使用,檢查之後發現是某個 php 檔的 ( 被改成 h,因此導致 Parse error。(如下圖)
    file changed
    當下先將問題修正,然後再找原因。