2013-06-04 21:49

[轉載] HTTP 狀態碼

轉載自:HTTP 狀態碼 - 網站管理員工具說明

當向您的伺服器傳送一個要求,要求顯示您網站的網頁 (例如,在使用者在瀏覽器中存取您的網頁,或 Googlebot 檢索該網頁時),則您的伺服器會傳回 HTTP 狀態碼,以回應該要求。

此狀態碼會提供有關該要求的狀態的資訊。此狀態碼會向 Googlebot 提供有關您的網站和所要求的網頁的資訊。

以下為一些常見的狀態碼:

  • 200 - 伺服器成功傳回網頁
  • 404 - 找不到所要求的網頁
  • 503 - 伺服器暫時無法使用

以下是 HTTP 狀態碼的完整清單。您還可以瀏覽有關 HTTP 狀態碼的 W3C 網頁,以取得更多資訊


1xx (Provisional response)
指出暫時回應並需要要求者採取措施以繼續的狀態碼。

  • 100 (Continue)
    要求者應當繼續此要求。伺服器傳回此代碼,指出已收到某個要求的第一部分,正等候其餘部分。
  • 101 (Switching protocols)
    要求者已請求伺服器切換通訊協定,伺服器正在確認即將進行切換。

2xx (Successful)
指出伺服器已成功處理該要求的狀態碼。

  • 200 (Successful)
    伺服器已成功處理該要求。一般而言,這代表伺服器已提供所要求的網頁。如果您在 robots.txt 檔案中看到此狀態,即表示 Googlebot 已成功擷取該網頁。
  • 201 (Created)
    該要求已成功完成,伺服器已建立新的資源。
  • 202 (Accepted)
    伺服器已接受該要求,但尚未處理。
  • 203 (Non-authoritative information)
    伺服器成功處理該要求,但正在傳回可能來自另一來源的資訊。
  • 204 (No Content)
    伺服器已成功處理該要求,但沒有傳回任何內容。
  • 205 (Reset Content)
    伺服器已成功處理該要求,但沒有傳回任何內容。與 204 回應不同,此回應需要要求者重設文件視圖 (例如,清除表單,以輸入新的資料)。
  • 206 (Partial Content)
    伺服器已成功處理部分 GET 要求。

3xx (Redirected)
您需要採取進一步的動作才能完成該要求。通常這些狀態碼會用來重新導向。Google 建議每個要求不要使用超過五次重新導向。您可以使用「網站管理員工具」來查看 Googlebot 在檢索重新導向的網頁時是否存在問題。在 [健康狀態] 下的「檢索錯誤」網頁會列出 Googlebot 因重新導向錯誤而無法檢索的網址。

  • 300 (Multiple Choices)
    根據該要求,伺服器可採取數種動作。伺服器可能會根據要求者 (user-agent) 選擇一個動作,或者可能列出清單供要求者選擇一個動作。
  • 301 (Moved Permanently)
    要求的網頁已永久移到新位置。當伺服器傳回此回應 (作為對 GET 或 HEAD 要求的回應) 時,會自動將要求者導向至新位置。您應該使用此代碼,讓 Googlebot 知道某個網頁或網站已永久移至新位置。
  • 302 (Moved Temporarily)
    伺服器目前正對來自不同位置的網頁回應該要求,但是要求者應該繼續使用原位置發出以後的要求。此代碼類似於回應 GET 或 HEAD 要求的 301 代碼,會自動將要求者導向至另一個位置,但是因為 Googlebot 會繼續檢索原位置並為其建立索引,所以您不應該使用此代碼來告知 Googlebot 某個網頁或網站已移除。
  • 303 (See Other Location)
    當要求者應該對另一個位置發出單獨的 GET 要求以擷取回應時,伺服器會傳回此代碼。對於 HEAD 之外的所有要求,伺服器會自動導向至其他位置。
  • 304 (Not Modified)
    要求的網頁自上次要求以後未經任何修改。當伺服器傳回此回應時,並不會傳回該網頁的內容。
    如果網頁自要求者上次要求以後,未經任何修改,則您應該設定伺服器傳回此回應 (稱為 If-Modified-Since HTTP 標頭)。這樣可以節省您的頻寬和負載,因為您的伺服器可以告知 Googlebot 網頁自上次檢索後,未經任何修改.
  • 305 (Use Proxy)
    要求者只能使用 Proxy 存取要求的網頁。當伺服器傳回此回應時,還會指出要求者應該使用的 Proxy。
  • 307 (Temporary Redirect)
    伺服器目前正對來自不同位置的網頁回應該要求,但是要求者應該繼續使用原位置發出以後的要求。此代碼類似於回應 GET 或 HEAD 要求的 301 代碼,會自動將要求者導向至另一個位置,但是因為 Googlebot 會繼續檢索原位置並為其建立索引,所以您不應該使用此代碼來告知 Googlebot 某個網頁或網站已移除。

