聚會時間公告: 11月份聚會為11月15號星期六下午兩點在MocaMona / 講者:shawn Topic: Hello BIOS: EFI, an opensource firmware framework

十一月 23, 2008
» Ubuntu Linux 8.10 使用 Skype 聲音嚴重 Lag 修復

Ubunut 升級到 8.10 後, 使用 Skype 打電話時, 聲音會非常的 Lag, 詢問後, 發現很多人都有此狀況, 主要是設定問題, 不過每個人的設定選項都有點差異, 在此也將我測試成功的設定做個紀錄.

Ubuntu 8.10 的 Skype 聲音 Lag 解法

解法如下步驟:

  1. Ubuntu 8.10 還是會遇到 PulseAudio 和 ALSA 相衝的問題, 解法可見: Ubuntu Gnome 的 Firefox 開影音網站後, 就無法再播放音樂 修復
  2. Skype 音效裝置設定: 選項 -> 音效裝置, 設定成如下:
    • 聲音進來(Sound In): Intel ICH5 (hw:ICH5,0)
    • 聲音出去(Sound Out): pulse
    • 鈴聲(Ringing): pulse

再來打電話就不會 Lag 囉~ :)

註: 第一步驟設定完成後, 記得先登出再登入.

相關網頁

十一月 20, 2008
» Ubuntu / Debian: sudo 出現 unable to resolve host 錯誤解法

於 Linux 環境, 假設這台機器名字叫 dev(機器的 hostname), 每次執行 sudo 就出現這個警告訊息:

sudo: unable to resolve host dev

雖然 sudo 還是可以正常執行, 但是警告訊息每次出來還是有點煩人, 而這只是機器在反解上的問題, 所以就直接從 /etc/hosts 設定, 讓 dev(hostname) 可以解回 127.0.0.1 的 IP 即可.

/etc/hosts 原始內容

$ cat /etc/hosts # 原始 /etc/hosts 設定檔內容

127.0.0.1       localhost

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

解法

於 127.0.0.1 localhost 後面加上主機名稱(hostname) 即可, /etc/hosts 內容修改成如下:

127.0.0.1       localhost dev
# 或 改成下面這兩行
#127.0.0.1       localhost
#127.0.0.1       dev

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

這樣設完後, 使用 sudo 就不會再有那個錯誤訊息囉~ :)

十一月 17, 2008
» Linux: umount 時 出現 "Device is busy" 的解法

當任何目錄有 mount, 然後有程式 使用/掛 在那個目錄上的話, 就沒有辦法 umount 掉, 於 umount 時會出現 Device is busy 的訊息.

要怎麼找出是哪個程式掛在那個目錄上? 然後去把那個程式砍掉呢?

使用 fuser 的指令

那要怎麼找出是哪個程式掛在那個目錄上, 可以使用 fuser - identify processes using files or sockets

假設現在 mount 起來的目錄是 /media/share

  • 查詢: fuser -m /media/share
  • 顯示: /media/share: 25023c

就代表是 process 25023(pid) 有使用到此目錄, 後面 c 代表的意思可參考下述:

  • c: current directory.
  • e: executable being run.
  • f: open file. f is omitted in default display mode.
  • F: open file for writing. F is omitted in default display mode.
  • r: root directory.
  • m: mmap'ed file or shared library.

要把這個資源釋放的話, 可以有下述做法:

  • kill -9 25023 # ps aux | grep 25023 應該就會看到它
  • fuser -m -v -i -k /media/share # 會問你是不是要把 25023 這個 kill 掉, 選 y 就會 kill 掉
    訊息如下:
                  USER      PID   ACCESS COMMAND
    /meida/share: root      25023 ..c..  bash
    Kill process 25023 ? (y/N) y

相關網頁

十一月 3, 2008
» Debian / Ubuntu Linux 的 Ruby on Rails 環境架設

Ruby on Rails 的 環境設定 / 安裝架設, 建制 Rails + Apache + MySQL 環境.

Rails 官方文件

套件說明(名詞需知)

  • Ruby: Ruby Programming Language
  • Ruby on Rails: Web framework
  • Gem: A gem is a packaged Ruby application or library
  • rake: a ruby build program with capabilities similar to make (Ruby Make)

架設步驟

  1. 安裝所需 Package
  2. 系統升級 (rails / gems)
  3. 設定 Apache 或 啟動 rails 的 server
  4. 測試

安裝設定步驟(Debian / Ubuntu 套件安裝)

Ubuntu 所需的 Package
  • apt-get install ruby rails rubygems rake # 安裝 Ruby / Rails 相關套件
  • apt-get install apache2 mysql-server libapache2-mod-ruby # 安裝 Aapche / MySQL
  • apt-get install libdbi-ruby libdbd-mysql-ruby # 安裝 Ruby 與 MySQL 連結所需 Library
  • apt-get install vim-rails # 使用 vim 的話就裝吧~
  • 或 apt-get install ruby rails rubygems rake apache2 mysql-server libapache2-mod-ruby libdbi-ruby libdbd-mysql-ruby vim-rails # 把上面匯整成一行, 一次安裝
Debian 所需的 Package
  • apt-get install ruby rails rubygems rake irb libapache2-mod-ruby libdbi-ruby libdbd-mysql-ruby

