2010年7月20日 星期二

[PHP] 使用 Signal Handler

之前用 PHP 寫了一些 tools level 的程式,也就是使用上都是透過 $ php t.php 的模式在進行,最近想替他加上 Signal 的處理,如此一來可以增加一些資料的正確性。


參考資料:



範例程式(小部份的修改 Example #1 pcntl_signal() example):


@ t.php
<?php
// tick use required as of PHP 4.3.0
declare(ticks = 1);

function sig_handler($signo)    // signal handler function
{
        switch ($signo)
        {
                case SIGTERM:   // handle shutdown tasks, kill, kill -15
                        print "SIGTERM\n";
                        break;
                case SIGHUP:    // handle restart tasks, kill -1
                        print "SIGHUP\n";
                        break;
                case SIGUSR1:
                        print "SIGUSR1\n";
                        break;
                case SIGINT:    // ctrl + c
                        print "SIGINT\n";
                        break;
                default:        // handle all other signals
                        print "Other:$signo\n";
        }
}

echo "Installing signal handler...\n";

// setup signal handlers
pcntl_signal( SIGTERM , "sig_handler" );        // kill or kill -15
pcntl_signal( SIGHUP ,  "sig_handler" );        // kill -1
pcntl_signal( SIGUSR1 , "sig_handler" );        // self
pcntl_signal( SIGINT , "sig_handler" );         // ctrl+c

//echo"Generating signal SIGTERM to self...\n";

while( 1 )
{
        echo ".";
        sleep( 1 );
}

// send SIGUSR1 to current process id
//posix_kill(posix_getpid(), SIGUSR1);

echo "Done\n"

?>


執行前需留意,上述程式已經擷取 ctrl+c 的訊號,在 Unix 環境中,需使用 kill -9 的訊號來終止他


$ php t.php


接著在 Unix 上可以用 pa aux | grep 'php t.php' 查看剛剛那隻的 pid,接著可以用 kill 指令去操控他囉!


簡單用 awk 處理,可自行把 system( "kill " $2 ) 更新為 system( "kill -9 " $2 ) 等模式


$ ps aux | grep 'php t.php' | awk 'match( $11,"php" ) && match( $12 , "t.php" ) {system( "kill " $2 )}'


依序用 Ctrl+C , kill -1, kill -15, kill -9 的訊號


$ php t.php
Installing signal handler...
....^CSIGINT
.....SIGHUP
....SIGTERM
...已砍掉


2010年7月19日 星期一

模擬網路連線的延遲 - Simulating network delay

目的:模擬連線到國外的網路品質。


由於有些新穎的服務都嘛是從國外開始蔓延,有的服務連過去使用時都有點頓頓,慶幸的有的是 Open Source,於是我把他架起來用用,但是,還是要好奇一下連到國外頓頓的感覺是不是完全是因為網路品質的關係,因此,我就要來試試將自己網路品質弄糟的方式。


一開始我只用 iptables 跟 limit 、delay、latency 或 ms 等關鍵字,找了找,最後發現這個應該是要跟 iproute 相關才是,有幾篇文章



最後,我是用 How to simulate a slow
network with 'wanem'
的方法,在 Ubuntu 10.04 環境下,用 tc 這個指令,並且將 eth3 網路卡的連線 dely 200ms


$ sudo tc qdisc add dev eth3 root handle 1:0 netem delay 200msec


假設 eth3 綁定的是 192.168.56.101 的位置,那就用 ping 來觀看,果真變慢囉(過程是一開始沒有設定,之後加上 dely 200ms,最後在拿掉該設定)


$ ping 192.168.56.101
PING 192.168.56.101 (192.168.56.101) 56(84) bytes of data.
64 bytes from 192.168.56.101: icmp_seq=1 ttl=64 time=0.305 ms
64 bytes from 192.168.56.101: icmp_seq=2 ttl=64 time=0.267 ms
64 bytes from 192.168.56.101: icmp_seq=3 ttl=64 time=201 ms
64 bytes from 192.168.56.101: icmp_seq=4 ttl=64 time=200 ms
64 bytes from 192.168.56.101: icmp_seq=5 ttl=64 time=200 ms
64 bytes from 192.168.56.101: icmp_seq=6 ttl=64 time=201 ms
64 bytes from 192.168.56.101: icmp_seq=7 ttl=64 time=203 ms
64 bytes from 192.168.56.101: icmp_seq=8 ttl=64 time=202 ms
64 bytes from 192.168.56.101: icmp_seq=9 ttl=64 time=0.344 ms
64 bytes from 192.168.56.101: icmp_seq=10 ttl=64 time=0.334 ms
64 bytes from 192.168.56.101: icmp_seq=11 ttl=64 time=0.697 ms
64 bytes from 192.168.56.101: icmp_seq=12 ttl=64 time=0.341 ms
64 bytes from 192.168.56.101: icmp_seq=13 ttl=64 time=0.631 ms
^C
--- 192.168.56.101 ping statistics ---
13 packets transmitted, 13 received, 0% packet loss, time 11998ms
rtt min/avg/max/mdev = 0.267/93.241/203.547/100.266 ms


測試完可以在用以下指令清除


$ sudo tc qdisc del dev eth3 root handle 1:0 netem delay 200msec


VirtualBox 常用的指令筆記


  1. 複製虛擬硬碟

    • $ VBoxManage clonevdi Source.vdi Target.vdi

      由於 *.vdi 內綁有 UUID 等資訊,若直接用 cp 指令,該 UUID 並不會更新,並且導致掛載時出現問題(重複的UUID)。



  2. 設定 port forwarding

    • 語法 VBoxManage getextradata "GuestOSName" enumerate

      $ VBoxManage getextradata Ubuntu1004i386 enumerate
      觀看 Ubuntu1004i386 的 extradata 資訊

    • 語法 VBoxManage setextradata [GuestOSName] "VBoxInternal/Devices/[ADAPTER]/0/LUN#0/Config/[DescriptiveName]/[GuestPort|HostPort|Protocol]" [TCP|UDP|PortNumber]

      $ VBoxManage setextradata Ubuntu1004i386 "VBoxInternal/Devices/e1000/0/LUN#0/Config/ssh/Protocol" TCP
      $ VBoxManage setextradata Ubuntu1004i386 "VBoxInternal/Devices/e1000/0/LUN#0/Config/ssh/GuestPort" 22
      $ VBoxManage setextradata Ubuntu1004i386 "VBoxInternal/Devices/e1000/0/LUN#0/Config/ssh/HostPort" 2222

      當預設的 Guest OS 使用 NAT 網路模式時,透過上述設定,使用 ssh -p 2222 localhost 即可連進 Guest OS,其中 adapter 為 e1000, 有的人是填 pcnet,關於此部份請查詢 /path_virtualbox/Machine/[GuestOSName]/Logs/VBox.log,此例網路卡使用 "e1000: eth0: e1000_probe: Intel(R) PRO/1000 Network Connection"


    • 若啟動虛擬機器時,產生 Configuration error: Failed to get the "MAC" value (VERR_CFGM_VALUE_NOT_FOUND). 錯誤訊息,可以編輯 /path_virtualbox/Machine/[GuestOSName]/[GuestOSName].xml 檔案,把類似的訊息刪除

          <ExtraData>
            ...
            <ExtraDataItem name="VBoxInternal/Devices/pcnet/0/LUN#0/Config/HTTP/GuestPort" value="22"/>
            <ExtraDataItem name="VBoxInternal/Devices/pcnet/0/LUN#0/Config/HTTP/HostPort" value="2222"/>
            <ExtraDataItem name="VBoxInternal/Devices/pcnet/0/LUN#0/Config/HTTP/Protocol" value="TCP"/>
            ...
          </ExtraData>




  3. 新增網路卡


  4. 共享資料夾

    • Windows 掛載網路硬碟

      • C:\> net use x: \\vboxsvr\[your folder name]






2010年7月14日 星期三

腹有詩書氣自華

記得第一次看到這句,好像是對岸的一篇故事,述說著求學向上的過程。這句話剛剛查了才知道原句出處的情境。


「腹有詩書氣自華」出自蘇軾〈和董傳留別〉:「麤繒大布裹生涯,腹有詩書氣自華。厭伴老儒烹瓠葉,強隨舉子踏槐花。囊空不辦尋春馬,眼亂行看擇婿車。得意猶堪誇世俗,詔黃新濕字如鴉。」(來源:煙霞山林 - http://blog.yam.com/gracecss/article/24906608


碩二上快結束時,曾和吳大閒聊,提到了「技術和健康」,相信只要把持住就不用擔心未來。現在我的確可以慢慢地累積技術跟健康,然而,內心呢?可還需要多多加把勁!期待兩年後。


[PHP] 取得指定目錄下的檔案清單

由於有些 open source 把 Javascript Code 分成很多個目錄,然後我又懶的一個個加入使用,所以,又偷懶寫了個小程式,用來取得指定目錄裡頭的檔案,搭配 Regular Expression 來決定哪些檔名要紀錄,哪些 file path 要捨棄。


程式碼:


<?php
function getFileList( $file_path , $filename_regexp_pattern , $skip_filepath_regexp_pattern )
{
        $_file_list = array();
        if( !file_exists( $file_path ) || !is_dir( $file_path ) )
                return $_file_list;
        if ( $handle = opendir( $file_path ) )
        {
                while (false !== ($file = readdir($handle)))
                {
                        if( $file == '.' || $file == '..' )
                                continue;
                        $target = $file_path . DIRECTORY_SEPARATOR . $file;
                        if( is_dir( $target ) )
                                foreach( getFileList( $target , $filename_regexp_pattern , $skip_filepath_regexp_pattern ) as $k => $v )
                                        $_file_list[ $v ] = $v;
                        if( !empty( $skip_filepath_regexp_pattern ) && preg_match( $skip_filepath_regexp_pattern , $target ) )
                                continue;
                        if( empty( $filename_regexp_pattern ) || preg_match( $filename_regexp_pattern , $file ) )
                                $_file_list[ $target ] = $target;
                }
                closedir($handle);
        }
        return $_file_list;
}

//print_r( getFileList( '.' , '/\.js$/is' , '/test/is' ) );
foreach( getFileList( '.' , '/\.js$/is' , '/test/is' ) as $js_file )
        echo '<script src="'.$js_file.'" type="text/javascript"></script>'."\n";
?>