4xx (Request Error)
這些狀態碼指出要求中可能存在使伺服器無法進行處理的錯誤。

  • 400 (Bad Request)
    伺服器無法解讀該要求的語法。
  • 401 (Not Authorized)
    該要求需要驗證。登入後,伺服器可能會對網頁傳回此回應。
  • 403 (Forbidden)
    伺服器拒絕要求。如果您看到 Googlebot 在嘗試檢索您網站的有效網頁時收到這個狀態碼 (您可以在 Google 網站管理員工具 [健康狀態] 標籤下的「檢索錯誤」網頁中看到這狀態碼),則可能是因為您的伺服器或主機封鎖了 Googlebot 的存取權。
  • 404 (Not found)
    伺服器找不到要求的網頁。例如,如果該要求是針對伺服器上不存在的網頁,則伺服器通常會傳回此代碼。
    如果您的網站上沒有 robots.txt 檔案,並在 Google 網站管理員工具的「封鎖的網址」網頁看到這個狀態,則這個狀態是正確的。不過,如果您有 robots.txt 檔案,並看到此狀態,則您的 robots.txt 檔案可能未正確命名或位於錯誤的位置。(應該位於網域的最高層級並且命名為 robots.txt)。
    如果您在 Googlebot 嘗試檢索的網址中看到這個狀態,則 Googlebot 所追蹤的很可能是來自其他網頁的無效連結 (可能是舊連結或拼字錯誤的連結)。
  • 405 (Method Not Allowed)
    不允許要求中指定的方法。
  • 406 (Not Acceptable)
    無法以所要求的內容特性回應要求的網頁。
  • 407 (Proxy Authentication Required)
    此狀態碼類似於 401(Not Authorized),但指定要求者必須使用 Proxy 進行驗證。當伺服器傳回此回應時,還會指出要求者應該使用的 Proxy。
  • 408 (Request Timeout)
    等候回應時,發生伺服器逾時。
  • 409 (Conflict)
    完成要求時,伺服器遇到衝突。伺服器必須包括有關在回應中的衝突的資訊。伺服器可能會在 PUT 要求與較早的某個要求相衝突時傳回此狀態碼作為回應,並會提供這兩個要求之間的差異清單。
  • 410 (Gone)
    要求的資源已永久移除後,伺服器會回傳此回應。此代碼類似於 404 (Not Found) 代碼,但在資源曾經存在但現已不復存在的情況下,有時會取代 404 而使用。如果資源已永久遷移,則應使用 301 指定資源的新位置。
  • 411 (Length Required)
    伺服器不接受不含有效內容長度不標頭欄位的要求。
  • 412 (Precondition Failed)
    伺服器未滿足要求者所要求的其中一個前提。
  • 413 (Request Entity Too Large)
    伺服器無法處理要求,因為要求過於龐大,伺服器無法處理。
  • 414 (Requested URI Is Too Long)
    要求的 URI (通常是網址) 過長,伺服器無法處理。
  • 415 (Unsupported Media Type)
    該要求的格式不受要求的網頁支援。
  • 416 (Requested Range Not Satisfiable)
    如果該要求是針對該網頁上無法使用的範則,則伺服器便會傳回此狀態碼。
  • 417 (Expectation Failed)
    伺服器無法滿足預期要求標頭欄位的要求。