設定 Apache module

  • a2enmod rewrite # 開啟 Apache 的 rewrite module

Ubuntu 8.04 問題排除 (gem)

問題: 執行 gem 時, 於 Ubuntu 8.04 出現 "uninitialized constant Gem::GemRunner (NameError)"

解法:

  1. vim /usr/bin/gem
  2. 於 require 'rubygems' 下面加上 require 'rubygems/gem_runner
  3. 如下述:
    require 'rubygems'
    require 'rubygems/gem_runner
  4. 這樣子就能執行 gem 了.

Rails 系統升級 (使用 gem)

 建議安裝完後, 就馬上執行下述升級

  1. gem install -v=2.1.0 rails # 升級成 2.1.0
  2. gem update --system
  3. gem update

Gem 常用指令

  • gem list -r yahoo # search
  • gem cleanup # 清除 cache
  • gem install ruby-openid # 安裝 ruby-openid package
  • gem uninstall ruby-openid # 移除 ruby-openid package
  • gem list --local # 看 local 裝多少 package
  • ls /usr/lib/ruby/gems/1.8/gems/ # Gem 安裝完成的 Package 都放在這邊

測試 Ruby 與 MySQL 連線

  1. vim /tmp/simple.rb
    # simple.rb - simple MySQL script using Ruby DBI module
    require "dbi"
    begin
        # connect to the MySQL server
        dbh = DBI.connect("dbi:Mysql:mysql:localhost", "root", "")

        # get server version string and display it
        row = dbh.select_one("SELECT VERSION()")
        puts "Server version: " + row[0]
    rescue DBI::DatabaseError => e
        puts "An error occurred"
        puts "Error code: #{e.err}"
        puts "Error message: #{e.errstr}"
    ensure
        # disconnect from server
        dbh.disconnect if dbh
    end
  2. 執行 ruby /tmp/simple.rb # 看到 MySQL 版本就正確囉~

測試 rails

  1. cd /var/www # 到 /var/www 來建立專案
  2. rails project_name # 建立一個 Project
  3. mysql> create database test; # 建一個 test 的 DB
  4. cd project_name
  5. rm public/index.html # 不砍掉的話, 預設畫面都會出現這個
  6. vim config/database.yml  # 修改 development: "database: test"
於 Controller 吐資料
  1. script/generate controller Blog # 建立一個 Blog 的 controller
  2. script/server # 啟動 server, 就可以由 http://localhost:3000/ 連線了
  3. # Rails 的 Hello world
  4. vim app/controllers/blog_controller.rb # 加入下述
    def index
        render :text => "Hello world"
    end
  5. 於 http://localhost:3000/ # 就可以看到 Hello world 了.
於 view 吐資料
  1. vim views/blog/index.rhtml # 於 View 吐 Hello world, 記得將上述 controller 的 render :text => "Hello world" 註解掉.
  2. 看到 Hello world  就正確囉~

設定 Apache 存取 Rails 專案

Apache 設定重點是下述內容:

ServerName DOMAIN_NAME
DocumentRoot /var/www/project_name/

RubyRequire apache/ruby-run
# Options +ExecCGI
<Files *.rbx>
    SetHandler ruby-object
    RubyHandler Apache::RubyRun.instance
</Files>

設定使用自己寫的 ruby file (不跑 rails framework), 透過 Apache 測試看看.

  1. cp /tmp/simple.rb /var/www/ruby/simple.rbx # 剛剛上面有個 simple.rb 檔, 直接 copy 過來測試
  2. 於 pache error log(/var/log/apache2/error.log) 若有發現下述錯誤:
    [Sat Oct 04 14:10:36 2008] [error] access to /var/www/ruby/test.rbx failed for (null), reason: file permissions deny server execution
  3. 執行 chmod +x /var/www/ruby/test.rbx 即可.

設定 Rails 專案步驟

  1. vim /etc/apache2/site-enable/test.conf # 建議於 sites-available 建, 再 ln 到 site-enable
    <VirtualHost *>
        ServerAdmin webmaster@localhost

        ServerName DOMAIN_NAME
        DocumentRoot /var/www/project_name/public/
        <Directory /var/www/project_name/public/>
        AddHandler cgi-script .cgi
        AddHandler fastcgi-script .fcgi .fcg .fpl
        Options +ExecCGI
        AllowOverride All
        Order allow,deny
        Allow from all

        RewriteEngine On
        RewriteRule ^$ index.html [QSA]
        RewriteRule ^([^.]+)$ $1.html [QSA]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
        </Directory>

        RubyRequire apache/ruby-run服器    <Files *.rbx>
            SetHandler ruby-object
            RubyHandler Apache::RubyRun.instance
        </Files>

        ErrorLog /var/log/apache2/error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog /var/log/apache2/access.log combined
        ServerSignature On
    </VirtualHost>
  2. 再 /etc/init.d/apache2 restart 即可, 就可以使用 http://DOMAIN_NAME/ 連到囉~ :)

相關網頁

» Linux 查看使用者最後登入時間 (last、lastlog)

Linux 要看使用者最後登入的時間, 直接執行 lastlog 就可以看到.

查詢自己的登入歷史紀錄, 使用 last 查看即可.

