php configure fast cgi

php 與 apache 最常協同工作的方式是採用在 apache 上掛載 mod_php 模組,在執行 apache 的時候呼叫這個模組來編譯 php 網頁。所以接收工作與回應的模式大都是 apache 在控制(這邊指的是行程的數量…與生命週期等等),預設情況 apache 會有一個 process pool 接到要求就從 pool 中叫一個起來工作,如果工作超過 pool 的 process 量的話則 fork 新 process 來處理,則會佔用大量的記憶體,尤其是 apache 是採用 process 不是 thread 的關係(一個 30M 200個 request 就需要 6G)。

common gateway interface 是一個讓網頁伺服器與程式銜接的介面,叫做 interface 就是代表各種語言只要實做了這個介面就能跟網頁伺服器溝通。而 fast cgi 則是 cgi 的擴展擁有許多更良好的特性,可以是一個不中斷程式持續的接收工作,而 apache 接到工作以後不是採用 php 模組的方式呼叫編譯,而是將要求轉送至已在運行的 fcgi 程式中。

透過 fast cgi 的方式運作與 spawn cgi 來管控數個設定如: php_cgi  行程的數量。透過管理 php_cgi 行程池,減低 apache 載入 php 模組所耗費的記憶體,應能加速 apache fork 行程的速度,因為少載入了一個肥大的 mod_php module。這樣的話假設實際環境使用者要求個網頁有 1個php 9個資源的情況,10個要求只有1個需要呼叫 php_cgi ,這樣 10 個 php_cgi 可以處理 100 個 apache process。

Continue reading…

Python shell history Substitution

