Monty Hall Problem
參賽者會看見三扇關閉了的門,其中一扇的後面有一輛汽車,選中後面有車的那扇門就可以贏得該汽車,而另外兩扇門後面則各藏有一隻山羊。當參賽者選定了一扇門,但未去開啟它的時候,節目主持人會開啟剩下兩扇門的其中一扇,露出其中一隻山羊。主持人其後會問參賽者要不要換另一扇仍然關上的門。問題是:換另一扇門會否增加參賽者贏得汽車的機率?
之前忘了在哪有聽到這個問題,不過都沒太仔細去思考這個問題,想說機率不都是三分之一嗎?沒想到換門的話,真的會提高機率。
2010年11月21日 星期日
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)做修改,可參考此網站
最後,啟動Service
# /etc/init.d/haproxy start
# 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 '新密碼';
# 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來當做修改的範本。
接著便是修改myservice script,部份修改如下:
最後便是利用update-rc.d指令,更新各runlevel服務啟動設定
defaults參數設定服務在runlevel為2,3,4,5啟動,runlevel為0,1,6為停止。若要詳細的設定,請參考man update-rc.d
首先要產生一個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 --config 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欲安裝的目的資料夾所在。
解壓縮完成後:
# 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+[↓↑]
介紹兩種方法:
第一種是同時開啟多個檔案
# vim -p file1 file2
操作指令如下:
:tabe file3 開啟一個新分頁file3檔案
:tabn 編輯下一個檔案
:tabp 編輯前一個檔案
若覺得切換分頁麻煩可以在vimrc設定
nmap
nmap
如此便可用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 欲執行的程式
詳細說明
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
# 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);
釋放記憶體區段
範例可參考此網頁
相關的函式:
#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日 星期四
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
先了解變數替換的方法
${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
兩個參數,第一個參數為預切割的字串,第二個參數為切割的符號(預設為逗號),因為是繼承vector,所以可以直接用vector的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]
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)
舊式:
echo The current date is `date`
新式
echo The current date is $(date)
2010年2月20日 星期六
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所要執行的程式
程式碼架構可參考此網站
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);
}
訂閱:
文章 (Atom)