若發現有非自己登錄時間的紀錄, 就得要小心囉~ :P

十月 30, 2008
» Linux 工具: 由 IP / Netmask 查看(計算)網路設定範圍: Ipcalc

由 IP 或 IP + Netmask 來計算網路設定的範圍, 除了手動計算外, 應該要找個好工具來用~

ipcalc 只要給它 IP 或 IP + Netmask, 它就會幫你計算出網路範圍:IP 最大HostMax / 最小值HostMin)、Broadcast、Class A/B/C、Private Internet 等.

Debian / Ubuntu Linux 安裝

  • apt-get install ipcalc

使用方法

執行: ipcalc 192.168.0.33 255.255.255.128

Address:   192.168.0.33         11000000.10101000.00000000.0 0100001
Netmask:   255.255.255.128 = 25 11111111.11111111.11111111.1 0000000
Wildcard:  0.0.0.127            00000000.00000000.00000000.0 1111111
=>
Network:   192.168.0.0/25    11000000.10101000.00000000.0 0000000
HostMin:   192.168.0.1         11000000.10101000.00000000.0 0000001
HostMax:   192.168.0.126     11000000.10101000.00000000.0 1111110
Broadcast: 192.168.0.127     11000000.10101000.00000000.0 1111111
Hosts/Net: 126                   Class C, Private Internet

十月 29, 2008
» VIM 開啟檔案時, 自動到上次開啟的行數

VIM 第二次開啟同檔案時, 要如何回到上次開啟的行數?

手動回上次開啟檔案的行數

vim 開啟 file 後:

