2011/12/21

Puppet

http://puppetlabs.com/

Puppet 是一個 Client/Server 式的[配置|設定|服務]管理工具,它是用 Ruby 寫的。

簡單講,所有(Linux)機器的配置集中管理在 Puppet Server 上,
Puppet Client 機器連線到 Server 上取得對應的配置,並根據其內容對自己進行設定。

Puppet 並不是 scp 一個設定檔回來然後 Apply。
Puppet Client 使用一套用 Ruby 寫的叫 facter 的工具取得主機基本資訊。
Puppet Server 根據傳來的資訊(ex:IP, OS, RAM, etc.)編譯出相對應的配置檔並回傳。

在 Ubuntu 系統上安裝 Puppet 非常簡單:
sudo apt-get install ruby-full # 安裝 Ruby 環境
sudo apt-get install facter # 安裝 Facter 後可以直接執行 facter 測試一下
sudo apt-get install puppet # Puppet Client 套件 
sudo apt-get install puppetmaster # Puppet Server 套件,Client 不需安裝

# 在 Redhat 環境,Puppet Client 套件叫:puppet
# 在 Redhat 環境,Puppet Server 套件叫:puppet-server

Puppet 看待裝置或服務的哲學跟 UNIX 很像:
每一個裝置、服務對 Puppet 來說,都是一個「資源(Resource)」。



【*.pp】

Puppet 解讀名爲 *.pp 的檔案,然後對不同的 Client 編譯產生不同的配置。
一個簡單的 test.pp 檔案內容如下:
file
{
    "/tmp/test.txt": content => "hello, world";
}
執行:
puppet test.pp
執行結果是在 /tmp 底下產生一個 test.txt 檔,且內容爲「hello, world」。
*.pp 有一套簡單的文法與規則,其中亦有類別跟繼承等,強烈建議閱讀文件瞭解!



【Puppet Client/Server 運作流程】

1」Puppet Client 的 puppetd 程式呼叫 facter 程式,facter 程式會偵測出 Puppet Client 主機的相關資訊,例如 hostname、RAM、Hard Disk、IP 等等。Puppet Client 的 puppetd 再透過“SSL”把這些訊息傳到 Puppet Server。

2」Puppet Server 的 puppetmaster 程式檢查 Puppet Client 送來的資訊,會使用 Puppet Client 的 hostname 來找到 /etc/puppet/manifest 裡面對應的 node 配置,然後分析以及解讀牽涉到的 *.pp 檔或 Puppet 程式碼,Puppet Client 使用 facter 生成的訊息會被當成變數傳入這些 *.pp 檔或 Puppet 程式碼。

3」當 Puppet Server 知道需要處理哪些 *.pp 檔後,就會將它們進行解析,這個 *.pp 檔解析的動作可以看成是程式的編譯(或是直譯?)。解析會分成幾個階段,首先是語法檢查,語法錯誤就會直接報錯了;語法檢查通過,會產生解析的結果(僞代碼檔?),這個結果同樣會透過 SSL 傳送回 Puppet Client。

4」Puppet Client 收到 Puppet Server 的解析結果,然後執行,並且把執行的結果回傳。

5」Puppet Server 把 Puppet Client 的執行結果寫到 log。



【Puppet Client/Server 配置】

Puppet Client 與 Puppet Server 的安裝、設定、配置,最好都使用 root 帳號。

進行 Client/Server 設置前,請務必千萬確定每臺主機的 hostname!
Puppet 的 Client/Server 配置有綁定 hostname 進行驗證。
Puppet 要求符合 FQDN 的 hostname。
請先執行 hostname 並檢查 /etc/hostname 進行確定。
並確認 /etc/hosts 檔案有正確的 hostname 與 IP 配對。

連線與驗證都需要 root 身份來進行。
Puppet Client 與 Server 的系統時間要校正一致,否則認證會出問題!
建議主機使用同樣的 NTP Server 進行時間同步。
請特別注意!

在 Client/Server 環境中,Puppet Server 預設讀取 *.pp 的路徑是:
/etc/puppet/manifests/

可以編寫一個 /etc/puppet/manifests/site.pp 檔測試:
node default
{
    file
    {
        "/tmp/puppet_server.message":
        content => "Hello, Puppet Client!";
    }
}

第一次進行 Client/Server 的配置連線會需要驗證。
先在 Puppet Client 執行:
puppetd --server 伺服器主機名稱 --test
再到 Puppet Server 執行:
puppetca --sign 客戶端主機名稱
最後回到 Puppet Client 執行:
puppetd --server 伺服器主機名稱 --test
此時,Puppet Client 應該會產生一個內容爲「Puppet Manifest」的 /tmp/site.txt 檔。



【Puppet CA 驗証】

Puppet 的驗證文件預設:
Puppet Client:/var/lib/puppet/ssl
Puppet Server:/var/lib/puppet/ssl/ca/

若驗證有問題,在該資料夾下找到相對應的 *.pem,刪除舊的 *.pem 檔後,重新認證。

puppetca --list --all
puppetca --list
puppetca --sign CLIENT_HOSTNAME
puppetca --print CLIENT_HOSTNAME
puppetca --clean CLIENT_HOSTNAME  # 刪除舊的認証
man puppetca



【建議的 /etc/puppet/ 目錄架構】
manifests/
        site.pp
        templates.pp
        nodes.pp

modules/
        {module_name}

modules/user/

services/

clients/

notes/

plugins/

tools/
來源:http://projects.puppetlabs.com/projects/1/wiki/Puppet_Best_Practice



【使用 Puppet Module】

來源:http://docs.puppetlabs.com/guides/modules.html



【使用 Puppet Template】

Puppet Template 可以用來動態產生不同的內容。
應用的情境比較像是同樣的設定檔,但是有些許的設定不盡相同。
例如都是 httpd 服務,不見得所有 Puppet node 的 httpd.conf 都完全相同。

Puppet Template 檔是使用 Ruby 的 ERB Template,並不難寫。
請參考:http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html

Puppet Template 的使用也很簡單:
$value = template("my_template.erb")
my_template.erb 可換成 erb 檔的絕對路徑,或把 erb 檔放到 Puppet 預設會找的路徑。
Red Hat 環境通常是 /var/lib/puppet/templates;
Ubuntu 環境通常是 /etc/puppet/templates。
可以使用 puppet --configprint templatedir 指令確認。
實作的建議是把 erb 檔放到各個 Module 資料夾中。

題外話,可以執行 puppet --configprint all 看看 :-)

來源:http://docs.puppetlabs.com/guides/templating.html



【Puppet 設定檔範例】

https://github.com/ghoneycutt/puppet-generic



【Puppet 名詞解釋】

catalog : A catalog is the totality of resources, files, properties, etc, for a given system.

manifest : A configuration file written in the Puppet language. These files should have the .pp extension.

module : A collection of classes, resource types, files, and templates, organized around a particular purpose.

node (general noun) : An individual server; for the purposes of discussing Puppet, this generally refers to an agent node.

node (Puppet language keyword) : A collection of classes and/or resources to be applied to the agent node whose unique identifier (“certname”) matches the specified node name. Nodes defined in manifests allow inheritance, although this should be used with care due to the behavior of dynamic variable scoping.

provider : A simple implementation of a type; examples of package providers are dpkg and rpm, and examples of user providers are useradd and netinfo. Most often, providers are just Ruby wrappers around shell commands, and they are usually very short and thus easy to create.

templates : templates are ERB files used to generate configuration files for systems and are used in cases where the configuration file is not static but only requires minor changes based on variables that Puppet can provide (such as hostname). See also distributable file.