在 linux 更新成 Python 2.7 後進入他 shell 以後發現,按上下鍵想要查尋歷史紀錄竟然只出現  ^[[A ,這些符號…感覺有點糟糕…

找了許多才發現原來是少安裝一個函式庫,不曉得是 readline 還是 ncureses ,管他的都裝…= =

ncureses 是一個提供在文字介面操作的 API 函式庫。應該跟文字介面上下左右事件監控有關。


yum install ncurses

yum install ncurses-devel
easy_install readline

ncurses 似乎還蠻有趣的,linux kernel menu config 好像就是用他寫的…
網路[3]上看到一個範例可以跑跑看…

#include <curses.h>
#include <stdlib.h>

#define ENTER 10
#define ESCAPE 27
void init_curses()
{
        initscr();
        start_color();
        init_pair(1,COLOR_WHITE,COLOR_BLUE);
        init_pair(2,COLOR_BLUE,COLOR_WHITE);
        init_pair(3,COLOR_RED,COLOR_WHITE);
        curs_set(0);
        noecho();
        keypad(stdscr,TRUE);
}
void draw_menubar(WINDOW *menubar)
{
        wbkgd(menubar,COLOR_PAIR(2));
        waddstr(menubar,"Menu1");
        wattron(menubar,COLOR_PAIR(3));
        waddstr(menubar,"(F1)");
        wattroff(menubar,COLOR_PAIR(3));
        wmove(menubar,0,20);
        waddstr(menubar,"Menu2");
        wattron(menubar,COLOR_PAIR(3));
        waddstr(menubar,"(F2)");
        wattroff(menubar,COLOR_PAIR(3));
}
WINDOW **draw_menu(int start_col)
{
        int i;
        WINDOW **items;
        items=(WINDOW **)malloc(9*sizeof(WINDOW *));

        items[0]=newwin(10,19,1,start_col);
        wbkgd(items[0],COLOR_PAIR(2));
        box(items[0],ACS_VLINE,ACS_HLINE);
        items[1]=subwin(items[0],1,17,2,start_col+1);
        items[2]=subwin(items[0],1,17,3,start_col+1);
        items[3]=subwin(items[0],1,17,4,start_col+1);
        items[4]=subwin(items[0],1,17,5,start_col+1);
        items[5]=subwin(items[0],1,17,6,start_col+1);
        items[6]=subwin(items[0],1,17,7,start_col+1);
        items[7]=subwin(items[0],1,17,8,start_col+1);
        items[8]=subwin(items[0],1,17,9,start_col+1);
        for (i=1;i<9;i++)
                wprintw(items[i],"Item%d",i);
        wbkgd(items[1],COLOR_PAIR(1));
        wrefresh(items[0]);
        return items;
}
void delete_menu(WINDOW **items,int count)
{
        int i;
        for (i=0;i<count;i++)
                delwin(items[i]);
        free(items);
}
int scroll_menu(WINDOW **items,int count,int menu_start_col)
{
        int key;
        int selected=0;
        while (1) {
                key=getch();
                if (key==KEY_DOWN || key==KEY_UP) {
                        wbkgd(items[selected+1],COLOR_PAIR(2));
                        wnoutrefresh(items[selected+1]);
                        if (key==KEY_DOWN) {
                                selected=(selected+1) % count;
                        } else {
                                selected=(selected+count-1) % count;
                        }
                        wbkgd(items[selected+1],COLOR_PAIR(1));
                        wnoutrefresh(items[selected+1]);
                        doupdate();
                } else if (key==KEY_LEFT || key==KEY_RIGHT) {
                        delete_menu(items,count+1);
                        touchwin(stdscr);
                        refresh();
                        items=draw_menu(20-menu_start_col);
                        return scroll_menu(items,8,20-menu_start_col);
                } else if (key==ESCAPE) {
                        return -1;
                } else if (key==ENTER) {
                        return selected;
                }
        }
}
int main()
{
    int key;
    WINDOW *menubar,*messagebar;

    init_curses();

    bkgd(COLOR_PAIR(1));
    menubar=subwin(stdscr,1,80,0,0);
    messagebar=subwin(stdscr,1,79,23,1);
    draw_menubar(menubar);
    move(2,1);
    printw("Press F1 or F2 to open the menus. ");
    printw("ESC quits.");
    refresh();

    do {
        int selected_item;
        WINDOW **menu_items;
        key=getch();
        werase(messagebar);
        wrefresh(messagebar);
        if (key==KEY_F(1)) {
            menu_items=draw_menu(0);
            selected_item=scroll_menu(menu_items,8,0);
            delete_menu(menu_items,9);
            if (selected_item<0)
                wprintw(messagebar,"You haven't selected any item.");
            else
                wprintw(messagebar,
                  "You have selected menu item %d.",selected_item+1);
            touchwin(stdscr);
            refresh();
        } else if (key==KEY_F(2)) {
            menu_items=draw_menu(20);
            selected_item=scroll_menu(menu_items,8,20);
            delete_menu(menu_items,9);
            if (selected_item<0)
                wprintw(messagebar,"You haven't selected any item.");
            else
                wprintw(messagebar,
                  "You have selected menu item %d.",selected_item+1);
            touchwin(stdscr);
            refresh();
        }
    } while (key!=ESCAPE);

    delwin(menubar);
    delwin(messagebar);
    endwin();
    return 0;
}

參考資源:

DNS Server

http://4271569.spaces.live.com/blog/cns!F1EA4F91324DA556!756.entry
CentOS v5.3-安裝 bind(DNS) / 新增網域名稱 / 每次開機就啟動 named
**Bind 的相關套件 ( DNS )
 .bind…………………………DNS 主程式
 .bind-chroot………………將 bind 主程式關在家理
 .bind-utils………………….用戶搜詢主機名稱的相關指令
 .system-config-bind
 .caching-nameserver

**安裝 bind,似 DNS 名稱解悉
**bind 的設定檔在 /var/named/chroot
# yum -y install bind bind-chroot bind-utlis system-config-bind caching-nameserver <-- 安裝套件。install 時不需再問全為 (y)es # cd /var/named/chroot/etc <-- 切換至 etc 目錄下 # cp named.caching-nameserver.conf named.conf <-- 覆製 named.caching-nameserver.conf,另存成 named.conf # ll <-- 觀察 named.conf 檔案權限, 此時應為 root root # chown root:named named.conf <-- 變更 named.conf 檔案權限 # ll <-- 觀察 named.conf 檔案權限, 此時應變稱為 root named # service named restart <-- 修改後需重新啟動,讓設定值生效。會先關畢,然後再啟動 # vi /var/named/chroot/etc/named.conf <-- 修改 named.conf 將 listen-on port 53 { 127.0.0.1; }; 修改成 listen-on port 53 { any; }; <-- 將127.0.0.1 改為 any,表示監聽所有 53 port 介面 將 allow-query { localhost; }; 修改成 allow-query { any; }; <-- 將 localhost 改為 any,表示允許外部來此台 dns 查詢 # service named restart <-- 修改後需重新啟動,讓設定值生效。會先關畢,然後再啟動 **新增 網域名稱 ◎假設網域名稱 ne160.kirnel.com  .新增加網域名稱 hello.ne160.kirnel.com  .新增加網域名稱 kitty.ne160.kirnel.com       ne160.kirnel.com ( 140.137.217.160 )           /       \          /         \         hello        kitty      ne160.kirnel.com  ne160.kirnel.com      140.137.217.160  140.137.217.160          |        | ┌-------- ┼- Apache -┼-------┐ | /opt/hello <┘        └> /opt/kitty | └-------------------------┘ # vi /var/named/chroot/etc/named.conf <-- 修改 etc 目錄下的 named.conf 檔 將 match-client { localhost; }; 修改成 match-client { any; }; 將 match-destinations { localhost; }; 修改成 match-destinations { any; }; # vi /var/named/chroot/etc/named.rfc1912.zones <-- 修改 named.rfc1912.zones 檔案 增加以下: zone "ne160.kirnel.com" IN { type master; file "ne160.zone"; allow-update { none; }; }; # cd /var/named/chroot/var/named # ll <-- 觀察是否有 ne160.zone # cp localhost.zone ne160.zone <-- 覆製 localhost.zone,另存成 ne160.zone # ll <-- 觀察 ne160.zone 檔案權限,此時應為 root root # chown root:named ne160.zone <-- 變更 ne160.zone 檔案權限 # ll <-- 觀察 ne160.zone 檔案權限,此時應變稱為 root named # vi /var/named/chroot/var/named/ne160.zone <-- 修改 ne160.zone,新增加 hello 及 kitty 網域 增加以下: hello  IN A  140.137.217.160 kitty  IN A  140.137.217.160 # service named restart <-- 修改完後,重新啟動 named。會先關畢,然後再啟動 **測試 # vi /etc/resolv.conf <-- 設定 DNS 增加以下: nameserver 168.95.1.1 # dig hello.ne160.kirnel.com @localhost <-- 使用本端機的 DNS,來查 hello.ne160.kirnel.com # dig hello.ne160.kirnel.com @168.95.1.1 <-- 使用中華電信的 DNS,來查 hello.ne160.kirnel.com # dig kitty.ne160.kirnel.com @localhost <-- 使用本端機的 DNS,來查 kitty.ne160.kirnel.com # dig kitty.ne160.kirnel.com @168.95.1.1 <-- 使用中華電信的 DNS,來查 kitty.ne160.kirnel.com **測試在 Windows 下使用 ping 指令  .ping hello.ne160.kirnel.com  .ping kitty.ne160.kirnel.com **建立 hello 及 kitty 網站目錄 # cd /opt <-- 切換至 /opt 目錄下,觀查有無 hello 及 kitty 目錄 # mkdir /opt/hello <-- 在 /opt 目錄下建立 hello 網站目錄 # mkdir /opt/kitty <-- 在 /opt 目錄下建立 kitty 的網站目錄 **建立網站內容文字 # echo "This is hello web." > /opt/hello/index.html <-- 在 hello 目錄下建立 index.html 檔案 # echo "This is kitty web." > /opt/kitty/index.html <-- 在 kitty 目錄下建立 index.html 檔案 **建立虛擬網站 # service httpd restart <-- 重新啟動。會先關畢,然後再啟動 # cd /etc/httpd/conf <-- 切換至 conf 目錄下 # vi httpd.conf 增加以下: NameVirtualHost 140.137.217.160:80
ServerAdmin hello@ne160.kirnel.com
DocumentRoot /opt/hello
ServerName hello.ne160.kirnel.com
ErrorLog /var/log/hello-error_log
CustomLog /var/log/hello-access_log common


ServerAdmin kitty@ne160.kirnel.com
DocumentRoot /opt/kitty
ServerName kitty.ne160.kirnel.com
ErrorLog /var/log/kitty-error_log
CustomLog /var/log/kitty-access_log common

# service httpd restart <-- 修改後,重新啟動。會先關畢,然後再啟動 **測試網站是否正確建立完成  .在 Windows 下開啟瀏覽器,在網址列內輸入 http://hello.ne160.kirnel.com  .在 Windows 下開啟瀏覽器,在網址列內輸入 http://kitty.ne160.kirnel.com **設定每次開機就啟動 named # chkconfig named on <-- 設定每次開機就啟動 named 功能 http://plus-now.com/?p=31

http://plus-now.com/?p=36

參考上述設定…

hadoop 0.21.0 ant build thrift php

名詞解釋
hadoop : 分散式檔案系統與 MapReduce 運算軟體框架
HDFS : 分散式檔案系統
ant : Java 自動編譯工具
thrift : 跨語言 API 介面,由 Facebook 開發用來銜接各語言 api 。

編譯 hadoop 建立 thrift server 

$ install ant
$ cd ./hdfs ;
$ ant compile

if error

[ivy:resolve] module not found: org.apache.hadoop#hadoop-common;0.21.0

原先的 repo snapshot 檔名都換過了,將 build.xml 內 repo 網址改成

https://repository.apache.org/content/repositories/snapshots/ => https://repository.apache.org/service/local/repositories/orgapachehadoop-042/content/

從 https://repository.apache.org/index.html 找到的

編譯 again

warning ‘includeantruntime’ was not set

錯誤 依照錯誤行數 在 javac 加上 includeantruntime=”false” 屬性就略過了 (http://www.coderanch.com/t/503097/tools/warning-includeantruntime-was-not-set)

接著會有 lib not fount 的錯誤

搬移 $hadoop/lib to hdfs/lib 應該是因為 抓的是 release 不是 dev 的版本 目錄位置有些差異,

然後發現缺了 conf ,所以對著 $hadoop/common 造著編譯一次,

然後混和兩個資料夾,我是建了一個 $hadoop/build

然後 cp $hadoop/common $hadoop/build -r ; cp $hadoop/hdfs $hadoop/build -ru

hdfs thrift server 環境就差不多了,thrift 負責建立一個 socket ,然後用各種語言透過 socket 連接 API 。

為什麼要自己編譯 hadoop 呢?我也不知道…感覺可以把編譯好的 hadoop-thrift.jar 拿來用,但是沒有地方有教…

只好照著有人有教的方式做,就編譯吧,順便瞭解一下原始碼路徑,大略看一下程式邏輯,並且之後還能做修改。

編譯 thrift-php ext

接著要建立 php 連接 thrift 的環境,可以先裝 thrift (http://thrift.apache.org/) 只是用不到= =,

thrift 應該是用來把寫好的 *.thrift(抽象API描述) 編譯成各種語言適用的API,只是 hadoop 已經都編譯好了,在 gen-php 裡面,

thrift 下載好以後,裡面有附 php-ext module 的程式,就一樣phpize;./configure;make ;make install;

他好像會在 /usr/lib/php/ 下面複製好對應的程式,./protocol/ , ./transport/ , ./Thrift.php …應該是吧 如果沒有就自己從 Thrift 原始碼裡面 co 出來吧,

然後建立一個 /usr/lib/php/packages/ 然後把 gen-php 丟進去 改名字叫…XD…原始碼裡面有寫…自己看…

example

進資料夾跑 build/src/contrib/thriftfs/scripts/start_thrift_serve.sh $port & 吧 ,可以指定 port,他會連結哪台伺服器一樣在 conf/core-site.xml 裡面設定,

然後在跑 client demo ..應該還ok,只是不知道 thrift_protocol 有作用嗎…

<?php
//include thrift路徑
$GLOBALS['THRIFT_ROOT'] = '/usr/lib/php';
require_once( $GLOBALS['THRIFT_ROOT'].'/Thrift.php' );
require_once( $GLOBALS['THRIFT_ROOT'].'/transport/TSocket.php' );
require_once( $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php' );
require_once( $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php' );
require_once( $GLOBALS['THRIFT_ROOT'].'/packages/hadoopfs/ThriftHadoopFileSystem.php' );
//建立連線
$socket = new TSocket( 'localhost', 50000 );
$socket->setSendTimeout( 10000 ); // Ten seconds
$socket->setRecvTimeout( 20000 ); // Twenty seconds
$transport = new TBufferedTransport( $socket );
$protocol = new TBinaryProtocol( $transport );
$client = new ThriftHadoopFileSystemClient( $protocol );
//啟動
$transport->open();
/*程式碼寫在這*/
try {
$pathname = new Pathname(array("pathname" => "/mlwmlw/"));
print_r($client->mkdirs($pathname));
<div>$pathname = new Pathname(array("pathname" => "/"));
<div>//列表
print_r($client->listStatus($pathname));
//用帳號名稱相同就能跨伺服器存取資料 權限很弱喔?!
} catch(Exception $e) {
print_r($e);
}
$transport->close();
?>

接著測 create and write 的部份就出錯了,錯誤訊息有兩種,第一次都是
TException: TSocket: Could not write 4 bytes
接著都是 TScoket timeout,在某篇資源裡面有提到他猜測是 php 處理 64bit 的整數時造成的錯誤,
因為 Thrift 有定義 64bit 整數的型態,然後API裡面有一個 readI64 的函式,好像是在合成兩個 32bit 的整數,
我自己試著去把 create 產生的 fileid 印出來,跟 HadoopThriftServer 進行比對,
發現總是對不起來,因為 create 產生的是 getRandom().nextLong() 好像都是滿滿 64bit 的長整數,
將他替換成 nextInt() 重新編譯就沒有問題了。

#org/apache/hadoop/thriftfs/HadoopThriftServer.java 50行
-- private long nextId = new Random().nextLong();
++ private long nextId = new Random().nextInt();

[參考資源]