2010年11月21日 星期日

蒙提霍爾(Monty Hall Problem)

Monty Hall Problem

參賽者會看見三扇關閉了的門,其中一扇的後面有一輛汽車,選中後面有車的那扇門就可以贏得該汽車,而另外兩扇門後面則各藏有一隻山羊。當參賽者選定了一扇門,但未去開啟它的時候,節目主持人會開啟剩下兩扇門的其中一扇,露出其中一隻山羊。主持人其後會問參賽者要不要換另一扇仍然關上的門。問題是:換另一扇門會否增加參賽者贏得汽車的機率?


之前忘了在哪有聽到這個問題,不過都沒太仔細去思考這個問題,想說機率不都是三分之一嗎?沒想到換門的話,真的會提高機率。

2010年8月14日 星期六

永春高中

今天在電視上看見有節目在永春高中出外景,讓我不自覺得停了下來,靜靜的收看。
在這三年的高中生活,讓我印象最深刻的不外乎是多到不行的階梯和那高一必學的永春拳了,雖說現在只記得永春拳的最後一式拍打功而已。

由於高中是透過聯考填志願考上的,所以同學們都是來自不同區域,不知道是因為這樣的緣故,所以到現在還有聯絡的高中朋友少之又少,還是我自己太孤僻,所以沒什麼朋友呢?我想這應該是我高中生活最遺憾的事了~~

2010年7月14日 星期三

Server Load Balance

HAProxy可以讓我們簡單架設一個Load Balance的機器。Debian架設方法如下:

# apt-get install haproxy

若要啟用,記得修改/etc/default/haproxy的設定檔
# vim /etc/default/haproxy
Enabled=1

接著便是依據實際環境對Load Balance的設定檔(/etc/haproxy/haproxy.cfg)做修改,可參考此網站

global
    maxconn 10000
    user    haproxy
    group   haproxy
    daemon
    nbproc  8
   
defaults
    log           global
    mode          http
    option        httplog
    option        dontlognull
    retries       3
    option        redispatch
    option        httpclose
    maxconn       32768
    contimeout    5000
    clitimeout    30000
    srvtimeout    30000
 

listen            web-server
    bind          0.0.0.0:80
    balance       roundrobin
    server        w1 192.168.1.1:80 weight 3 check
    server        w2 192.168.1.2:80 weight 3 check
    option        httpchk GET /index.html

    option        redispatch
    option        forwardfor

最後,啟動Service
# /etc/init.d/haproxy start

2010年7月5日 星期一

PostgreSQL安裝

Debian安裝PostgreSQL

# apt-get install postgresql

要登入PostgreSQL,必須以postgres的身份執行
# su postgres
# psql template1

接著便可新增使用者(可新增資料庫及使用者的權限)
create user 帳號 with password '密碼' createdb createuser;

修改密碼
alter user 帳號 with password '新密碼';

2010年6月26日 星期六

update-rc.d

寫了一支Daemon程式,除了在/etc/init.d/rc.local上寫入欲執行的指令外,也可以利用[Debian]update-rc.d指令,更新各runlevel下要執行的script。
首先要產生一個init.d script來執行我們要執行的Daemon,我們可以利用/etc/init.d/skeleton來當做修改的範本。

# cp /etc/ init.d/skeleton /etc/init.d/myservice
# chmod a+x /etc/init.d/myservice

接著便是修改myservice script,部份修改如下:
# vim /etc/init.d/myservice
DESC="Daemon的描述"
NAME=Daemon的檔名
DAEMON=Daemon所在絕對路徑
PIDFILE=/var/run$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

最後便是利用update-rc.d指令,更新各runlevel服務啟動設定
# cd /etc/init.d
# update-rc.d myservice defaults

defaults參數設定服務在runlevel為2,3,4,5啟動,runlevel為0,1,6為停止。若要詳細的設定,請參考man update-rc.d

2010年6月20日 星期日

全力搶救死刑狗





現在影片看到的狗可能都已經不在了。想到這就好難過,牠們沒有罪沒有錯,為什麼短短的十二天就要決定牠們的生死!殘酷的人類,既然決定養牠,就應該把牠當作家人一樣看待,而不只是一時興起養牠,最後卻將牠棄養。

狗是人類最忠實的朋友,聽起來真是諷刺阿~~

update-alternatives for gcc

update-alternatives提供了程式版本切換管道,以下將教學如何將gcc也加入到此管理系統。

假設系統已安裝gcc-4.1, g++-4.1, gcc-4.3, g++-4.3

# update-alternatives --remove-all gcc
# update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.3 41 --slave /usr/bin/g++ g++ /usr/bin/g++-4.3 --slave /usr/bin/gcov gcov /usr/bin/g++-4.3
# update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.1 41 --slave /usr/bin/g++ g++ /usr/bin/g++-4.1 --slave /usr/bin/gcov gcov /usr/bin/g++-4.1

顯示所有的版本
# update-alternatives --display gcc