type : abstract description of a type of resource. Can be implemented as a native type, plug-in type, or defined type.

agent or agent node : An operating system instance managed by Puppet. This can be an operating system running on its own hardware or a virtual image.

來源:http://projects.puppetlabs.com/projects/puppet/wiki/Glossary_Of_Terms



強烈推薦文件:
http://puppet.wikidot.com

Reference:
http://puppet-manifest-share.googlecode.com/files/puppet-1.0.pdf
http://www.comeonsa.com/category/puppet/
http://bitcube.co.uk/content/puppet-errors-explained
http://www.example42.com
http://docs.puppetlabs.com/guides/troubleshooting.html
http://docs.puppetlabs.com/guides/troubleshooting.html
http://blog.akquinet.de/2011/11/23/managing-an-apache-server-with-puppet/

2011/11/23

使用 apt-get 安裝 Redmine

*其實不推薦使用 apt-get 安裝,Redmine 或 Rails 的更新常會造成整個網站垮掉 ....

環境:Ubuntu Server 10.04

【快速安裝】

編輯 apt 來源:
sudo vim /etc/apt/source.list

在檔案最後加上:
deb http://ppa.launchpad.net/ondrej/redmine/ubuntu lucid main
deb-src http://ppa.launchpad.net/ondrej/redmine/ubuntu lucid main

執行:
sudo apt-get install apache2 sqlite3
sudo apt-get install redmine
sudo ln -s /usr/share/redmine/public /var/www/redmine

移除:
sudo apt-get autoremove redmine


【環境設定】

如果需要設定 apt-get 的 proxy:
vim /etc/apt/apt.conf.d/70debconf

加入:
Acquire::http::Proxy "http://YOUR_PROXY_SERVER:YOUR_PROXY_PROT";