5xx (Server Error)
這些狀態碼指出伺服器在嘗試處理要求時發生內部錯誤。這些錯誤可能是伺服器本身的錯誤,而不是要求的錯誤。

  • 500 (Internal Server Error)
    伺服器遇到錯誤,無法完成要求。
  • 501 (Not Implemented)
    伺服器不具備完成要求所需的功能。例如,當伺服器無法識別要求方式時,就會傳回此代碼。
  • 502 (Bad Gateway)
    伺服器用作閘道或 Proxy,接收到來自上游伺服器的無效回應。
  • 503 (Service unavailable)
    伺服器目前暫時無法使用 (因為超載或維護之故而關閉)。一般而言,這是暫時性狀態。
  • 504 (Gateway Timeout)
    伺服器用作閘道或 Proxy,而且未接收到來自上游伺服器的及時要求。
  • 505 (HTTP Version Not Supported)
    伺服器不支援要求中所用的 HTTP 通訊協定版本。
2013-06-04 20:54

[轉載] 電腦開機(異常)BIOS嗶聲判斷

轉載自:電腦不開機 BIOS 嗶 嗶聲 說明教學

電腦開機時,會載入BIOS其電腦周邊相關硬體,而不同硬體周邊異常時,BIOS會利用機殼的喇叭發生嗶聲,利用不同的嗶聲可以判斷目前電腦的異常狀況為何。

但不同主機板,採用不同的BIOS公司與版本,則會有不一樣的聲音。

以下僅作為判斷參考,各電腦可參閱該主機板所提供的說明手冊判斷為準。


BIOS(CMOS)的異常聲音:

AMI BIOS
1短音DRAM復新失敗
1長音3短音音 DRAM錯誤
1長音8短音顯示測試失敗
2短音DRAM同位檢測失敗
3短音基本64K RAM測試失敗
4短音系統時鐘錯誤
5短音CPU處理器錯誤
6短音主機板鍵盤控制器錯誤
7短音CPU中斷錯誤
8短音顯示卡記憶體寫入/讀取錯誤
9短音ROM BIOS檢查碼錯誤
10短音CMOS 關機暫存器寫入/讀取錯誤
11短音快取記憶體故障

Award BIOS
1短音系統啟動正常
2短音CMOS設定錯誤
1長音1短音DRAM或主機板錯誤
1長音2短音顯示錯誤(顯示器或顯示卡)
1長音3短音鍵盤控制器錯誤
1長音9短音主機板Flash RAM或EPROM錯誤(BIOS損壞)
不斷地響(長音)DRAM沒插好或損壞
不斷地響電源,顯示器未和顯示卡連接好
重覆短響電源有問題

Phoenix
1短系統啟動正常
1短1短1短系統開機初始化失敗
1短1短2短主機板錯誤
1短1短3短CMOS或電池失效
1短1短4短ROM BIOS校驗錯誤
1短4短3短EISA時序器錯誤
1短3短1短RAM復新錯誤
3短1短2短主DMA暫存器錯誤
3短1短3短主中斷處理暫存器錯誤
3短2短4短主機板鍵盤控制器錯誤
3短4短2短顯示錯誤(顯示器或顯示卡)
4短2短2短關機錯誤
4短4短1短串列埠錯誤
4短4短2短並列埠錯誤

IBM BIOS
無畫面無聲電源供應器或主機板完全損壞
持續主機板嚴重損壞
短聲系統自我測試,情況正常
2短聲自我測試發現錯誤 ( 錯誤訊息顯示於螢幕上 )
持續短聲電源供應器或主機板損壞
1長1短主機板有錯誤
1長2短顯示卡錯誤
1長3短顯示卡錯誤
3長鍵盤錯誤
2013-05-30 22:21

[PHP] 從網頁執行 SVN 更新

想說寫一個透過網頁就可以執行 SVN 更新的程式,結果並不是我想得那樣簡單,有一些眉角需要注意的說。

先以 Apache 的使用者帳號執行 SVN checkout,這樣 Apache 才有 SVN 的連結權力,才可以透過網頁執行 SVN update

su -s /bin/bash www-data
cd /var/www
svn checkout http://www.xxx.com/svn/my_site 


  1. 在用 PHP 執行 shell 指令前要加上 export LANG=C.UTF-8 的環境宣告,不然 SVN update 時遇到中文會出現 error,Ubuntu 的 Apache 預設是 LANG=C
  2. 接著要為 SVN 補上 --accept theirs-full 的參數,這是當衝突發生時,都以 SVN Server 的檔案版本為主
  3. 最後再加上 2>&1,讓 PHP 可以取得包含錯誤的所有訊息