設定所要選擇的版本
# update-alternatives --config gcc

2010年6月18日 星期五

Linux Kernel Headers

在編譯程式時,有時會需要Linux kernel header。除了用套件管理程式下載外,也可自己去下載Linux Kernel Source下來,透過下面指令安裝到指定的目錄下。

解壓縮完成後:
# make ARCH=$ARCH headers_check
# make ARCH=$ARCG INSTALL_HDR_PATH=$HEADER_DIR headers_install

$ARCH為處理器的架構平台,如ppc, arm等。
$HEADER_DIR為Header欲安裝的目的資料夾所在。

2010年5月30日 星期日

vim同時編輯多個檔案

vim也具有同時開啟及編輯多個檔案的能力:

介紹兩種方法:

第一種是同時開啟多個檔案
# vim -p file1 file2

操作指令如下:
:tabe file3 開啟一個新分頁file3檔案
:tabn 編輯下一個檔案
:tabp 編輯前一個檔案

若覺得切換分頁麻煩可以在vimrc設定
nmap <F3>:tabn<ENTER>
nmap <F4>:tabp<ENTER>
如此便可用F3、F4鍵來快速切換分頁

第二種則類似分割視窗的作法
在vim命令模式
:sp file2

畫面便會被分割,切換檔案方式如下:
[ctrl]+w+[↓↑]

2010年5月27日 星期四

Linux上偵測Memory Leak

Memory leak一不小心就會發生,往往很難去發現。在Linux有開發程式,可以利用Valgrind這套軟體來偵測程式是否有Leak發生。

Valgrind不僅可偵測Memory Leak,也可以偵測Invalid Pointer和使用未初始化的變數。

Debian:
# apt-get install valgrind

使用方法:
# valgrind --tool=memcheck --leak-check=yes 欲執行的程式

詳細說明

2010年5月24日 星期一

新三國

小時候因為一本三國演義讓我迷上了三國,高中架了一個三國網站,書櫃也擺著一整排的三國書籍。
最近又迷上一部三國的電視劇,拍攝技巧較十多年前的三國演義進步許多,但就是在對話的用詞上,有些怪怪的,說不上來。



雖說三國演義七實三虛,許多描述也過於誇大與神話,但我就是喜歡。因為我不是歷史學家,是真是假又有什麼重要呢?

2010年5月15日 星期六

exim4外寄郵件伺服器

在Debian如何透過exim4設定外寄郵件伺服器來寄信(以gmail以及hotmail為例)

# dpkg-reconfigure exim4-config

在smarthost的設定填入對應的值
gmail
smtp.gmail.com::587
hotmail
smtp.live.com

# vim /etc/exim4/passwd.client
gmail
gmail-smtp.1.google.com:帳號@gmail.com:密碼
*.google.com:帳號:密碼
smtp.gmail.com:帳號@gmail.com:密碼

hotmail
smtp.live.com:帳號@hotmail.com:密碼

重新讀取設定
# /etc/init.d/exim4 reload

2010年4月18日 星期日

mmap

Mapped memory允許不同的Process透過Shared file來溝通,mmap()可以將檔案mapping到 process's address space中,好處是可以加速檔案的存取。

相關的函式:
#include <sys/mman.h>
void * mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);

將檔案內容對應到記憶體
addr: 指定記憶體的起始位址,若為NULL,Linux會自動選擇一個可用的位址。
len: 對應的檔案的大小(byte)
prot: 記體體的存取權限,以下常數OR

PROT_READ - 可讀取
PROT_WRITE - 可寫入
PROT_EXEC - 可執行
PROT_NONE - 不可存取

flags :記憶體區段內容的修改方式

MAP_FIXED - 記憶體位址必須是指定的address
MAP_PRIVATE - 修改不會寫回原檔案
MAP_SHARED - 修改會反應到原檔案

int msync(void *addr, size_t len, int flags);
讓記憶體區段被修改的內容,寫回到對應該的檔案中
addr: 記憶體的起始位址
len: 記憶體區段的大小
flags: 更新方式

MS_ASYNC - 非同步寫入,不需馬上寫入
MS_SYNC - 同步寫入,馬上寫入
MS_INVALIDATE - 重新從檔案取得最新的資料

int munmap(void *addr, size_t len);
釋放記憶體區段

範例可參考此網頁

2010年4月8日 星期四

mutt寄信

在Linux用指令來寄信並加上附件,可以用mutt來完成。

指令: mutt -a 附件檔案 -s 主旨 收件者,例:
# mutt -a attachement.txt -s "Hello Mutt" test@test.com

寄件者的Email可以設定在~/.muttrc
my_hdr From: Name <E-Mail>

2010年3月17日 星期三

大量改檔名

若同一個資料夾裡,要用同樣的規則修改檔名,如所有為.dat副檔名要更名為.txt,可以寫一個簡單的shell script來完成。