先把 Redmine 的 PPA 加入 apt-get sources.list:
sudo add-apt-repository ppa:ondrej/redmine
如果以上步驟有問題,則手動 import GPG Public Key。
下載 Redmine PPA 的 Public Key。
(http://keyserver.ubuntu.com:11371/pks/lookup?op=get&search=0x4F4EA0AAE5267A6C)
把內容復制存成文字檔 redmine.public.key,然後:
sudo apt-key add redmine.public.key

sudo apt-get install python-software-properties
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install apparmor-profiles
sudo apt-get install tasksel
sudo tasksel install lamp-server
sudo aa-complain /usr/sbin/mysqld
sudo apt-get install redmine redmine-mysql subversion
sudo aa-enforce /usr/sbin/mysqld
sudo ln -s /usr/share/redmine/public /var/www/redmine
sudo apt-get install libapache2-mod-passenger

vim /etc/apache2/mods-available/passenger.conf 加入:
PassengerDefaultUser www-data 

vim /etc/apache2/sites-available/redmine
<directory/var/www/redmine>
    RailsBaseURI /redmine
    PassengerResolveSymlinksInDocumentRoot on
</Directory>

sudo chmod a+x /usr/share/redmine/public
sudo a2enmod passenger
sudo a2ensite redmine
sudo /etc/init.d/apache2 restart

檢查 http://localhost/redmine

預設的資料庫名稱:redmine_default
預設的資料庫帳號:redmine
預設的資料庫密碼:安裝過程中使用者設定
預設的資料庫設定:/etc/redmine/default/database.yml
預設檔案儲存路徑:/var/lib/redmine/default/files/
Redmine 安裝路徑:/usr/share/redmine

Reference:
http://zx-1986.blogspot.com/2011/02/redmind.html
https://help.ubuntu.com/community/AppArmor
https://help.ubuntu.com/community/Tasksel
www.redmine.org/projects/redmine/wiki/HowTo_Install_Redmine_in_Ubuntu

2011/11/20

vsftpd

Very Secure FTP Daemon

yum install vsftpd
yum install libdb3-util

/etc/vsftpd/vsftpd.conf

Reference:
http://ubuntuforums.org/showthread.php?t=518293
http://ubuntuforums.org/showthread.php?p=3497743
http://www.linuxfocus.org/English/July2004/article341.shtml

2011/10/26

IEH 20111025

2011/10/25 於 d`Cafe 的聚會筆記

[NoSQL ,MongoDB,Neo4j,Graph Database ...]

[Hadoop]
HDFS:是基礎建設,就像地基,是根本中的根本。
MapReduce:精華!大絕招!
HBase:Google Big Table,base on HDFS 的資料庫。
Cassandra:
Avro:
Hive:
Mahout:
Zookeeper:後面有一堆好用的 MapReduce 函式(工具?)可以呼叫使用
Pig:類似 SQL,是一種資料庫語言
Apache 有 Top Project 跟非 Top Project,
Hadoop 相關的 Sub Project 一堆都是 Top Project。

很棒的 hadoop 演講:
http://www.youtube.com/watch?v=3NAP5rk9Nzs

[Design Patten,無招勝有招,禪 ...]
Strategy
Template Method
Visitor:不同的專家去扣問不同的問題
Mediator
Observer

Reference:
http://neo4j.org/
http://www.mongodb.org/
http://www.readwriteweb.com/cloud/2011/04/5-graph-databases-to-consider.php
http://en.wikipedia.org/wiki/Graph_database
http://hadoop.apache.org/
http://hadoop.apache.org/common/docs/current/mapred_tutorial.html
http://www.jaceju.net/blog/archives/1828
http://coolshell.cn/articles/4844.html

2011/10/24

套件管理員

Python:pip
easy_install 或 setuptools 或 ez_setup.py
使用 easy_install 安裝起來放在 site-packages 的 *.egg 類似 Java 的 *.jar

PHP:Pear

Ruby:RubyGems

Perl:CPAN(Comprehensive Perl Archive Network)

R:CRAN

Node.js:npm

Ubuntu:apt-get、dpkg

Redhat:yum

Mac:homebrew

Reference:
01. http://www.ibm.com/developerworks/cn/linux/l-cppeak3.html

2011/10/23

CoffeeScript

CoffeeScript is just JavaScript!

CoffeeScript 有自己獨特的語法(類似 Python 混搭 Ruby),
編寫好的 CoffeeScript 檔,透過 CoffeeScript Compiler 可以編譯成通用的 Javascript

[使用 apt-get 安裝 CoffeeScript Compiler]
sudo apt-get install python
sudo apt-get install openssh-server libssl-dev
sudo apt-get install python-software-properties
sudo add-apt-repository ppa:chris-lea/node.js
sudo add-apt-repository ppa:gias-kay-lee/coffeescript
sudo apt-get update
sudo apt-get install nodejs
sudo apt-get install coffeescript

[使用 NPM 安裝 CoffeeScript Compiler]

要使用 NPM 需要先安裝好 Node.js 環境,請參考:
http://zx-1986.blogspot.com/2011/10/nodejs.html

然後執行:
sudo npm install -g coffee-script

[編譯安裝 CoffeeScript Compiler]
git clone https://github.com/jashkenas/coffee-script.git
cd coffee-script
sudo bin/cake install

[編譯 .coffee 檔產生 .js 檔]
# Compile a directory tree of .coffee files into a parallel tree of .js, in lib:
coffee -o lib/ -c src/

# Watch a file for changes, and recompile it every time the file is saved:
coffee --watch --compile experimental.coffee

# Concatenate a list of files into a single script:
coffee --join project.js --compile src/*.coffee

# Print out the compiled JS from a one-liner:
coffee -bpe "alert i for i in [0..10]"

# Start the CoffeeScript REPL(read-eval-print loop):
coffee

Reference:
http://upgrade2rails31.com/coffee-script
http://jashkenas.github.com/coffee-script

2011/10/18

Ubuntu 安裝 Sun Java

### Ubuntu 10.10

http://www.oracle.com/technetwork/java/javase/downloads/java-se-jdk-7-download-432154.html

### Ubuntu 11.10

```
sudo add-apt-repository ppa:ferramroberto/java
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install sun-java6-plugin sun-java6-jre sun-java6-plugin sun-java6-jdk sun-java6-bin sun-java6-fonts
sudo update-alternatives --all # 選擇 default 使用 Sun Java
```

http://www.lffl.org/2011/10/ubuntu-1110-oneiric-rimosso-java-dai.html)
http://askubuntu.com/questions/52154/how-do-i-install-the-latest-version-of-sun-java-in-ubuntu-11-10

### Ubunto 12.04

```
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java7-installer
sudo update-java-alternatives -s java-7-oracle
```

http://www.webupd8.org/2012/01/install-oracle-java-jdk-7-in-ubuntu-via.html
http://www.webupd8.org/2011/09/how-to-install-oracle-java-7-jdk-in.html

2011/10/12

Ubuntu 安裝 DHCP Server


dhcp3-server is a dummy package which wraps the real isc-dhcp-server package.
許多舊的關於 Ubuntu DHCP Server 教學文件都是不符合現狀的。
Ubuntu 11.04 內的 dhcp3-server 根本就是幌子!

真正的 DHCP 服務名稱既不是 dhcpd 也不是 dhcp3-server,而是 isc-dhcp-server。

Internet Systems Consortium, Inc. (ISC) is proud to be the producer and distributor of commercial quality Open Source software for the Internet Community and to offer world-class online and professional services based on our software.

sudo apt-get install isc-dhcp-server

設定檔:
/etc/dhcp/dhcp.conf
/etc/defaults/isc-dhcp-server

記錄檔:
/var/lib/dhcp/dhcpd.leases
/var/log/syslog

啟動腳本:
/etc/init.d/isc-dhcp-server

有多張網卡在 DHCP Server 上的需要特別注意:

When a DHCP configured PC boots, it requests its IP address from the DHCP server. It does this by sending a standardized DHCP broadcast request packet to the DHCP server with a source IP address of 255.255.255.255.
If your DHCP server has more than one interface, you have to add a route for this 255.255.255.255 address so that it knows the interface on which to send the reply.


Reference:
http://ubuntuforums.org/showthread.php?t=1754623
http://manpages.ubuntu.com/manpages/natty/man8/dhcp-helper.8.html
http://prefetch.net/articles/iscdhcpd.html
http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch08_:_Configuring_the_DHCP_Server

2011/09/25

Ruby On Rails 環境架設

【使用 apt-get 的安裝流程】

#在 Ubuntu 底下架設 Ruby On Rails + Apache 2 + MySQL 環境

安裝所需套件:
sudo apt-get install ruby rails rubygems rake

sudo apt-get install apache2
sudo apt-get install libapache2-mod-ruby

sudo apt-get install mysql-server 
sudo apt-get install libdbi-ruby libdbd-mysql-ruby

sudo apt-get install vim-rails
sudo apt-get install libfcgi-dev

開啓 Apache rewrite 模組:
sudo a2enmod rewrite
sudo service apache2 restart

RubyGems 指令:
sudo gem list # 列出已安裝套件
sudo gem list -r 套件名稱 # 搜尋套件
sudo gem install 套件名稱 # 安裝套件
sudo gem uninstall 套件名稱 # 移除套件

ERROR: gem update --system is disabled on Debian, because it will overwrite the content of the rubygems Debian package, and might break your Debian system in subtle ways. The Debian-supported way to update rubygems is through apt-get, using Debian official repositories.
If you really know what you are doing, you can still update rubygems by setting the REALLY_GEM_UPDATE_SYSTEM environment variable, but please remember that this is completely unsupported by Debian.

使用 apt-get 或 aptitude 安裝的 RubyGems,Gems 套件預設會放在:
/var/lib/gems/1.8/gems/



【使用 tarball 的安裝流程】

下載 Ruby 原始檔
解壓縮並切換到原始檔資料夾
執行 configure
執行 make
執行 make install

下載 Gem 原始檔
解壓縮並切換到原始檔資料夾
執行 ruby setup.rb

使用 tarball 安裝,Gem 的執行檔預設會是:
/usr/bin/gem1.8

使用 tarball 安裝,Gems 套件預設會放在:
/usr/lib/ruby/gems/1.8



【ruby-full 搭配 Gem tarball】
sudo apt-get install ruby-full

下載 Gem 原始檔
解壓縮並切換到原始檔資料夾
執行 ruby setup.rb

使用 tarball 安裝,Gem 的執行檔預設會是:
/usr/bin/gem1.8

使用 tarball 安裝,Gems 套件預設會放在:
/usr/lib/ruby/gems/1.8



【XDite 推薦的安裝流程】

http://github.com/zx1986/rails-nginx-passenger-ubuntu
http://killtw.k2ds.net/blog/2011/10/29/how-to-install-rails



Reference:
01. https://help.ubuntu.com/community/RubyOnRails
02. http://blog.xdite.net/?p=1754
03. http://blog.xdite.net/?p=1807
04. http://github.com/jnstq/rails-nginx-passenger-ubuntu
05. http://www.cc.ntu.edu.tw/chinese/epaper/20070620_1007.htm
06. http://packages.ubuntu.com/hardy/ruby-full
07. http://blog.longwin.com.tw/2008/11/ruby-on-rails-linux-environment-build-2008/
08. http://ihower.tw/rails3/installation.html

tmux 與 screen

sudo apt-get install tmux

tmux
# 啓動 Tmux

ctrl + b
# 作用鍵,先按作用鍵,再按功能鍵

作用鍵 + c
# 開新的視窗

作用鍵 + n / p
# 切換前一個 / 後一個視窗

作用鍵 + "
# 分割視窗,好用!

作用鍵 + Ctrl + 方向鍵上/下/左/右
# 可以調整當前分割視窗的長寬,好用!

作用鍵 + Space
# 切換分割視窗的佈置

作用鍵 + d
# 將目前的 Tmux Session 丟到背景去

tmux ls
# 列出主機上所有的 Tmux Session

tmux a -t 0
# 將背景的第 0 號 Tmux Session 叫回,a 代表 attach

作用鍵 + ?
# 查詢所有功能



【screen】

screen
# 啓動 screen

ctrl + a
# 作用鍵,先按作用鍵,再按功能鍵

作用鍵 + c
# 開新的視窗

作用鍵 + n / p
# 切換前一個 / 後一個視窗

作用鍵 + k
# 關閉視窗

作用鍵 + d
# 將目前的 Screen Session 丟到背景去

screen -ls
# 顯示背景所有的 Screen Session

screen -r 背景 Session 的名稱
# 將指定的 Screen Session re-Attach 回來

作用鍵 + S
# 水平分割畫面

作用鍵 + |
# 垂直分割畫面

作用鍵 + Tab
# 切換分割畫面

作用鍵 + "
# 將分割畫面接上指定的視窗

p.s.
Screen 的分割畫面很不直覺。
當使用者切出一個新的分割畫面,那個畫面會是整個 blank 的,什麼都沒有。
使用者必須先切到該分割畫面,然後爲該畫面接上指定的 Screen 視窗。
我的需求通常是在分割畫面裡,直接接上一個新的 Screen 視窗。
指令流程:
1] 作用鍵 + S 或 作用鍵 + |
2] 作用鍵 + Tab
3] 作用鍵 + c

Reference:
01. http://clyang.net/blog/2009/09/26/356
02. http://crazylion.wordpress.com/2010/06/04/tmux-2/

2011/09/20

快速架設 NTP Server

yum install ntp tzdata
chkconfig ntpd on
編輯 /etc/ntp.conf:
# 拒絕 IPv4
restrict default kod nomodify notrap nopeer noquery

# 拒絕 IPv6
restrict -6 default kod nomodify notrap nopeer noquery

# 放行指定的主機,一般會填寫上層 NTP Server
restrict your.time.server

# 預設放行本機
restrict 127.0.0.1
restrict -6 ::1

# 放行指定的私有網路主機
restrict 192.168.100.0 mask 255.255.255.0 nomodify

# 設定上層 NTP Server 
# 原本的 [0|1|2].centos.pool.ntp.org 的可以註解掉
server your.time.server

# 預設時間差異分析檔案與暫不用到的 keys 等
driftfile /var/lib/ntp/drift
keys      /etc/ntp/keys
/etc/init.d/ntpd restart
Reference:
http://linux.vbird.org/linux_server/0440ntp.php#server

2011/09/07

在 RHEL 作業系統內使用 LUN

安裝作業系統或對主機進行磁碟管理時,最好先關機,然後把光纖線拔下來,再做其它動作。

multipathd
dev-mapper

/dev/sda
/dev/dm-1
/dev/mpath/mpath1
/dev/mapper/mpath1

2011/06/29

rsyslog

rsyslog + logwatch

Reference:
01. http://wiki.rsyslog.com
02. http://linuxdiary.blogspot.com/2008/10/logwatch.html

關於 log 檔

/var/log
/var/log/dmesg
/var/log/message
/var/log/mail.log
/var/log/apache2/

2011/06/22

設定 Apache 的 Virtual Host

環境:RHEL 6.0
目錄:/etc/httpd

編輯 /etc/httpd/conf/httpd.conf,確定 vhost 模組有載入,然後取消該行注解:
#NameVirtualHost *:80

在該行後面加上:
Include vhosts/*.conf

會是這樣:
NameVirtualHost *:80
Include vhosts/*.conf
基本上是為了要保持其它的 Virtual Hosts 設定都在 NameVirtualHost *:80 之後再載入。

手動在 /etc/httpd 底下建立一個 vhosts 資料夾,
/etc/httpd/vhosts 資料夾內放置各個 Virtual Hosts 的設定。

可以先建立一個以 IP 作為 Domain Name 指向預設 DocumentRoot 的設定。
例如該 httpd 主機的 IP 是 192.168.1.100,預設 DocumentRoot 是 /var/www/html,
則建立:
/etc/httpd/vhosts/192.168.1.100.conf
<VirtualHost *:80>
     ServerName 192.168.1.100
     DocumentRoot /var/www/html
     ErrorLog logs/192.168.1.100-error_log
     CustomLog logs/192.168.1.100-access_log common
</VirtualHost>

假設要設定一個叫 abc.example.com 的 Domain Name 指向 /var/www/html/abc,
則建立:
/etc/httpd/vhosts/abc.example.com.conf
<VirtualHost *:80>
     ServerName abc.example.com
     DocumentRoot /var/www/html/abc
     ErrorLog logs/abc.example.com-error_log
     CustomLog logs/abc.example.com-access_log common
</VirtualHost>

重新啟動 httpd 服務。

Reference:
01. http://freebsd.lab.mlc.edu.tw/apache/VirtualHost.shtml
02. http://phorum.study-area.org/index.php?topic=17120.0
03. http://wiki.ubuntu.org.cn/index.php?title=Apache%E8%99%9A%E6%8B%9F%E4%B8%BB%E6%9C%BA%E6%8C%87%E5%8D%97&variant=zh-tw

2011/05/31

2011/05/05

rpmbuild - 以 Python 2.7 為例

Red Hat Enterprise Linux 的很多東西都很舊,特別是 RHEL 5 系列。
有些新的軟體更新,它不見得會跟著推出新的 rpm 檔。
除了使用 tarball 安裝方法,也可以自己包一個 rpm 檔。

環境:RHEL 5.6

安裝必備套件
yum groupinstall "Development Tools"
yum install rpmdevtools

you should NEVER build an RPM with the root user.
絕對不要使用 root 來打包 rpm!


建立一個專門打包 rpm 的使用者帳號
useradd rpm_maker

切換成該使用者
su - rpm_maker

在 rpm_maker 的家目錄下執行
rpmdev-setuptree     # 會建立 ~/rpmbuild 目錄

下載 Python2.7 原始檔,解壓縮,放置 python-2.7.spec 與原始檔
cd ~
wget  http://www.python.org/ftp/python/2.7.1/Python-2.7.1.tar.bz2
tar  jxvf Python-2.7.1.tar.bz2
cp  ~/Python-2.7.1/Misc/RPM/python-2.7.spec  ~/rpmbuild/SPECS/
mv  Python-2.7.1.tar.bz2  ~/rpmbuild/SOURCES/

補足相關套件
yum install tk-devel tcl-devel expat-devel db4-devel gdbm-devel sqlite-devel

根據指定的 spec 建立 rpm 檔
cd ~/rpmbuild/SPECS/
rpmbuild -ba python-2.7.spec

http://blog.milford.io/2012/01/building-and-installing-python-2-7-rpms-on-centos-5-7/

Reference:
01. https://fedoraproject.org/wiki/How_to_create_an_RPM_package/zh-tw
02. http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/
03. http://www.ibm.com/developerworks/library/l-rpm1/
04. http://villaroad.com/2010/10/rolling-python-2-6-2-on-centos-5-3/
05. http://willsani.com/2011/03/02/centos-5-5-x86_64-install-python-2-7/
06. http://www.joywang.info/?p=112
07. http://serverfault.com/questions/11209/python-3-0-rpms-for-centos-5-rhel-5
08. http://serverfault.com/questions/162217/upgrading-python-on-rhel5
09. http://stackoverflow.com/questions/4149361/on-linux-suse-or-redhat-how-do-i-load-python-2-7

2011/05/02

mod_python 與 mod_wsgi

Reference:
01. http://docs.python.org/howto/webservers.html
02. http://www.modpython.org/python10/
03. http://code.google.com/p/modwsgi/

Django

【安裝 Django】

Ubuntu 底下安裝可以使用:sudo apt-get install python-django
Red Hat 底下安裝可以使用:yum install Django

Ubuntu 預設會把 Django 放在:/usr/local/lib/python2.*/site-packages
Red Hat 預設會把 Django 放在:/usr/lib/python2.*/site-packages

Python won't recognize Django unless it is installed in the "site-packages" directory, so instead we just create a symbolic link to the source code in our home directory.

由上文可知,其實 Django 只要放到正確的 site-packages 下,Python 就可以認到了。
比較麻煩的就是 Python 版本的差異,例如 RHEL 5 預設只有 Python 2.4。
但是 RHEL 5 底下使用 yum 安裝的所有 Python 套件,都會放到 Python 2.4 的 site-packages。
如果你執行的環境是 Python 2.6,那就很頭大了,Python 2.6 底下 import 會少一堆東西。

較好的解決方案是使用:python-virtualenv
跑題了,之後再補充。

使用 Django 原始檔來安裝(想成是 Linux 的 tarball install 吧),自由度會比較高些。

可以下載官方版本來解壓縮,或使用 Subversion 同步一份到自己的家目錄:
cd /var/www
svn co http://code.djangoproject.com/svn/django/trunk/ django_src

使用這個命令取得 Python 的 site-packages 路徑:
#注意 python、python2.4、python2.6 的差別!
python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
python2.4 -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
python2.6 -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"

選擇你的 site-packages 路徑(python2.4 或 python2.6),做一個 symbolic link 到那裡:
ln -s /var/www/django_src/django   你的 site-packages 路徑/django

把 django-admin.py 加到執行路徑(PATH)裡:
sudo cp /var/www/django_src/django/bin/django-admin.py /usr/local/bin

基本上這樣就安裝好 Django 了。
可以進入你的 Python 2.* 環境,測試一下:
>> import django



【建立 Django 專案】

建立一個新的 Django 專案:
cd /var/www/
django-admin.py startproject hello_django

裡面預設的結構是:
__init__.py
manage.py
setting.py
urls.py

再增加幾個資料夾到專案裡面:
cd /var/www
ln -s /var/www/django_src/django/contrib/admin/media  admin_media

cd /var/www/hello_django
mkdir media
mkdir templates

setting.py 裡面可以設置管理資訊與資料庫設定:
ADMINS = (
     ('Your Name', 'your_email@domain.com'),
)

DATABASE_ENGINE = 'mysql'            # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
DATABASE_NAME = 'databaes_name'    # Or path to database file if using sqlite3.
DATABASE_USER = 'user_name'          # Not used with sqlite3.
DATABASE_PASSWORD = 'user_password' # Not used with sqlite3.
DATABASE_HOST = ''                 # Set to empty string for localhost. Not used with sqlite3.
DATABASE_PORT = ''                 # Set to empty string for default. Not used with sqlite3.

TEMPLATE_DIRS = ( 
    "/var/www/hello_django/templates/"    # Absolute path
)

MEDIA_ROOT = '/var/www/hello_django/media/'   # Absolute path to the directory that holds media.

# URL that handles the media served from MEDIA_ROOT. 
# Make sure to use a trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com", "http://example.com/media/" 
MEDIA_URL = 'http://yourdomain.com/media/'

# URL prefix for admin media -- CSS, JavaScript and images. 
# Make sure to use a trailing slash.
# Examples: "http://foo.com/media/", "/media/".
ADMIN_MEDIA_PREFIX = '/admin_media/'

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
)

同步資料庫:
django-admin.py syncdb

編輯 urls.py 檔:
# Uncomment this for admin:
 (r'^admin/', include('django.contrib.admin.urls')),



【設置 Apache】




Reference:
01. http://jeffbaier.com/articles/installing-django-on-an-ubuntu-linux-server/
02. http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/
03. https://help.ubuntu.com/community/Django
04. http://nildamului.blogspot.com/2009/03/django-1.html
05. http://nildamului.blogspot.com/2009/04/django-2.html

CGI

有時候,想要瞭解某些協定、標準,最準確也最快速的方法就是直接去讀它的 RFC 文件。
應該也不用讀太多,每條協定幾乎都有摘要(Abstract)跟它的存在目的(Purpose)。

這篇是我對 Common Gateway Interface 的筆記。
先節錄幾段 Wikipedia 與 RFC 3875 的內容:

" The Common Gateway Interface (CGI) is a standard (RFC 3875: CGI Version 1.1) that defines how web server software can delegate the generation of web pages to a text-based application. Such applications are known as CGI scripts; they can be written in any programming language, although scripting languages are often used. " - Wikipedia

" The Common Gateway Interface (CGI) is a simple interface for running external programs, software or gateways under an information server in a platform-independent manner. Currently, the supported information servers are HTTP servers. " - RFC 3875

" The Common Gateway Interface (CGI) allows an HTTP server and a CGI script to share responsibility for responding to client requests. " - RFC 3875

" The server is responsible for managing connection, data transfer, transport and network issues related to the client request, whereas the CGI script handles the application issues, such as data access and document processing. " - RFC 3875

簡單來說,「HTTP 伺服器」負責管理來自 Client 端的連線、傳輸等網路協定的相關事宜。
「HTTP 伺服器」會呼叫並執行「CGI 程式」,「CGI 程式」負責處理應用程式面的事宜,
例如,Client 端要求的檔案,是否需要經過處理,是否需要存取資料庫等等。

「CGI 程式」允許使用許多不同的程式語言來實作。
但那麼多種程式語言,「HTTP 伺服器」如果呼叫某種語言的「CGI 程式」,
就得有對應該程式語言的呼叫介面,那「HTTP 伺服器」的開發人員會瘋掉。

所以「CGI」就出現了。

「CGI」規範了「HTTP 伺服器」與「CGI 程式」間的連接。
「CGI」是包在「HTTP 伺服器」裡面的。

如果想要用某種程式語言撰寫「CGI 程式」供「HTTP 伺服器」叫用,
該程式語言必須有遵守「CGI」規範的接口。
在實際的例子中,這些接口就是 Apache 伺服器上的:
mod_php、mod_python、mod_ruby、mod_perl、mod_mono 等等。

「HTTP 伺服器」只要提供一套「CGI」規範給各種程式語言遵循即可,
而各種程式語言如何去實作「CGI」規範的接口,就是它自己的事了。

通常,Client 端送來的參數跟 URL 其實就是在呼叫要執行的「CGI 程式」了。

我畫了一張簡圖,希望大家指正:




【WSGI】

" WSGI (Web Server Gateway Interface) was created as a low-level interface between web servers and web applications or frameworks to promote common ground for portable web application development. WSGI is based on the existing CGI standard. " - Wikipedia

Python 的 WSGI,應該是欲取代掉 mod_python 的角色。
同一種程式語言,但該語言的多種框架如果對應到多種不同的「HTTP 伺服器」,還是很累人。
早先 Python 爲了迎合 CGI、FastCGI、mod_python 等不同規範,吃了不少苦頭。

但實際應用上,WSGI 沒那麼簡單。
WSGI 還可以起到 Middleware 的作用,可以看成是伺服器 response 內容的 filter。

這篇寫得很精彩:http://blog.ez2learn.com/2010/01/27/introduction-to-wsgi/



【Rack】

" Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call. " - Wikipedia

在 Ruby 方面,受 WSGI 的啓發產生了 Rack。

" Rack 的規範非常簡單:就是需要一個 Call method 吃進一個 Enviroment 參數,然後回傳一個 Array,Array 裡面包含 status,header,body。" - XDite

請參考:http://blog.xdite.net/?p=1557

Reference:
01. http://en.wikipedia.org/wiki/Common_Gateway_Interface
02. http://tools.ietf.org/html/rfc3875
03. http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface

2011/04/11

phpMyAdmin

【Red Hat Enterprise Linux】
yum install phpmyadmin
cp  /usr/share/phpmyadmin/config.sample.inc.php  /usr/share/phpmyadmin/config.inc.php
cat  /etc/httpd/conf.d/phpmyadmin.conf

【Ubuntu】
apt-get install phpmyadmin

【tarball】

新版的 phpMyAdmin 需要 PHP 5.2 以上的環境。

大致流程是:
1. 安裝 HTTP Server 與 PHP 環境
2. 下載最新版的 phpMyAdmin
3. 解壓縮到 HTTP Server 的 Document Root
4. 編輯 phpMyAdmin 的 config.inc.php 檔
5. 連線 http://localhost/phpmyadmin 測試

# using Ubuntu + Apache + MySQL
sudo apt-get install apache2 mysql-server php5-mysql
cd /var/www
wget URL_of_phpMyAdmin_Source_Package.zip (http://www.phpmyadmin.net/home_page/downloads.php)
unzip phpMyAdmin*.zip
mv phpMyAdmin* phpmyadmin
cd /var/www/phpmyadmin
cp config.sample.inc.php config.inc.php
vim config.inc.php

簡單的 config.inc.php 設定
$cfg['blowfish_secret'] = '123'; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */

/*
 * Servers configuration
 */
$i = 0; 

/*
 * First server
 */
$i++;
/* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'cookie';
/* Server parameters */
$cfg['Servers'][$i]['host'] = 'localhost';  // MySQL 主機的位址
$cfg['Servers'][$i]['connect_type'] = 'tcp';
$cfg['Servers'][$i]['compress'] = false;
/* Select mysqli if your server has it */
$cfg['Servers'][$i]['extension'] = 'mysql';
$cfg['Servers'][$i]['AllowNoPassword'] = false;

Reference:
01. http://wiki.phpmyadmin.net/pma/Quick_Install
02. http://wiki.phpmyadmin.net/pma/Config

2011/04/08

使用 Kickstart 自動安裝 RHEL

The Red Hat Kickstart installation method is used primarily (but not exclusively) by the Red Hat Enterprise Linux operating system to automatically perform unattended operating system installation and configuration.

【製作 Kickstart 光碟】

事前准備:
Red Hat Enterprise Linux 安裝光碟
一些編寫好的 kickstart 檔案(例如:rhel5.cfg)
一台可以燒錄 ISO 檔的 Linux 主機

首先,把 Red Hat Enterprise Linux 安裝光碟放到 Linux 主機。
到裏面找到 /images 這個資料夾,復制裏面的 boot.iso 到 Linux 主機上。

使用以下指令把 boot.iso 挂載到 /opt/boot_iso:
sudo su -
mkdir -p /opt/boot_iso
mount -o loop -t iso9660 boot.iso /opt/boot_iso

復制 /opt/boot_iso 裏面的 isolinux 資料夾:
cd /opt/boot_iso
cp -R isolinux /opt/

復制編寫好的 kickstart 檔案到 isolinux 資料夾:
cp rhel5.cfg /opt/isolinux

將 isolinux 資料夾制作成可開機的 boot.iso:
cd /opt/isolinux
mkisofs -r -T -J -V "kickstart" -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -v -o /opt/kickstart.iso .

[注意!]
RHEL 5 跟 RHEL 6 的光碟檢查碼與架構都不一樣!
每個不同的版號都得使用不同版本的 boot.iso 來制作 kickstart 光碟!
簡單說:
RHEL 5.5 得使用它自己的 boot.iso 制作自己的 kickstart 光碟。
RHEL 5.6 得使用它自己的 boot.iso 制作自己的 kickstart 光碟。
雖然它們的 rhel5.cfg 檔案可以共用。
這跟光碟的檢查碼有關系。

將產生的 /opt/kickstart.iso 檔案燒錄成光碟。

使用該光碟開機後,在安裝的 shell prompt 中輸入指定的 kickstart 檔名:
> linux ks=cdrom://rhel5.cfg

當開機檔案與指定的 kickstart 讀取到記憶體之後,開始安裝時,可能會碰到以下訊息:
The Red Hat Enterprise Linux CD was not found in any of your CDROM drives.
Please insert the Red Hat Enterprise Linux CD and press OK to retry.

此時,把 kickstart 光碟拿出來,放入原始的 RHEL 安裝光碟,壓 Enter。
順利的話,RHEL 就會照指定的 kickstart 檔的設定安裝了。

Reference:
01. http://en.wikipedia.org/wiki/Kickstart_(Linux)
02. http://junktrap.naihl.net/doku.php?id=redhat:kickstartbootcd

2011/03/29

autofs

使用 autofs 工具來挂載 NFS 檔案系統。

服務的執行腳本:
/etc/init.d/autofs  [ start | stop | reload ]

auto.master 預設在 /etc 下,它記錄了 mapping files 的位置。
如果說,mount points 的對照是地圖,auto.master 不是地圖,它記錄的是地圖的位置。

/etc/auto.master
/misc    /etc/auto.misc    --timeout 60
例如,要在 /misc 資料夾內做 auto mount,則 autofs 啟動時會全權控制該資料夾。
并且根據它對應的地圖檔 /etc/auto.misc 的內容,自動挂載磁區。
--timeout 則是設定該 auto mount 根目錄(/misc)下所有 mount point 的卸載時間。
超過 60 秒沒有對該磁區存取,就自動 umount 了。

根據 /etc/auto.master 的地圖指引,還需要編寫一個真正的 auto mount points 對映檔。
/etc/auto.misc
the_directory_name_in_misc    -OPTIONS    remote_host:/path
第一個欄位記錄的是 auto mount point 的名稱,假設叫 foo。
則該 autofs 的根目錄(/misc)不能有名稱為 foo 的資料夾。
基本上,/misc 會保持空的,autofs 會自動在挂載時建立 mount point。

第二個欄位就是挂載的設定選項了,使用逗號","分隔,記得最前面要加一個 -
例如:-default,rw

最後一個欄位是遠端主機 NFS export 出來的挂載點。

2011/03/25

架設 Yum 伺服器

#!/bin/bash

# RPMForge

cd /yum/rpmforge5/i386/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./rpmforge http://apt.sw.be/redhat/el5/en/i386/rpmforge/RPMS/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./dag http://apt.sw.be/redhat/el5/en/i386/dag/RPMS/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./extras http://apt.sw.be/redhat/el5/en/i386/extras/RPMS/

cd /yum/rpmforge5/x86_64/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./rpmforge http://apt.sw.be/redhat/el5/en/x86_64/rpmforge/RPMS/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./dag http://apt.sw.be/redhat/el5/en/x86_64/dag/RPMS/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./extras http://apt.sw.be/redhat/el5/en/x86_64/extras/RPMS/

cd /yum/rpmforge6/i386/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./rpmforge http://apt.sw.be/redhat/el6/en/i386/rpmforge/RPMS/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./dag http://apt.sw.be/redhat/el6/en/i386/dag/RPMS/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./extras http://apt.sw.be/redhat/el6/en/i386/extras/RPMS/

cd /yum/rpmforge6/x86_64/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./rpmforge http://apt.sw.be/redhat/el6/en/x86_64/rpmforge/RPMS/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./dag http://apt.sw.be/redhat/el6/en/x86_64/dag/RPMS/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./extras http://apt.sw.be/redhat/el6/en/x86_64/extras/RPMS/

# EPEL

cd /yum/epel5/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./i386 http://download.fedora.redhat.com/pub/epel/5/i386/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./i386/debug http://download.fedora.redhat.com/pub/epel/5/i386/debug/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./x86_64 http://download.fedora.redhat.com/pub/epel/5/x86_64/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./x86_64/debug http://download.fedora.redhat.com/pub/epel/5/x86_64/debug/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./i386 http://download.fedora.redha t.com/pub/epel/testing/5/i386/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./x86_64 http://download.fedora.red hat.com/pub/epel/testing/5/x86_64/

cd /yum/epel6/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./i386 http://download.fedora.redhat.com/pub/epel/6/i386/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./i386/debug http://download.fedora.redhat.com/pub/epel/6/i386/debug/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./x86_64 http://download.fedora.redhat.com/pub/epel/6/x86_64/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./x86_64/debug http://download.fedora.redhat.com/pub/epel/6/x86_64/debug/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./i386 http://download.fedora.redhat.com/pub/epel/testing/6/i386/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./x86_64 http://download.fedora.redhat.com/pub/epel/testing/6/x86_64/

# Remi

cd /yum/remi5/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./i386 http://rpms.famillecollet.com/enterprise/5/remi/i386/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./i386 http://rpms.famillecollet.com/enterprise/5/olds/i386/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./x86_64 http://rpms.famillecollet.com/enterprise/5/remi/x86_64/ 
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./x86_64 http://rpms.famillecollet.com/enterprise/5/olds/x86_64/

cd /yum/remi6/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./i386 http://rpms.famillecollet.com/enterprise/6/remi/i386/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./i386 http://rpms.famillecollet.com/enterprise/6/olds/i386/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./x86_64 http://rpms.famillecollet.com/enterprise/6/remi/x86_64/ 
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./x86_64 http://rpms.famillecollet.com/enterprise/6/olds/x86_64/

# CentOS

cd /yum/centos5
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./i386 http://mirror.centos.org/centos/5/os/i386/CentOS/
wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./x86_64 http://mirror.centos.org/centos/5/os/x86_64/CentOS/

#cd /yum/centos6/
#wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./i386 http://mirror.centos.org/centos/6/os/i386/
#wget --accept=rpm --level=1 --recursive --no-parent -N --no-directories --directory-prefix=./x86_64 http://mirror.centos.org/centos/6/os/x86_64/

2011/03/22

wget

GNU Wget is a free software package for retrieving files using HTTP, HTTPS and FTP, the most widely-used Internet protocols. It is a non-interactive commandline tool, so it may easily be called from scripts, cron jobs, terminals without X-Windows support, etc.

wget 是開放原始碼的下載工具,它可以透過 HTTP、HTTPS、FTP 協議擷取指定的檔案。
wget 并不是一個可以互動的指令工具,不過它可以輕易地套在 shell script 中。
wget 不需要圖形環境支援,只要有文字終端機就可以使用了。

可以把 wget 想成平常在網頁上點了一個連結的效果,不同的地方在於:
當你點了一個連結,瀏覽器會把你導向該連結的網頁,并把該網頁畫出來,呈現給你看;
當你給定一個連結給 wget,wget 會幫你把該連結的檔案給抓下來,放到你的硬碟。

例如:
wget www.google.com

wget 會把 Google 的首頁抓下來,你會得到一個 Google 首頁的 index.html 檔案。
你可能會疑惑,Google 首頁那些圖片呢?那些首頁引用的 Javascript 檔呢?

wget 預設只針對使用者給的 URL 做處理。
至于該 URL 的內容所含的其他 URL 資源,wget 不會去抽取它們。

不過 wget 有許多參數跟選項,適當地調整跟啟動它們,就會有非常驚人的能力。
它們就像是 wget 的魔法按鈕,按下去就會達成你的願望。
它們很多,很繁復。

例如:
wget -r www.google.com

r 就是 recursive 的意思,遞迴處理。
這個動作就是網路上經常聽到“砍站”,意思就是把整個網站完整的復制下來。

這個選項要非常小心使用!
通常會使用 --level 參數限制遞迴的層數,
否則網站的 URL 如果連到另一個網站,另一個網站又連到 ...
搞不好你會把整個 Internet 抓下來 :-)

不過 wget 在做 recursive 下載時,會嚴謹恪守 Robot Exclusion 的規範。
robots.txt 內規定不能動、不能挖取的檔案,wget 是不會去觸犯的。
可以嘗試一下,看看效果:
wget -r http://en.wikipedia.org



[1]

目標:把 OEC SPACE(http://www.hsiu28.net)網站整個抓到 /tmp 資料夾下。

指令:
wget --mirror --wait=2 --html-extension --convert-links --directory-prefix=/tmp http://www.hsiu28.net
--mirror:映射網站,遞迴網站的所有連結,搜尋必要之檔案。
--wait=2:等待兩秒才送下一個 request,可用 --random-wait 取代。
--html-extension:在 .cgi 或 .php 或 .jsp 等等的副檔名最後再加上 .html。
--covert-links:把網頁上所有絕對位置連結轉成本地端的相對位置連結。
--directory-prefix=路徑:本地端儲存的路徑,可簡寫成“-P 路徑”。

--mirror 其實是好幾個選項的合體(-r -N -l inf -nr):
-r,--recursive:遞迴下載。
-l,--level:遞迴下載的層數,inf 表示無限。
-N,--timestamping:檢查遠端文件的時間是否較本地端的新,再決定是否下載。
-nr,--dont-remove-listing:保留 .listing 檔案。

[2]

目標:續傳一個大檔案。

指令:
wget -c http://URL/the_big_file
-c,--continue:檔案續傳

[3]

目標:將 http://apt.sw.be/redhat/ 的 rpm 通通鏡像下來。

指令:
wget --mirror --reject=gif,bmp,html --accept=rpm,RPM http://apt.sw.be/redhat/
-A,--accept=副檔名:要下載的檔案類型
-R,--reject=副檔名:不要下載的檔案類型

[4]

目標:使用 wildcard 遮罩(*.rpm)下載 FTP 上的一大堆 rpm 檔案。

注意,此處并沒有使用 --mirror,而是使用通用字元告訴 wget 下載符合規則的檔案。
這樣的用法,在 wget 中,僅限於 FTP 協議才可以。

指令:
# FTP ONLY!
wget ftp://apt.sw.be/mirrors/redhat/rhel/beta/6/i386/os/Packages/*.rpm

[5]

目標:透過 HTTP 下載 apt.sw.be 上 EPEL 5 i386 所有的 .rpm 檔案。

wget 并沒有辦法透過 HTTP 使用 wildcard 遮罩下載檔案。
在 HTTP 中,必須指定檔名,wget 才有辦法處理。
要達成類似 wildcard 的效果,必須繞個彎想法子,
所以改成指定 wget 下載這層目錄下副檔名為 rpm 的檔案,
不過,前提是該 Web Server 必須開放該層目錄的 file list,wget 才有辦法解析。

指令:
wget --accept=rpm --level=1 --recursive --no-parent -N http://apt.sw.be/redhat/el5/en/i386/rpmforge/RPMS/
-np,--no-parent:不要追溯回父目錄

Reference:
01. http://blog.dayuer.com/freebsd-tooltips/wget_help
02. http://redhat.ecenter.idv.tw/bbs/showthread.php?threadid=39222
03. http://ubuntuforums.org/showthread.php?t=638362

curl

cURL

表單範例:

GET method 互動
curl "www.hostname.com/when/do.cgi?who=me&press=OK"

POST method 互動
curl -d "who=me&press=%20OK%20" www.hostname.com/when/do.cgi

2011/03/15

Gitorious

Setup Gitorious in Ubuntu
Setup Gitorious in RHEL 5.x

https://github.com/zx1986/Gitorious-Setup

舊筆記怎麽被刪掉了!?
該死!

2011/02/08

Javascript Frameworks

【jQuery】

jQuery 雖然稱爲 Javascript 的「Framework」,但它其實更像一套「Toolkit」。
而且是一套非常強的 Javascript Toolkit,族繁不及備載的外掛、五花八門的特效等等。

jQuery 包好了許多函式,叫用這些函式,可以很快速地完成從前需要花許多功夫的效果。
在 jQuery 這個自成體系的工具包裡,DOM 的操作變得簡單、易用、快速。
除了這些,jQuery 也提供了它自成一系的 Ajax 操作,還有各種動畫特效等。

撰寫 Javascript 很多時候都是在處理或控制 DOM 元素。
修改某個 div 裡的內容、刪除某列 tr、爲某個 id 的元素加上指定的 class ...
許多想得到的 DOM 操作,使用 jQuery 的話,可以省下不少程式碼數量。

引入 jQuery:


在 HTML 文件中引入 jQuery 函式庫之後,就可以透過「jQuery」或其別名「$」使用它。
例如很多時候,我們希望使用者在整個 DOM 文件建構好之後,再來執行 Javascript 的直譯動作,
傳統的 Javascript 會這樣控制:
window.onReady = function()
{
    // your codes
}
在 jQuery 裡,則是這樣作:
jQuery(document).ready(function()
{
    // your codes
});
或是
$(document).ready(function()
{
    // your codes
});
另一種比較嚴謹的做法是:
(function($){
    $(document).ready(function(){
        // your codes
    });
}(jQuery));
最後一種寫法直接定義並執行一個匿名函式 function($),
function($) 中的 $ 指的是要傳入這個匿名函式的參數,
而這個傳入的參數,寫在最後一行的掛號裡,即 (jQuery)。
這樣的作法可以避免跟其他也使用 $ 作爲名稱空間 prefix 的框架衝突,
如此一來,在這個匿名函式 function($) 的範圍內,$ 確定僅是 jQuery。

如果有用 Javascript 做過 DOM 元素控制(寫過 Javascript 幾乎都做過),
那麼改用 jQuery 來作同樣事情時,一定會驚豔於 jQuery 的簡便、易用。
例如選擇 DOM 裡面某個 id 的元素,單純的 Javascript 寫法是:
var a = document.getElementById("some_id");
使用 jQuery 則可以這樣寫:
var a = $("#some_id");





【Mootools】

MooTools 是一個用 JavaScript 原本應有的方式來寫 JavaScript 的框架(Framework)。
其立意是實作一個跟 JavaScript 非常相似的 API 並且針對各個部分加以強化。

引入 Mootools:



【YUI】

YUI 使用:




【ExtJS】

ExtJS 使用:



【RightJS】

RightJS 使用:






Roadmap

http://docs.jquery.com/JQuery_1.5_Roadmap
http://www.sencha.com/products/js/roadmap.php
http://yuilibrary.com/projects/yui3/roadmap
http://rightjs.org/blog



Reference:
01. http://www.ibm.com/developerworks/cn/web/wa-jsframeworks
02. http://www.ibm.com/developerworks/web/library/wa-aj-extjs
03. http://clay0529.blogspot.com/2010/02/yui-3.html
04. http://yufei34514.blog.163.com/blog/static/407836552009114154340
05. http://www.ajaxray.com/blog/2009/04/05/extjs-quick-start-guide-for-jquery-developers-javascript-howto
06. http://jqueryvsmootools.com

2011/02/07

Javascript


初次接觸 Javascript 時,沒有認真把它當成一門程式語言來對待。
我想,這應該也是許多人的通病。

它的名字真的害人不淺,如果本身有以貌取人的毛病,那慘了:
「輕量級的 Java 語言嘛,Java 式的 Script 嘛,對吧?」

千 萬 別 這 麼 想 !

Javascript 跟 Java 沒有關係!
Javascript 絕對不只是 Script 那麼單純!

最近要做一份 Javascript Frameworks 的文件。
我發現,如果要寫一份關於 Javascript Frameworks 的文件,
沒有先弄清楚 Javascript,似乎不大對。

但是要全部記錄在同一篇,也太自不量力了。
Javascript Frameworks 每一套幾乎都可以各自出一本書了。
Javascript 當然更不用說了,市面上 Javascript 的書成百上千。

我寫這篇文章,記錄跟整理我對 Javascript 的瞭解,幫自己作個備忘。
內容會持續更新與修正,希望大家指正與教導!




資訊技術的世界,一個十年大概就像社會中一個世紀那麼遙遠。
Javascript 的出現,對 2010 的我們來說,就像是曾祖輩的事情。
雖然 Javascript 第一次出現只不過是在 1995 年而已。

有些古老的歷史對現在新接觸 Javascript 的人來說,似乎不是那麼重要了。
因爲瀏覽器大戰實在太遙遠了,就像是第一次世界大戰那樣。
但 Javascript 的由來、爲何而存在、是怎麼樣的一個存在,我想都應該值得搞清楚。



故事的開始,要從網際網路(Internet)說起。

Internet 的出現,最初是美國在學術與軍事應用上的考量。
從學術方面簡單說,就是爲了讓各地學術單位、研究人員可以交流分享成果。

那該怎麼樣來呈現 Internet 上的資訊呢?
又該用什麼樣的工具來瀏覽 Internet 上的資訊呢?
於是,HTML 和瀏覽器粉末登場。

從學術分享的目的出發,HTML 最初設計出來就是爲了呈現文字。
因爲科學研究報告的許多內容就是文字,或者再加上些圖片。

HTML 完整的稱呼是 HyperText Markup Language。

Markup Language 是標記語言,就是用規定的格式將某些內容標記起來。
例如,買手搖式飲料的時候,老闆會在杯子上面寫好哪杯是珍奶,哪杯是綠茶。
老闆「寫上去」那個動作就是「標記」的意思。

Hyper 在英文中則有過度的、超過的等意思。
爲什麼叫它過度的文字,或者說它是超越文字的文字?
因爲 HTML 除了可以標記出內容的結構:哪邊是段落、哪邊是標題、哪些又是表格;
HTML 還可以標記出「連結」:從這裡可以連結到哪個文件、哪個位置。

2011/01/30

Web Servers

Apache(httpd)
Lighttpd
Nginx
Passenger
Unicorn
Mongrel
Thin
GWS(Google Web Server)
IIS(Internet Information Services)

Reference:
01. http://wiki.nginx.org/Chs

2011/01/28

Storage Area Network

LUN

Reference:
01. http://en.wikipedia.org/wiki/Storage_area_network
02. http://en.wikipedia.org/wiki/Logical_Unit_Number
03. http://en.wikipedia.org/wiki/ISCSI
04. http://en.wikipedia.org/wiki/Fibre_Channel

2011/01/26

Plurk 機器人

做一個 Plurk 機器人其實不難,只是相關的文章好像都很少。
或許太簡單了,大家都懶得寫。
但我這種容易忘的人還是幫自己記錄一下好了。
初次接觸的人也可以一起參詳一下,大家一起做寫有趣的應用。



其實許多程式機器人的原理都是差不多的。
假設你已經很熟悉 Plurk 的使用了,你想要做提供用餐建議的機器人,該怎麼做呢?
請你先想象一下你自己就是這個機器人(機器人其實就是模擬「人」,對吧?)。

你的工作情境是:
  
你的 Plurk 帳號會允許所有使用者的好友請求,並且把對方也加入爲好友。

假設有 10 位 Plurk 使用者加你好友,你也會加他們到你的好友清單。
這樣一來,你的 Plurk 河道上就會追蹤到這 10 位使用者的 plurks 了。

你「每一分鐘」檢查一次自己的 Plurk 河道是否有新的未讀訊息。
檢查的條件:
1)訊息狀態是否爲「好奇(wonder)」;
2)訊息內容是否爲「早餐」或「中餐」或「晚餐」;
3)符合以上條件,則回應用餐建議到該訊息。

回應的流程:
1)根據「早」、「中」、「晚」餐,從對應的用餐建議庫裡隨機選出一個;
2)組合成完整的回應內容,回覆到對應的訊息底下。