<?php
putenv('LANG=C.UTF-8');
$result = shell_exec('svn update --accept theirs-full /var/www/my_site 2>&1');
echo nl2br($result);
2013-05-29 23:38

[轉載] (X)HTML Strict 下的嵌套规则

轉載自:(X)HTML Strict 下的嵌套规则

下面是一份在 HTML 4 Strict 和 XHTML 1.0 Strict 下必须遵守的标签嵌套规则,比如你不能在 <a> 里面再嵌入一个 <a> 这样的约定。

说明:
  • 为了方便读者阅读,本文中的标签使用了大写(根据 XHTML 的规则,元素名必须小写,比如 <html> 而不应是 <HTML>
  • 小写的单词表明一组或一系列 HTML 标签
  • 每一项条目(标签)后都跟随一组标签列表,如果没有这个列表,那么表明该条目(标签)内部不允许包含任何标签。这意味着该条目内部只能包含纯文本内容(#PCDATA,见下文)。如果注明 (empty),这意味着该条目内部不允许包含任何形式的内容。对于 flow,inline,block,OBJECT 和 BODY,其内部允许包含的内容在文中会单独给出。
  • #PCDATA 的意思是“parsed character data”,即纯文本内容(不包括任何 HTML 标签,但是转义内容可以存在,比如 &auml;&#228;
  • CDATA 的意思是“character data”,这意味着不包括转义内容的纯文本内容,详细内容可以参考CDATA Confusion
  • excluding ... 意即不得直接或者间接的包含所列的元素



注1. 以上内容基于 [HTML 4.01 Specification] 的 Strict DTDJunChen 翻译自 Allowed nesting of elements in HTML 4 Strict (and XHTML 1.0 Strict)

注2. 对于 XHTML 1.0,基本上一致,不同点如下:
  • 对于 <script><style> 的内容,在 HTML 4 里是 CDATA 而在 XHTML 里是 #PCDATA
  • 在 XHTML 中,<table> 标签后可以紧跟一个 <tr>,而在 HTML 4.01 里,不允许这样,不过 <tbody> 标签又是可以省略的。意思就是说,如果代码中的 <table> 后紧跟 <tr>,对于 HTML 4.01,会隐性的生成一个 <tbody> 标签,而在 XHTML 里面就没有。这会影响到样式表使用 tbody 作为选择器。
2013-05-29 21:23

[轉載] Default style sheet for HTML 4

轉載自:W3C Appendix D. Default style sheet for HTML 4

This appendix is informative, not normative.

This style sheet describes the typical formatting of all HTML 4 ([HTML4]) elements based on extensive research into current UA practice. Developers are encouraged to use it as a default style sheet in their implementations.

The full presentation of some HTML elements cannot be expressed in CSS 2.1, including replaced elements ("img", "object"), scripting elements ("script", "applet"), form control elements, and frame elements.

For other elements, the legacy presentation can be described in CSS but the solution removes the element. For example, the FONT element can be replaced by attaching CSS declarations to other elements (e.g., DIV). Likewise, legacy presentation of presentational attributes (e.g., the "border" attribute on TABLE) can be described in CSS, but the markup in the source document must be changed.

html, address,
blockquote,
body, dd, div,
dl, dt, fieldset, form,
frame, frameset,
h1, h2, h3, h4,
h5, h6, noframes,
ol, p, ul, center,
dir, hr, menu, pre   { display: block; unicode-bidi: embed; }

li              { display: list-item; }

head            { display: none; }

table           { display: table; }

tr              { display: table-row; }

thead           { display: table-header-group; }

tbody           { display: table-row-group; }

tfoot           { display: table-footer-group; }

col             { display: table-column; }

colgroup        { display: table-column-group; }

td, th          { display: table-cell; }

caption         { display: table-caption; }

th              { font-weight: bolder; text-align: center; }

caption         { text-align: center; }

body            { margin: 8px; }

h1              { font-size: 2em; margin: .67em 0; }

h2              { font-size: 1.5em; margin: .75em 0; }

h3              { font-size: 1.17em; margin: .83em 0; }

h4, p,
blockquote, ul,
fieldset, form,
ol, dl, dir,
menu            { margin: 1.12em 0; }

h5              { font-size: .83em; margin: 1.5em 0; }

h6              { font-size: .75em; margin: 1.67em 0; }

h1, h2, h3, h4,
h5, h6, b,
strong          { font-weight: bolder; }

blockquote      { margin-left: 40px; margin-right: 40px; }

i, cite, em,
var, address    { font-style: italic; }

pre, tt, code,
kbd, samp       { font-family: monospace; }

pre             { white-space: pre; }

button, textarea,
input, select   { display: inline-block; }

big             { font-size: 1.17em; }

small, sub, sup { font-size: .83em; }

sub             { vertical-align: sub; }

sup             { vertical-align: super; }

table           { border-spacing: 2px; }

thead, tbody,
tfoot           { vertical-align: middle; }

td, th, tr      { vertical-align: inherit; }

s, strike, del  { text-decoration: line-through; }

hr              { border: 1px inset; }

ol, ul, dir,
menu, dd        { margin-left: 40px; }

ol              { list-style-type: decimal; }

ol ul, ul ol,
ul ul, ol ol    { margin-top: 0; margin-bottom: 0; }

u, ins          { text-decoration: underline; }

br:before       { content: "\A"; white-space: pre-line; }

center          { text-align: center; }

:link, :visited { text-decoration: underline; }

:focus          { outline: thin dotted invert; }


/* Begin bidirectionality settings (do not change) */
BDO[DIR="ltr"]  { direction: ltr; unicode-bidi: bidi-override; }

BDO[DIR="rtl"]  { direction: rtl; unicode-bidi: bidi-override; }

*[DIR="ltr"]    { direction: ltr; unicode-bidi: embed; }

*[DIR="rtl"]    { direction: rtl; unicode-bidi: embed; }

@media print {
    h1            { page-break-before: always; }

    h1, h2, h3,
    h4, h5, h6    { page-break-after: avoid; }

    ul, ol, dl    { page-break-before: avoid; }
}
2013-05-29 20:47

[轉載][PHP] Pattern Modifiers - 正規表示式的修飾符

下面是當前規則表達式裡可用的修飾. 括號內的名字是那些修飾符的內部 PCRE 名字.

i (PCRE_CASELESS)
如果設置了這個修飾符, 則表達式不區分大小寫.

m (PCRE_MULTILINE)
默認的, PCRE 認為目標字符串值是單行字符串 (即使他確實包含多行). 行開始標記 (^) 只匹配字符串的開始部分, 而行結束標記 ($) 只匹配字符串的尾部,或者一個結束行(除非指定 E 修飾符). 這個和 Perl 裡面一樣.

如果設定了這個修飾符, 行開始和行結束結構分別匹配在目標字符串任何新行的當前位置後面的或者以前的, 和每一個開始和結束一樣. 這個等於 Perl 裡面的 /m 修飾符. 如果目標字符串沒有 "n" 字符, 或者模式裡沒有 ^ 或 $ ,這個修飾符不起作用.

s (PCRE_DOTALL)
如果設置這個修飾符, 模式裡的一個"點"將匹配所有字符, 包括換行. 沒有他, 換行將被排除在外. 這個修飾符等同於 Perl 裡面的 /s 修飾符. 一個相反的類型,例如 [^a] 將總是匹配換行字符,而不管這個修飾符的限制.

x (PCRE_EXTENDED)
如果設置這個修飾符, 模式裡面的空格數句將會被全部忽略,除非用轉義符或者一個字符的內部類型,還有所有字符類型外的未轉義的 # 號之間的也被忽略. 這個等同於 Perl 裡面的 /x 修飾符, 這樣可以複雜的模式裡面加入註釋. 注意,只適用於數據字符. 空格字符將不會在指定的模式字符指定順序中出現。

e
如果設置這個修飾符, preg_replace() 將在替換值裡進行正常的涉及到 \ 的替換, 等同於在 PHP 代碼裡面一樣, 然後用於替換搜索到的字符串.

只在 preg_replace() 裡使用這個修飾符; 其它 PCRE 函數忽略他.

A (PCRE_ANCHORED)
如果設置這個修飾符, 模式被強制為錨(anchored), 也就是說, 他將值匹配搜索字符串的開始. 這個效果可以通過恰當的模式結構自身來實現,那是在 Perl 裡面的唯一途徑.

D (PCRE_DOLLAR_ENDONLY)
如果設置這個修飾符,則模式裡的 $ 修飾符將僅匹配目標字符串裡的尾部. 沒有這個修飾符, $ 字符也匹配新行的尾部 (但是不再新行的前面). 如果設置了 m 修飾符則忽略這個修飾符. 在 Perl 裡面沒有類似的.

S
如果一個模式將被使用多次, 使用長些時間分析他來來提高匹配的速度. 如果使用這個修飾符,則進行額外的分析. 目前, 研究模式僅用於非錨模式,沒有一個固定的開始字符.

U (PCRE_UNGREEDY)
這個修飾符翻轉數量的 "greediness" ,使得默認不被 greedy,但是如果你緊跟問號(?),則可以 greedy. 這個和 Perl 不兼容. 這個也可以通過在模式裡面的(?U) 修飾符得到.

X (PCRE_EXTRA)
這個修飾符打開額外的功能,這些和 Perl 不兼容. 任何模式裡面的後面帶字符但沒有特殊意義的反斜槓將引起錯誤, 從而儲備這些聯合用於將來的擴充. 默認的, 在 Perl 裡面, 反斜槓後面有無意義的字符被當成正常的 literal. 目前還沒有其他的控制特徵
2013-05-29 20:38

[轉載][Ubuntu] 檔案系統格式簡介

發信人: tdb.bbs@ptt.cc (tbd), 看板: Linux
標 題: [分享] 檔案系統格式簡介
發信站: 批踢踢實業 (Wed Jul 19 06:22:33 2006)
轉信站: SayYa!ctu-reader!news.nctu!ptt
Origin: sally.csie.ntu.edu.tw

在 MS Winsows 的世界,硬碟可以格式化成 NTFS、FAT32、FAT16 等等。相同的,在 GNU/Linux 底下也是有很多不同的檔案系統格式可以選擇喔。目前在 GNU/Linux 底下,比較常用的有以下這幾種格式 Ext3, ReiserFS, XFS 和 JFS 等數種。當然各種格式都有其憂缺點,所以我們將在下面給與簡單的介紹。

除了 Ext2 以外,其它幾種都是日誌型檔案系統。那什們是日誌系統呢?就是系統會多用一些額外的空間紀錄硬碟的資料狀態,因而在不正常開關機後,不需整個硬碟從新掃描,來恢復系統狀態。


Ext2
此為一非常老舊且不支援日誌系統的檔案系統格式,早期 Linux 玩家還記得吧,每次不正常關機後,重新開機時錯誤檢查很久,且在沒有正常關機下,常常會讓您一次不見很多檔案,現在很少人使用這款檔案系統了!

Ext3
為 Ext2 個改良版,所以 Ext2 可以直接升級成為 Ext3 而不必從新格式化,這也可以讓舊的 Ext2 系統更加穩定。而主要和 Ext2 的差別是,增加了日誌系統 (metadata),所以在不正常開關機時,可以迅速使系統恢復。而因為它舊有的系統相容,和所以很多發行版預設使用 Ext3。而在實際測試上,它的硬碟使用率不佳,大概只有真正空間的 93%會被使用到,並且其它效能測試表現中等。而且它在格式化與建立檔案系統的時間也是其它種類的數十倍。

ReiserFS - http://www.namesys.com
它是採用日誌型系統,為 Hans Reiser 所創使,所以以他的名子命名。技術上使用的是 B*-tree 為基礎的檔案系統,其特色為能很有效率地處理大型檔案到眾多小檔案都可以用很高的效率處理。實務上 ReiserFS 在處理檔案小於 1k 小檔案時,甚至效率可以比 Ext3 快約 10 倍,所以 ReiserFS 專長在處理很多小檔案。而在一般操作上,它的效能表現也有中上的程度。

XFS - http://oss.sgi.com/projects/xfs/
為繪圖工作站公司 SGI 為了高級繪圖處理器系統 IRIX 所設計的檔案格式,也是日誌型系統。而 SGI 亦將其移植到 GNU/Linux 上。而他本來是針對高效能繪圖設計,且為高階工作站使用,所以他在穩定行和效率是無雍致疑的。而在實務上的表現,它的處理各種檔案大小混合的情況下效率最好,並且在一般使用上有不錯的表現。

JFS - http://jfs.sourceforge.net
為全球最大電腦供應商 IBM 為 AIX 系列設計的日誌型檔案系統,技術上使用的是 B+-tree 為基礎的檔案系統,和 ReiserFS 使用 B*-tree 不同。而在穩定度上,IBM AIX 伺服器使用它,而此系列機器很多都在金融上使用,所以穩定是沒話說的。而它最重要的特色是在處理檔案 I/O 的時候,是這些檔案系統裏面最不佔 CPU 資源的,也就是 CPU 使用率最低。但在這樣節省使用 CPU 的情況下,它的效率表現也有中上以上的程度。


雖然 Ext3 效能不好 (在日誌型檔案系統中效率上最糟糕的),那為何那們多人使用?那是因為當時 Ext3 可以直接從 Ext2 升級,而不需要先備份然後格式化後再把檔案拷備回去,所以造成使用人數較多了。但這也是不能怪它,因為它為了和 Ext2 相容,所以有很多的歷史包袱存在。因此我建議新的電腦考慮使用 ReiserFX,XFS 或 JFS。若是以效能為考慮,則可以選擇 ReiserFS 或 XFS。若是系統資源不多,要使用最低的 CPU 使用率,那們可以選擇 JFS,它有著最好的效能資源比。

而網路上有一些檔案系統效能評估,這裡列出來給讀者參考一下

http://www.debian-administration.org/articles/388
http://fsbench.netnation.com/
http://linuxgazette.net/122/TWDT.html
http://linuxgazette.net/102/piszcz.html
2013-05-20 22:41

[PHP] aHash, pHash, dHash 實做

<?php
/**
 * 圖片特徵 Hash 計算
 *
 * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax $
 * @author      jax.hu
 *
 * <code>
 *  //Sample_1
 *  $hashA = ImageHash::pHash('001.jpg');
 *  $hashB = ImageHash::pHash('002.jpg');
 *  if(ImageHash::isSimilar($hashA, $hashB)){
 *
 *  }
 *
 * </code>
 */

class ImageHash {

    /**讀取圖片至指定大小*/
    public static function readImageTo($imagePath, $width, $height){
        if(!$imagePath || !file_exists($imagePath)){ return null; }

        if(class_exists('Imagick')){
            $image = new Imagick($imagePath);
            $image->thumbnailImage($width, $height);
            $img = imagecreatefromstring($image->getImageBlob());
            $image->destroy(); $image = null;

        }else{
            $createFunc = array(
                IMAGETYPE_GIF   =>'imageCreateFromGIF',
                IMAGETYPE_JPEG  =>'imageCreateFromJPEG',
                IMAGETYPE_PNG   =>'imageCreateFromPNG',
                IMAGETYPE_BMP   =>'imageCreateFromBMP',
                IMAGETYPE_WBMP  =>'imageCreateFromWBMP',
                IMAGETYPE_XBM   =>'imageCreateFromXBM',
            );

            $type = exif_imagetype($imagePath);
            if(!array_key_exists($type, $createFunc)){ return null; }

            $func = $createFunc[$type];
            if(!function_exists($func)){ return null; }

            $src = $func($imagePath);
            $img = imageCreateTrueColor($width, $height);
            imageCopyResized(
                $img, $src, 
                0,0,0,0, 
                $width, $height, imagesX($src),imagesY($src)
            );
            imagedestroy($src);
        }

        return $img;
    }



    /**取得灰階數值*/
    public static function getGray($img,$x,$y){
        $col = imagecolorsforindex($img, imagecolorat($img,$x,$y));
        return intval($col['red']*0.3 + $col['green']*0.59 + $col['blue']*0.11);
    }



    /**取得 DCT 常數*/
    private static $_dctConst = null;
    public static function getDctConst(){
        if(self::$_dctConst){ return self::$_dctConst;}

        self::$_dctConst = array();
        for ($dctP=0; $dctP<8; $dctP++) {
            for ($p=0;$p<32;$p++) {
                self::$_dctConst[$dctP][$p] = 
                    cos( ((2*$p + 1)/64) * $dctP * pi() );
            }
        }

        return self::$_dctConst;
    }



    /**圖片檔案 aHash
     * @param string $filePath 檔案位址路徑
     * @return string 圖片 hash 值,失敗則是 null
     * */
    public static function aHash($imagePath){
        $img = self::readImageTo($imagePath, 8, 8);
        if(!$img){ return null; }

        $graySum = 0;
        $grays = array();
        for ($y=0; $y<8; $y++){
            for ($x=0; $x<8; $x++){
                $gray = self::getGray($img,$x,$y);
                $grays[] = $gray;
                $graySum +=  $gray;
            }
        }
        imagedestroy($img);

        /*計算所有像素的灰階平均值*/
        $average = $graySum/64;

        /*計算 hash 值*/
        foreach ($grays as $i => $gray){
            $grays[$i] = ($gray>=$average) ? '1' : '0';
        }

        return join('',$grays);
    }




    /**圖片檔案 pHash
     * @param string $filePath 檔案位址路徑
     * @return string 圖片 hash 值,失敗則是 null
     * */
    public static function pHash($imagePath){
        $img = self::readImageTo($imagePath, 32, 32);
        if(!$img){ return null; }

        /*取得灰階數值 32*32*/
        $grays = array();
        for ($y=0; $y<32; $y++){
            for ($x=0; $x<32; $x++){
                $grays[$y][$x] = self::getGray($img,$x,$y);
            }
        }
        imagedestroy($img);


        /*計算 DCT 8*8*/
        $dctConst = self::getDctConst();
        $dctSum = 0;
        $dcts = array();
        for ($dctY=0; $dctY<8; $dctY++) {
            for ($dctX=0; $dctX<8; $dctX++) {

                $sum = 1;
                for ($y=0;$y<32;$y++) {
                    for ($x=0;$x<32;$x++) {
                        $sum += 
                            $dctConst[$dctY][$y] * 
                            $dctConst[$dctX][$x] * 
                            $grays[$y][$x];
                    }
                }

                /*apply coefficients*/
                $sum *= .25;
                if ($dctY == 0 || $dctX == 0) {
                    $sum *= 1/sqrt(2);
                }

                $dcts[] = $sum;
                $dctSum +=  $sum;
            }
        }

        /*計算所有像素的灰階平均值*/
        $average = $dctSum/64;

        /*計算 hash 值*/
        foreach ($dcts as $i => $dct){
            $dcts[$i] = ($dct>=$average) ? '1' : '0';
        }

        return join('',$dcts);
    }



    /**圖片檔案 dHash
     * @param string $filePath 檔案位址路徑
     * @return string 圖片 hash 值,失敗則是 null
     * */
    public static function dHash($imagePath){
        $img = self::readImageTo($imagePath, 9, 8);
        if(!$img){ return null; }

        $grays = array();
        for ($y=0; $y<8; $y++){
            for ($x=0; $x<9; $x++){
                $grays[$y][$x] = $gray = self::getGray($img,$x,$y);
            }
        }
        imagedestroy($img);

        $bitStr = array();
        for ($y=0; $y<8; $y++){
            for ($x=0; $x<8; $x++){
                $bitStr[] = ($grays[$y][$x] < $grays[$y][$x+1]) ? '1' : '0';
            }
        }

        return join('',$bitStr);
    }



   /**比較兩個 hash 值,是不是相似
    * @param string $aHash A圖片的 hash 值
    * @param string $bHash B圖片的 hash 值
    * @return bool 當圖片相似則回傳 true,否則是 false
    * */
   public static function isSimilar($hashStrA, $hashStrB){
       $aL = strlen($hashStrA); $bL = strlen($hashStrB);
       if ($aL !== $bL){ return false; }

       /*計算兩個 hash 值的漢明距離*/
       $distance = 0;
       for($i=0; $i<$aL; $i++){
           if ($hashStrA{$i} !== $hashStrB{$i}){ $distance++; }
       }

       return ($distance <= 10) ? true : false;
   }

}