先了解變數替換的方法
${var%word} - 由var變數內容的後端,向前刪除符合word關鍵字(最短部份)
${var%%word} - 由var變數內容的後端,向前刪除符合word關鍵字(最長份)
${var#word} - 由var變數內容的前端,向後刪除符合word關鍵字(最短部份)
${var##word} - 由var變數內容的前端,向後刪除符合word關鍵字(最長部份)

舉例:
變數$abc = howard, john, tom
# echo ${abc%,*}
howard, john
# echo ${abc%%,*}
howard

重新命名範例:將附檔名dat改為txt
#/bin/bash
for i in *.dat
do
mv $i "${i%dat}txt"
done

2010年3月14日 星期日

strtok in C++

C++來實作類似strtok()的function

class StrTok : public vector<std::string> {
public:
StrTok(const string & strInput, const string & strDelim = " ,") {
string::size_type nHead, nTail;
nHead = strInput.find_first_not_of(strDelim, 0);
nTail = strInput.find_first_of(strDelim, nHead);

while(nHead != string::npos || nTail != string::npos) {
push_back(strInput.substr(nHead, nTail - nHead));
nHead = strInput.find_first_not_of(strDelim, nTail);
nTail = strInput.find_first_of(strDelim, nHead);
}
}
};

兩個參數,第一個參數為預切割的字串,第二個參數為切割的符號(預設為逗號),因為是繼承vector,所以可以直接用vector的function去存取切割後的字串。範例如下:

StrTok tok("howard, john");
for(StrTok::size_type i = 0; i < tok.size(); i++)
cout << tok[i];

2010年3月11日 星期四

MySQL最大連線數

MySQL的最大連線數可以透過my.cnf設定檔來設定

max_connections = 200 (若沒有設定,預設值為100)。

上述方法需重新啟動MySQL才能套用設定,另一種方法則是直接下指令,缺點就是下次重啟動時還是會回到原設定
mysql> set global max_connections = 200;

透過以下指來可查看此參數設定。
mysql> show variables;

至於目前的連線數,可透過Threads_connected來得知,動態變化,可透過以下指令得知目前連線數
mysql> show status;

此外,若發現MySQL的連線數出現異常,如短時間爆增連線,可以用以下指令來找尋目前的連線狀態,找出當下SQL Query的指令與來源。
mysql> show full processlist;

若有異常的指令,可以下kill來刪除該指令
mysql> kill [id]

2010年3月7日 星期日

命令執行

在Shell Script常常會需要抓取或是儲存執行某個指令的結果。舊式的寫法是用反引號`cmd`,要注意的一點就是符號不是單引號(')。而新式的寫法是採用$(cmd)。

舊式:
echo The current date is `date`

新式
echo The current date is $(date)

F2 重新命名

在Windows作業系統,在圖示按兩下便可以更改檔名,然而在Linux下的桌面環境,點兩下卻是沒有回應,要按右鍵屬性去修改,感覺有些麻煩。現在才發現有一個更快的方法,那就是F2鍵就如同在圖示點兩下,Windows也適用。

2010年2月20日 星期六

網頁轉址

常常忘記語法,先記下來。
<meta http-equiv="refresh" content="0; url=xxx.html">

2010年1月3日 星期日

Daemon Tutorial

參考一份文件,介紹寫Daemon程式所需要的基本步驟:
1. Fork off the parent process
利用fork()脫離父程序,成為init的子程序
2. Change file mode mask
利用umask()控制Daemon所建立的檔案權限
3. Open any logs for writing
可透過寫檔或是syslog來記錄執行的過程
4. Create a unique Session ID
利用setsid()建立新的session並脫離tty
5. Change the current working directory to a safe place
利用chdir()來改變工作目錄(用意不太清楚)
6. Close standard file descriptors
因為Daemon不會使用terminal,所以關閉不必要的descriptors
7. Enter actual daemon code
Daemon所要執行的程式

程式碼架構可參考此網站
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>

#define DAEMON_NAME "MyDaemon"

int main(int argc, char** argv)
{
pid_t pid, sid;

// Change file mode mask
umask(0);

// Open logs for writing
openlog(DAEMON_NAME, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_USER);
syslog(LOG_NOTICE, "%s daemon started", DAEMON_NAME);

pid = fork();
if(pid < 0) {
syslog(LOG_ERR, "Fail to fork a process");
exit(EXIT_FAILURE);
}

// Fork off the parent process
if(pid > 0) {
exit(EXIT_SUCCESS);
}

// Create a unique Session ID
sid = setsid();
if(sid < 0) {
syslog(LOG_ERR, "Fail to create a new Session ID");
exit(EXIT_FAILURE);
}

// Change the current working directory
if((chdir("/") < 0)) {
syslog(LOG_ERR, "Fail to change the current working directory");
exit(EXIT_FAILURE);
}

// Close out the standard file descriptiors
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);

//******************************************************************
// Insert the daemon process
//******************************************************************

exit(EXIT_SUCCESS);
}