手動按 `" 即可.

自動回上次開啟檔案的行數

每次開啟檔案, 都回復到上次的行數, 於 .vimrc 加入此段即可:

if has("autocmd")
    autocmd BufRead *.txt set tw=78
    autocmd BufReadPost *
    \ if line("'\"") > 0 && line ("'\"") <= line("$") |
    \   exe "normal g'\"" |
    \ endif
endif

» VIM 設定 alias 詞 對應(縮寫)

VIM 裡面要設定某些詞的縮寫(以便快速輸入), ex: 輸入 市府 要自動轉換成 台北市政府.

設定

於 vim 輸入 (ab 是 abbreviate 的意思)

:ab 市府 台北市政府

若有很多詞的對應, 要於 vim 載入時就自動設定, 就將修改下述內容直接寫入 .vimrc 即可. (下述多列幾個即可)

  • :abbreviate teh the
  • :ab 市府 台北市政府

用 :ab 或 :abbreviate 都可以, 於 .vimrc 把要對應的詞與縮寫都列出來就可以了~ :)

使用

輸入市府, 再按 ESC, 就會自動將 市府 轉換成 台北市政府.

詳細說明

  • /usr/share/vim/vim71/doc/index.txt
  • /usr/share/vim/vim71/doc/usr_24.txt # Debian vim help path

十月 26, 2008
» 設定 Debian/Ubuntu 不允許使用 root ssh 登入

基本上, root 密碼是什麼我也記不起來(都是亂打的), 不過直接於 ssh 擋掉還是較安全點~(Ubuntu / Debian Linux 預設是允許 root ssh login 的)

設定不允許 root ssh 登入

  1. vim /etc/ssh/sshd_config
    找到 PermitRootLogin yes
    改成 PermitRootLogin no
  2. /etc/init.d/ssh restart 即可.

修改 ssh Port

  • 若有要改跑其它 Port, 一樣於 sshd_config 找到 Port, 將 22 改成想要的 Port number 即可.

限定特定帳號登入

若只允許某些帳號登入:

  1. vim /etc/pam.d/sshd
    # account  required     pam_access.so
    拿掉註解
    account required pam_access.so
  2. vim /etc/security/access.conf # 照範例設定即可.

這是另一種方法, 此方法我沒試過(摘錄自: SSH 的一些安全小技巧):

  1. vi /etc/pam.d/sshd
    # 加入此行
    auth required pam_listfile.so item=user sense=allow file=/etc/ssh_users onerr=fail
  2. echo user1 >> /etc/ssh_users # user1 就是你要允許的 user 名稱 (一個帳號一行)

相關網頁

十月 15, 2008
» PHP session 暫存檔過多的注意事項

註: 若您已經將 session 存入 MySQL 或 存入 memcache, 此文對您就沒有幫助囉~ :)

PHP 預設 session 是會存成 file, 預設檔名是 sess_一串亂碼, FreeBSD 是存在 /tmp/var/tmp, Debian 會放在 /var/lib/php5. (以下都以 Debian 為例)

PHP session 設定參數(php.ini)

session 暫存檔過多可能產生的系統狀況

PHP session 暫存檔過多, 可能會造成下述的狀況:

  • 作業系統變的很慢
  • ls /var/lib/php5 (或 ls /tmp) 很慢 (檔案過多)
  • Apache 回應很慢
  • 前端頁面看到一片空白 (作業系統硬的碟滿了也會這樣)

session 暫存檔檢驗

照理說, 除非網站的量太大, 不然一般的量, sess_* 的檔案應該會自動回收清除(Debian 可見 /etc/cron.d/php5 檔, 此檔會去抓過期時間設定, 定時清除)

若沒有特別修改 php.ini, 通常 session 過期時間是 1440 秒(24分鐘), 所以要知道有沒有自動清除, 只要如下:

  1. ls -lt /var/lib/php5
  2. 看最後一個檔案的日期, 離現在時間有沒有超過 24 分鐘. (不過 PHP cron 清除時間是半小時跑一次, 所以可能要多觀察幾分鐘(Debian 是每小時的 09, 39 分跑.))
  3. 有超過就代表沒有執行自動清除動作, 沒超過 24 分鐘, 但檔案還是太多, 下面再說解法.

sess_* 檔案時間存活超過設定時間

這代表沒有執行自動清除的動作, 或者是過期時間有另外設定(暫時不考慮程式另外設定過期時間), 這時後可以去 php.ini 找

; After this number of seconds, stored data will be seen as 'garbage' and
; cleaned up by the garbage collection process.
session.gc_maxlifetime = 1440

; NOTE: If you are using the subdirectory option for storing session files
;       (see session.save_path above), then garbage collection does *not*
;       happen automatically.  You will need to do your own garbage
;       collection through a shell script, cron entry, or some other method.
;       For example, the following script would is the equivalent of
;       setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes):
;          cd /path/to/sessions; find -cmin +24 | xargs rm

這邊有個注意事項, 他有寫說, 如果你有去修改預設的 session.save_path 的話, 系統將不會自動幫你清除過期的暫存檔, 需要自己手動管理回收暫存當的動作.

若有修改 session.save_path 的話, 需要手動管理, 可以試試下面兩種方法:

  • 官方說明檔建議: cd /path/to/sessions; find -cmin +24 | xargs rm # 把這行寫入 cron, 定期清除
  • 另外一種, 可以試著去修改 /etc/cron.d/php5 (不過這個我沒改過, 理論上應該修改就能動才對. XD)

sess_* 檔案時間有定時清除, 但檔案還是過多

這代表你的網站量應該還不小, 或者就是 session.gc_maxlifetime 時間設太長, 最好的解法當然是把 session 寫到 MySQL 或 memcache, 或寫 Cookie 也是好解法(記得加密)~

在此先不考慮 MySQL 和 memcache, 用最快的方法解決有下面幾種解法:

  1. 若是每個 User 進來都會自動產生 session file 的話, 可以考慮將這行加入 cron (時間看要 3 ~ 5分鐘跑一次)
    find /var/lib/php5 -cmin +5 -name "sess_*" -and -size 0 -delete > /dev/null 2>&1 # 清除 超過 5分鐘, 且容量為 0 的檔案
  2. 另一個是修改 php.ini, 預設 session.save_path = /var/lib/php5

    當檔案太多時, 可以考慮切目錄來放那些 session file, 只要修改設定檔, 它就會自動建立目錄, 將檔案放進去囉~

    官方說明: (PHP: Runtime Configuration - Manual)

    session.save_path = "N;MODE;/path"

    There is an optional N argument to this directive that determines the number of directory levels your session files will be spread around in. For example, setting to '5;/tmp'  may end up creating a session file and location like /tmp/4/b/1/e/3/sess_4b1e384ad74619bd212e236e52a5a174If.

    依官方說明設定, 設定範例如下:

    • 設定 session.save_path = '5;/tmp'
    • session file 就會存成 /tmp/4/b/1/e/3/sess_4b1e384ad74619bd212e236e52a5a174If (切五層的目錄來存放)
    • 這樣子就可以暫時先解決檔案過多造成的系統問題囉~

十月 14, 2008
» Ubuntu / Debian 快速修改預設編輯器(nano -> vim)

 Debian / Ubuntu Linux 在 visudo 等動作, 預設是 nano, 要修改預設編輯器可用下述命令:(還是改成 vim 比較熟, nano 連複製都不會, 修改起來很辛苦)

  • update-alternatives --config editor

上述指令會出現如下選項:

   可使用的替換項目
===========================
          1    /bin/ed
*+        2    /bin/nano
          3    /usr/bin/nvi
          4    /usr/bin/mcedit-debian
          5    /usr/bin/vim.basic

按下 enter 來指定預設選項[*],或者輸入選擇的號碼:

這個代表現在預設是 nano, 輸入數字即可設定預設的編輯器 (我是一定選 5 的. XD)

改用 vim 後, 擺脫掉原先黑白的設定畫面~ 果然彩色的設定看起來就不一樣, 改起來也輕鬆多了~ :)

十月 12, 2008
» 安裝 PHP bcompile 做 編譯/加密 原始碼

PHP 的程式在公司在交付程式中, 比較麻煩的就是要如何把原始碼編譯或加密, 免費的方案, 可以考慮用 bcompiler(PHP bytecode Compiler).

不過這套於 PHP5 的物件寫法, 繼承等等, compiler 後執行會有問題, 純 function / include 等等, 是正常的.

PHP bcompiler 安裝步驟

下述環境於 Debian / Ubuntu Linux 安裝

  1. apt-get install libbz2-dev php-pear php5-dev # 因為 pecl compile bcompiler 需要 libbz2(bz2 library)
  2. pecl install channel://pecl.php.net/bcompiler-0.8 # 因為 bcompiler 是 beta, 不是 stable, 所以需要完整路徑.
  3. cat "extension=bcompiler.so" >> /etc/php5/conf.d/bcompile.ini
  4. /etc/init.d/apache2 restart

確認 Module 是否載入

  • php -m | grep bcompiler
  • phpinfo(); # 看是否有載入 bcompiler module

PHP bcompiler 使用

先寫一個編譯程式, 準備把 example.php 編譯成 example.phb (或 xxx.php 都可以), 詳細可見: bcompiler_write_file.

編譯其他程式用的檔案 bcompiler.php
<?php
$fh = fopen("example.phb", "w");
bcompiler_write_header($fh);
bcompiler_write_file($fh, "example.php");
bcompiler_write_footer($fh);
fclose($fh);
?>
hello.php
<?php
function hello()
{
   echo "hello\n";
}
?>
example.php
<?php
include('hello.php');
hello();
?>
  1. 編譯: php bcompiler.php # 會發現有產生出 example.phb (或於 bcompiler.php 有另外取名字的 xxx.php)
  2. 執行: php example.phb # 會秀 hello, 然後此檔案已經是編譯過的 php code.

另外查到 使用 bcompiler 來編譯(加密)您的 PHP 原始碼 這篇的作者, 寫了一個 bencoder 的好用程式, 可以 compile 整個目錄, 詳細可見: BENCODER v1.3 - Encode your PHP script using bcompiler

Bencoder 安裝使用

  1. wget http://bencoder.urdada.net/bencoder
  2. chmod +x ./bencoder
  3. vim bencoder # 修改 php 執行路徑, Debian PHP 存放路徑在 /usr/bin/php
    #!/usr/local/bin/php 改成 #!/usr/bin/php
  4. 執行: ./bencoder -f -o php/Breadcrumb_ben/ -s php/Breadcrumb/ -r
    encoded: php/Breadcrumb_ben//first.php
    encoded: php/Breadcrumb_ben//index.php
    encoded: php/Breadcrumb_ben//bread.php
    encoded: php/Breadcrumb_ben//second.php

十月 5, 2008
» Ubuntu Gnome 的 Firefox 開影音網站後, 就無法再播放音樂 修復

Ubuntu 8.04 的 Gnome, 很奇怪的狀況是, 只要 Firefox 開啟影音網站(ex: YouTube), 之後再開其它的 Mplayer, Audacious 等都沒有聲音.

猜測應該是 PulseAudio 的 Client 都被佔滿了, 不過直接 pulseaudio --check 都看不到東西.

於是 apt 找找, 發現 PulseAudio 有 GUI 的管理程式, 就是 PulseAudio Device Chooser.

Ubuntu 安裝 PulseAudio Device Chooser

  • apt-get install padevchooser

PulseAudio Device Chooser 使用

  1. 執行 padevchooser
  2. 於註程式的圖示, 滑鼠左鍵點選, 選擇 Manager
  3. 選 Client 看是哪個程式佔住資源 -> Properties -> Kill (我於這個步驟常常看到一堆的 Pidgin, 就直接把 Pidgin 重啟即可)
  4. 這樣子應該就可以正常聽到聲音囉~

完美解法(PulseAudio 和 ALSA 相衝 for Ubuntu 8.04)

基本上就是 PulseAudio 和 ALSA 相衝, 下述作法是讓已經在成功運行於PulseAudio的繼續基於PulseAudio, 只支援ALSA的軟體,繼續使用ALSA:

  1. vim /etc/pulse/default.pa # 做下述修改:
  2. #load-module module-alsa-sink => load-module module-alsa-sink device=dmix
  3. load-module module-suspend-on-idle => #load-module module-suspend-on-idle
  4. load-module module-hal-detect => #load-module module-hal-detect
  5. 登出再登入即可.

十月 3, 2008
» 查看 MySQL 語法 詳細執行時間 與 CPU/記憶體使用量: MySQL Query Profiler

MySQL 的 SQL 語法調整主要都是使用 EXPLAIN, 但是這個並沒辦法知道詳細的 Ram(Memory)/CPU 等使用量.

於 MySQL 5.0.37 以上開始支援 MySQL Query Profiler, 可以查詢到此 SQL 會執行多少時間, 並看出 CPU/Memory 使用量, 執行過程中 System lock, Table lock 花多少時間等等.

MySQL Query Profile 詳細介紹可見: Using the New MySQL Query Profiler (2007.04.05 發表)

效能分析主要分下述三種(轉載自上篇):

  • Bottleneck analysis - focuses on answering the questions: What is my database server waiting on; what is a user connection waiting on; what is a piece of SQL code waiting on?
  • Workload analysis - examines the server and who is logged on to determine the resource usage and activity of each.
  • Ratio-based analysis - utilizes a number of rule-of-thumb ratios to gauge performance of a database, user connection, or piece of code.

MySQL Query Profile 使用方法

啟動
  • mysql> set profiling=1; # 此命令於 MySQL 會於 information_schema 的 database 建立一個 PROFILING 的 table 來紀錄.
SQL profiles show
  • mysql> show profiles; # 從啟動之後所有語法及使用時間, 含錯誤語法都會紀錄.
  • ex: (root@localhost) [test]> show profiles; # 注意 Query_ID, 下面執行時間統計等, 都是依 Query_ID 在紀錄
    	+----------+------------+---------------------------+
    	| Query_ID | Duration   | Query                     |
    	+----------+------------+---------------------------+
    	|        1 | 0.00090400 | show profile for query 1  |
    	|        2 | 0.00008700 | select * from users       |
    	|        3 | 0.00183800 | show tables               |
    	|        4 | 0.00027600 | mysql> show profiles      |
    	+----------+------------+---------------------------+
    	
查詢所有花費時間加總
  • mysql> select sum(duration) from information_schema.profiling where query_id=1; # Query ID = 1
    	+---------------+
    	| sum(duration) |
    	+---------------+
    	|      0.000447 |
    	+---------------+
    	
查詢各執行階段花費多少時間
  • mysql> show profile for query 1; # Query ID = 1
    	+--------------------+------------+
    	| Status             | Duration   |
    	+--------------------+------------+
    	| (initialization)   | 0.00006300 |
    	| Opening tables     | 0.00001400 |
    	| System lock        | 0.00000600 |
    	| Table lock         | 0.00001000 |
    	| init               | 0.00002200 |
    	| optimizing         | 0.00001100 |
    	| statistics         | 0.00009300 |
    	| preparing          | 0.00001700 |
    	| executing          | 0.00000700 |
    	| Sending data       | 0.00016800 |
    	| end                | 0.00000700 |
    	| query end          | 0.00000500 |
    	| freeing items      | 0.00001200 |
    	| closing tables     | 0.00000800 |
    	| logging slow query | 0.00000400 |
    	+--------------------+------------+
    	
查詢各執行階段花費的各種資源列表
  • mysql> show profile cpu for query 1; # Query ID = 1
    	+--------------------------------+----------+----------+------------+
    	| Status                         | Duration | CPU_user | CPU_system |
    	+--------------------------------+----------+----------+------------+
    	| (initialization)               | 0.000007 | 0        | 0          |
    	| checking query cache for query | 0.000071 | 0        | 0          |
    	| Opening tables                 | 0.000024 | 0        | 0          |
    	| System lock                    | 0.000014 | 0        | 0          |
    	| Table lock                     | 0.000055 | 0.001    | 0          |
    	| init                           | 0.000036 | 0        | 0          |
    	| optimizing                     | 0.000013 | 0        | 0          |
    	| statistics                     | 0.000021 | 0        | 0          |
    	| preparing                      | 0.00002  | 0        | 0          |
    	| executing                      | 0.00001  | 0        | 0          |
    	| Sending data                   | 0.015072 | 0.011998 | 0          |
    	| end                            | 0.000021 | 0        | 0          |
    	| query end                      | 0.000011 | 0        | 0          |
    	| storing result in query cache  | 0.00001  | 0        | 0          |
    	| freeing items                  | 0.000018 | 0        | 0          |
    	| closing tables                 | 0.000019 | 0        | 0          |
    	| logging slow query             | 0.000009 | 0        | 0          |
    	+--------------------------------+----------+----------+------------+
    	
  • mysql> show profile IPC for query 1;
    	+--------------------------------+----------+---------------+-------------------+
    	| Status                         | Duration | Messages_sent | Messages_received |
    	+--------------------------------+----------+---------------+-------------------+
    	| (initialization)               | 0.000007 |             0 |                 0 |
    	| checking query cache for query | 0.000071 |             0 |                 0 |
    	| Opening tables                 | 0.000024 |             0 |                 0 |
    	| System lock                    | 0.000014 |             0 |                 0 |
    	| Table lock                     | 0.000055 |             0 |                 0 |
    	| init                           | 0.000036 |             0 |                 0 |
    	| optimizing                     | 0.000013 |             0 |                 0 |
    	| statistics                     | 0.000021 |             0 |                 0 |
    	| preparing                      | 0.00002  |             0 |                 0 |
    	| executing                      | 0.00001  |             0 |                 0 |
    	| Sending data                   | 0.015072 |             0 |                 0 |
    	| end                            | 0.000021 |             0 |                 0 |
    	| query end                      | 0.000011 |             0 |                 0 |
    	| storing result in query cache  | 0.00001  |             0 |                 0 |
    	| freeing items                  | 0.000018 |             0 |                 0 |
    	| closing tables                 | 0.000019 |             0 |                 0 |
    	| logging slow query             | 0.000009 |             0 |                 0 |
    	+--------------------------------+----------+---------------+-------------------+
    	
其它屬性列表
  • ALL - displays all information
  • BLOCK IO - displays counts for block input and output operations
  • CONTEXT SWITCHES - displays counts for voluntary and involuntary context switches
  • IPC - displays counts for messages sent and received
  • MEMORY - is not currently implemented
  • PAGE FAULTS - displays counts for major and minor page faults
  • SOURCE - displays the names of functions from the source code, together with the name and line number of the file in which the function occurs
  • SWAPS - displays swap counts
設定 Profiling 存的 Size
  • mysql> show variables where variable_name='profiling_history_size'; # 預設是 15筆
關閉
  • mysql> set profiling=0;

相關文章

十月 2, 2008
» Debian Linux 完整移除套件 / 重新安裝套件 / 鎖定套件版本(apt)

很多人常會發生把某個套件搞爛了, 或者設定檔之類不小心砍掉了, 再來想到的當然是移除再重新安裝 或直接 (apt-get install --reinstall package), 但是怎麼裝, 設定檔就是回不來, 搞爛的資料也還是留著.

這並不是 Debian 的錯, 主要是怕你在移除時, 不小心就將重要資料跟著就砍掉了(ex: MySQL 不小心移除就把 DB 砍掉, 這就很尷尬了.)

此篇文章也有說明發生狀況: 如何在 Debian Etch 系統下完全移除套件與實體目錄?

套件重新安裝

就上述那篇文章的例子, 不小心將 Apache 的設定檔蓋掉/砍掉, 所以打算重新安裝 Apache.

套件移除重新安裝, 和 apt-get install --reinstall apache2 並沒有錯, 只不過問題是, apache2 的 package 裡面並沒有 設定檔. Orz.

由此可見 Package 套件內容:

  • dpkg -L apache2 | grep conf
  • dpkg -L apache2.2-common | grep conf # Debian 設定檔都放在 package_name-common 中
  • 或者上述文章作者的做法是 less /var/lib/dpkg/info/apache2.list 也是可以.
  • 所以要重新取得設定檔, 應該直接
    apt-get install --reinstall apache2.2-common
    即可. (請修改成自己系統的 apache2 版本)

套件完整移除

現在遇到的另一個狀況是, MySQL 被搞爛了, 所以要將全部移除(含資料都要移除), 再重新安裝.

完整移除的步驟:

apt-get remove --purge mysql-server mysql-server-5.0 mysql-common mysql-client mysql-client-5.0

這一行就會將 DB/設定檔都完整移除(--purge 會將所有移除), 不過大多人的問題是, --purge 後面那一串是從哪來的?

可用下述查法:

  • dpkg -l | grep mysql # dpkg -l 會列出此系統安裝的所有 package
  • ls /var/lib/dpkg/info/*mysql*

移除之後, 重新安裝直接 apt-get install 就可以囉~ :)

註: 若只是 Database file 爛了, 只要 apt-get remove --purge mysql-server-5.0, 再重新安裝 mysql-server-5.0 即可.

套件鎖定版本

此段內容詳可見: Apt和dpkg快速參考

假設現在要鎖定 gaim 版本, 不想要 gaim 被升級或降級,有下述兩種做法:

  1. echo "gaim hold" | dpkg --set-selections # 將 gaim 鎖定版本
    dpkg --get-selections "gaim" # 檢查: 出現 gaim hold # 狀態是 hold, 就不能被升級了.
  2. vim /etc/apt/preferences # 內容如下, 把版本編號寫死.
    Package: gaim
    Pin: version 0.58*

套件解除鎖定

  1. echo "gaim install" | dpkg --set-selections
  2. dpkg --get-selections "gaim" # 檢查: 出現 gaim install # 狀態被重置為 install, 就可以繼續升級了

狀態檔案位置

  • hold / install 這些狀態標誌都寫在 /var/lib/dpkg/status 裡, 也可以手動去修改變 hold / install 等狀態.

其它相關

  • apt-get clean #/var/cache/apt/archives 會清掉 *.deb 檔
  • apt-get update # 會更新 /var/lib/apt/lists 的資料

相關網頁

尋找要安裝的檔案是哪個 Package

感謝 Thomas 提供的方法

除了上述已經知道檔案是在哪個 Package, 若是檔案不確定是在哪個 Package 的狀況, 可以用下述方法:

  • dpkg -S apache2.conf (apache2.conf 可以代換成你知道的 keyword 或 filename)
  • 找出來的列表最前面就是 Package name, 重新安裝那個 Package 即可.

九月 18, 2008
» Apache2 載入 Expires 的模組(mod_expires) 與 設定

設定 圖片 / CSS / Javascript 等靜態檔案的過期時間, 可以讓網頁下次 loading 的速度更快(直接從瀏覽器的 cache 拉), 也可以節省 頻寬 和 Apache 吐這些檔案所耗的資源.

首先需要 Enable apache expires module, 方法如下:

  • a2enmod expires # a2enmod, a2dismod - enable or disable an apache2 module
  • 或 cd /etc/apache2/mods-enabled/; ln -s ../mods-available/expires.load

哪些檔案要加入 Expire header 的, 做如下述的設定:

  • 於 .htaccess 加入
    ExpiresActive On
    ExpiresDefault "access plus 4 hours"
    ExpiresByType application/javascript "access plus 1 week"
    ExpiresByType application/x-javascript "access plus 1 week"
    ExpiresByType text/javascript "access plus 1 week"
    ExpiresByType text/css "access plus 1 day"
    ExpiresByType text/html A900
    ExpiresByType text/xml A14400
    ExpiresByType text/plain "access plus 1 hours"
    ExpiresByType image/gif "access plus 1 day"
    ExpiresByType image/jpg "access plus 1 day"
    ExpiresByType image/jpeg "access plus 1 day"
    ExpiresByType image/png "access plus 1 day"
    ExpiresByType image/bmp "access plus 1 day"
    ExpiresByType application/x-shockwave-flash A3600
  • 或 Apache 的設定檔加入
    <IfModule mod_expires.c>                                                                                                          ExpiresActive On
    ExpiresByType application/javascript "access plus 1 week"
    ExpiresByType application/x-javascript "access plus 1 week"
    ExpiresByType text/javascript "access plus 1 week"
    ExpiresByType text/css "access plus 1 day"
    ExpiresByType text/html A900
    ExpiresByType text/xml A14400
    ExpiresByType text/plain "access plus 1 hours"
    ExpiresByType image/gif "access plus 1 day"
    ExpiresByType image/jpg "access plus 1 day"
    ExpiresByType image/jpeg "access plus 1 day"
    ExpiresByType image/png "access plus 1 day"
    ExpiresByType image/bmp "access plus 1 day"
    ExpiresByType application/x-shockwave-flash A3600
    </IfModule>

上述 image/png, application/x-shockwave-flash 等 mime-type, 詳細的可見: /usr/share/doc/apache-common/examples/mime.types.gz (Debian 放在這邊)

測試設定檔是否正確

  1. /usr/sbin/apache2ctl configtest 或 /usr/sbin/apache2ctl -t # 測試 Apache 設定檔有沒有錯誤 (此/usr/sbin/apache2ctl 是 Debian Linux 的路徑)
  2. 看到 Syntax OK, 就可以 /etc/init.d/apache2 reload 囉~ :)

相關網頁

九月 17, 2008
» Debian Linux 安裝 php-java-bridge (tarball 安裝)

雖然 php-java-bridge 有包好的 deb 檔, 但是安裝的東西稍嫌多了點(詳可見: Debian Linux 安裝 php-java-bridge (使用deb安裝)), 使用 tarball 安裝, 可以少安裝蠻多不必要的 Package.(省掉安裝 tomcat 就差蠻多了)

安裝 JDK

  1. Java SE Downloads 找到 Java SE 6 Update 10 RC 的 Linux Platform: self-extracting JDK file (目前最新版)
  2. JDK下載: wget -O jdk-6u10-rc2-bin-b31-linux-i586-05_sep_2008.bin http://www.java.net/download/jdk6/6u10/promoted/b31/binaries/jdk-6u10-rc2-bin-b31-linux-i586-05_sep_2008.bin
  3. chmod +x ./jdk-6u10-rc2-bin-b31-linux-i586-05_sep_2008.bin
  4. ./jdk-6u10-rc2-bin-b31-linux-i586-05_sep_2008.bin # 再輸入 yes 即可
  5. mv jdk1.6.0_10/ /usr/local/
  6. ln -s /usr/local/jdk1.6.0_10/ /usr/local/jdk # 之後升級的話, 只要再重新 ln, 改的設定比較少.

Compile php-java-bridge

  1. export LC_CTYPE=it_CH.ISO_8859-1
  2. export LC_ALL=zh_TW.UTF-8
  3. apt-get install php5-dev re2c make php-pear
  4. tar zxvf php-java-bridge_5.2.2.tar.gz (此檔案從 php-java-bridge 下載 Linux RedHat/Fedora source)
  5. mv php-java-bridge_5.2.2 /usr/local/
  6. cd /usr/local/php-java-bridge_5.2.2
  7. phpize
  8. ./configure --disable-backend --with-java=/usr/local/jdk
  9. make
  10. make install # /usr/lib/php5/20060613+lfs/java.so (php-java-bridge-5.2.2/modules/java.so)
  11. cp -r php-java-bridge-5.2.2/server/META-INF/java /usr/share/php/ # PHP 和 Java 串接的程式 Library

補 /usr/lib/php5/20060613+lfs/JavaBridge.jar 檔

  1. Php/Java Bridge 的 Binary package: php-java-bridge_5.2.2-2, 下載 php-java-bridge_5.2.2_j2ee.zip
  2. wget http://nchc.dl.sourceforge.net/sourceforge/php-java-bridge/php-java-bridge_5.2.2_j2ee.zip
  3. unzip php-java-bridge_5.2.2_j2ee.zip
  4. cp JAVA.STANDALONE/JavaBridge.jar /usr/lib/php5/20060613+lfs/

設定 PHP 的 java.ini 檔

  • vim /etc/php5/conf.d/java.ini
    include_path = ".:/usr/share/php"

    extension=java.so ;; php_java.dll on windows

    [java]
    java.class.path= /usr/lib/php5/20060613+lfs/
    java.library.path = /usr/lib/php5/20060613+lfs/:/usr/local/jdk/bin/
    java.java_home = /usr/local/jdk/bin/
    java.java = /usr/local/jdk/bin/java
    java.log_level = 2

重新啟動

  • /etc/init.d/apache2 restart

測試

  • php -m  | grep java # 會看到 java module 已經載入, 再檢查phpinfo() 看看.
  • vim test.php
    <?php
    $system=new Java('java.lang.System');
    echo "java version".$system->getProperty('java.version')."<BR>";
    echo "java vendor".$system->getProperty('java.vendor')."<BR>";
    echo "OS".$system->getProperty('os.name')."<BR>";
    echo "OS version".$system->getProperty('os.version')."<BR>";
    echo "OS arch".$system->getProperty('os.arch')."<BR>";
    // java.util.Date ex