11月 2011

2011年11月28日 星期一

CGI in Python


如何在Apache上使用cgi呢? 這次會透過設定httpd.conf,讓Apache可以執行python。

如何設定httpd.conf?

1. vi httpd.conf

AddHandler cgi-script .cgi .py
   
<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options ExecCGI
    Order allow,deny
    Allow from all
</Directory>


2. 重啟 httpd

/etc/init.d/httpd restart



簡單的python程式,呼叫ifconfig,並且把結果印出來,這邊要先用python模擬html的表頭符合httpd的標準,才可以正常以網頁方式輸出。

#!/usr/bin/env python
#coding:utf-8
import cgi
import os

print "Content-type: text/html\n\n"

print "<html>"
print "<head>"
print "<title>CGI Program</title>"
print "</head>"
print "<body>"
print "CGI Program"

#cgi.os.popen('su')
#output = cgi.os.popen('mkdir 1')
#print output.read()

print(cgi.os.popen("ifconfig").read())


print cgi.print_environ()
print cgi.print_environ_usage()

print "</body>"



在網址列輸入 http://localhost/cgi-bin/xx.py 即可獲得結果!

後記: 透過這個方式可以讓python到server端上執行指令,並取得結果以網頁方式顯示,這樣就可以做出許多應用。

2011年11月24日 星期四

date in PHP


這篇會介紹PHP中的date()怎麼使用,主要會說明如何把時間與總秒數互相轉換,還有如何透過ssh同步時間\。(因公司緣故,不知為何無法透過NTP同步時間,才會透過SSH做相似的功能)

#把時間轉成總秒數

$now_time_seconds = strtotime(date("d M Y H:i:s"));

#把總秒數轉成時間

date("d M Y H:i:s",$now_time_seconds);



透過ssh 與server的時間用utc時制同步時間

$ip = 'x.x.x.x';
$_user = "root";
$_passord = "";
$_port="22";
if (!($connection=@ssh2_connect($ip, $_port))) {
        echo 'Lost Connection';
}else {
        if (!@ssh2_auth_password($connection,$_user,$_passord))
        {
                echo 'Invalid Password';
        }else{
        #把server的時間用utc時制轉成總秒數,再存入xx_time檔
                $server_senconds_time=date("Y-m-d-H:i:s");
                system("date -u +%m%d%k%M%y.%S > ".$server_senconds_time."_time");


        #從檔案中把總秒數取出來
                $server_senconds="";
                if(file_exists($server_senconds_time."_time"))
                {
                        $file = fopen($server_senconds_time."_time", "r");
                        $tmp_server_senconds = trim(fgets($file));
                        fclose($file);
                        if($tmp_server_senconds!="" && $tmp_server_senconds!=NULL)
                                $server_senconds=$tmp_server_senconds;

                        system("rm ".$server_senconds_time."_time");
                }

        #透過ssh的方式實現時間同步
                if($server_senconds!="")
                {
                         ssh2_exec($connection, "date -u ".$server_senconds." \n exit");
                }else{
                         ssh2_exec($connection, "exit");
                }
    }
}



這邊還有問題是在透過ssh與server時間同步時,會有些許的誤差,主要是因為寫檔與讀檔的緣故。如果有誤請麻煩改正~謝謝~~

2011年11月22日 星期二

Write and Read from a file in Python



昨天在網路上看到某位大大教學如何寫檔與讀檔
但是他的舊方式會造成 IOError: Errno 0 Error
照他的舊方式我重新在Python 3.2.1中試了一下
發現read檔案時會發生無法印出的問題
還有就是寫檔時會寫成binary的格式
之後就追蹤一下程式碼 並且研究一下和之前看到的範例有何差別
最後發現是 讀檔時若用a+方式 會讀不到檔案 要改用r+
底下是將其的程式碼稍做修改後 就可以正確印出和寫入



#!/usr/bin/python
import os,time,sys

Org_Sub = 'abc'
sSub = 'def'

SaveDirectory = os.getcwd()
filename = os.path.join(SaveDirectory,"poem.txt")

try:
   
    f = open(filename,"r+")
    print(filename)
    Log_file = f.read()   
    print(Log_file)
   
except:
    print(filename, sys.exc_info())

sData =Org_Sub  + sSub
f.write(str(sData))
f.close()


如有寫錯的地方請幫忙指正~感恩!


2011年11月17日 星期四

Using Memcached with PHP


本篇介紹如何在PHP中使用memcached.

*需要安裝memcache-3.0.6.tgz

install PECL-memcached (http://pecl.php.net/package/memcache)

    1. tar xvf memcache-3.0.6.tgz

    2. cd memcache-3.0.6

    3. phpize

    4. ./configure

    5. make && make install


在php.ini中extension memcach.so

    1. vi /etc/php.ini

    2. #add memcache module

    3. extension=memcache.so

    4. pkill httpd

    5. httpd


確認memcache module有正確匯入到php中

    <?php

        phpinfo();

    ?>

簡單的測試memcahed,透過這個程式可以知道memcached的版本

    <?php

    $memcache = new Memcache;

    $memcache->connect('192.168.39.102', 11511);

    $version = $memcache->getVersion();

    echo "Server's version: ".$version."\n";

    ?>



本篇著重於初次使用memached所需注意地方,之後會慢慢把memcached in PHP的進階篇補齊.如果有寫錯的地方請指正!謝謝~

2011年11月16日 星期三

Socket in PHP


這篇粗略使用PHP實現client server 的socket程式,底下會稍加解釋如何運作。

透過下列的方式可以實現簡單的client server的socket應用,讓client傳送指令給server端去執行,並於server端結束後會回傳Executed succussfully的訊息給client。

*需要先在php.ini中 extension sockets.so 

Server Node:

 <?php

//使用tcp的公開協議類型

$commonProtocol = getprotobyname("tcp");

 // 建立一個以tcp協議,依順序執行基於stream的socket連接

$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);

//綁定ip和port

socket_bind($socket, '192.168.39.104', 1338);

//開始監聽port

socket_listen($socket);

while(true)

{

        //接受連接進來的連線

        $connection = socket_accept($socket);

        printf("Socket connecting\r\n");

       //讀取client端送來的資料

        $data = socket_read($connection, 1024);

        if($data!=NULL && $data!="")

        {

                system($data);

                //把資料送至clinet端

                socket_write($connection, "Executed succussfully\r\n");

        }else{

                socket_write($connection, "Executed failure\r\n");

        }

        //關閉socket連線

        socket_close($connection);

        printf("Closed the socket\r\n");

}

?>


Client Node:

<?php

class socket

{

        var $socket;

        public $connection_success=0;

        function socket($ip,$port)

        {

                //開啟一個用tcp協議的socket

                $this->socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);

               

                //連結到server

                $result = socket_connect($this->socket,$ip,$port);

                if ($result <1)

                {

                        //印出錯誤訊息

                        echo "Socket connect failed. Cause:".socket_strerror(socket_last_error())."<br>";

                } else{

                        echo "Connect Successfully<br>";

                        $this->connection_success=1;

                        return 1;

                }

        }

        function sendmsg($msg)

        {

                //把$msg傳送到server端

                socket_write($this->socket,$msg,strlen($msg));

                if($msg=="" || $msg==NULL)

                {

                        printf("Send : EMPTY<br>");

                        return 0;

                }else{

                        printf("Send : ".$msg."<br>");

                        return 1;

                }

        }

        function recvmsg()

        {

                //接收server端送的字串

                $result = socket_read($this->socket,100);

                if($result=="" || $result==NULL)

                {

                        printf("Receive : EMPTY<br>");

                        return 0;

                }else{

                        printf("Receive :".$result."<br>");

                        return 1;

                }

        }

        function close()

        {

                //終止連線

                socket_close($this->socket);

        }

}

function check_success($result)

{

        if($result==0)

        {

                $success_or_not="Failed";

                return;

        }

}

$success_or_not="Success";

$a = new socket("192.168.39.104","1338");

if($a->connection_success==1)

{

        check_success($a->sendmsg("ls"));

        check_success($a->recvmsg());

        $a->close();

}else{

        $success_or_not="Failed";

}

echo "Executed ".$success_or_not."<br>";






Problem:
但是有一些問題尚未解決,例如這是阻塞式的socket程式,需要尋找另外的解決方式。 

這邊做個紀錄。 如果有寫錯的地方麻煩幫忙改正,感謝!





2011年11月15日 星期二

SSH Method in PHP


目前因為工作關係,所以對PHP有一些研究,剛好有需要用到SSH來對遠端的LINUX抓資料,故在此紀錄三種SSH使用的方式,並且比較所需時間和限制。

*需要把ssh2.so給extension到php.ini才能在PHP中使用SSH


檔案大小約10k

Method 1:
透過ssh2_exec($connection,$command)方式連結到遠端的電腦下指令抓資料,如果要一次下許多 指令,就必需用\n來間斷,或者使用&&來連結,但是遇到一個指令發生錯誤時,就會造成後續的指令沒辦法繼續執行,所以需要後續兩種方式來改良。

$ip="xx.xx.xx.xx";

$_user = "root";

$_passord = "";
$_port="22";

if (!($connection=@ssh2_connect($ip, "22")))
{
          echo "Can't Connect";
}else {
          if(!@ssh2_auth_password($connection,$_user,$_passord))
          {
                    echo "Invalid Password";
          }else{
                    ssh2_exec($connection, "scp /mnt/test_thread_socket_client1.c root@".$_SERVER['SERVER_ADDR'].":/mnt/1.c \n exit");
          }


}



Method 2:
透過include ssh2.php去抓資料,這種方式的好處是可以把各個指令分別用$mv_shell->writeShell()這種呼叫使用,這種方式可以有效避免單一指令執行失敗,造成後續指令繼續執行問題,但是透過這種方式遇到帳號密碼錯誤,失去連線的狀況時,有可能會一直卡在連線狀況,沒有回應,所以外層再包一層去解決密碼錯誤和失去連線的情況,這種方式是最耗時。 ps.ssh2.php是網路上某位大大所寫的php function,可以到網路搜尋。

include_once("ssh2.php");$ip="xx.xx.xx.xx";
$_user = "root";
$_passord = "";
$_port="22";
if (!($connection=@ssh2_connect($ip, "22")))
{
          echo "Can't Connect";
}else {

  if(!@ssh2_auth_password($connection,$_user,$_passord))

        {

                echo "Invalid Password";

        }else{

                    ssh2_exec($connection, "exit");


                    $scp_shell = new ssh2($ip);
                    $scp_shell->authPassword("root","");
                    $scp_shell->openShell("xterm");
                    $scp_shell->writeShell("scp /mnt/test_thread_socket_client1.c root@".$_SERVER['SERVER_ADDR'].":/mnt/1.c");
                    $scp_shell->writeShell("logout");
                    $scp_shell->getResult();
          }
}





Method 3:
ssh2_scp_recv()這方式是PHP內的語法,不需要使用方法二的ssh2.php,就可以解決前一指令執行失敗,所可能造成後續連續中段的問題,這種方式的執行速度相當快,但是遇到錯誤的密碼時也是會卡住連線,沒有回應,所以外層需要再包一層去判斷密碼錯誤的問題。

$ip="xx.xx.xx.xx";

$_user = "root";
$_passord = "";
$_port="22";
if (!($connection=@ssh2_connect($ip, "22")))
{
          echo "Can't Connect";
}else {
        if(!@ssh2_auth_password($connection,$_user,$_passord))
        {
                echo "Invalid Password";
        }else{
                ssh2_exec($connection, "exit");

                $connection2 = ssh2_connect($ip, 22);
                ssh2_auth_password($connection2, 'root', '');
                ssh2_scp_recv($connection2, '/mnt/test_thread_socket_client.c', '/mnt/1.c');
        }
}



執行所需時間比較:

抓一個檔案的回應時間
  1. Method 1:: Cost 0.77803492546082 sec 
  2. Method 2: Cost 1.3200099468231 sec 
  3. Method 3: Cost 0.63576698303223 sec 
當遇到空ip的時候的回應時間
  1. Method 1 : Cost 2.0159571170807 sec 
  2. Method 2: Cost 3.0096590518951 sec 
  3. Method 3: Cost 3.0093159675598 sec 
當密碼錯誤時的回應時間
  1. Method 1: Cost 5.2045171260834 sec 
  2. Method 2: Cost 無回應 
  3. Method 3: Cost 5.2065389156342 sec 
連結到win7時的回應時間 (取決於time-out設定)
  1. Method 1: Cost 60.061077833176 sec 
  2. Method 2: Cost 60.060883045197 sec 
  3. Method 3: Cost 60.060894012451 sec 
當遠端沒有此檔案時的回應時間
  1. Method 1:: Cost 0.797611951828 sec 
  2. Method 2: Cost 1.3146259784698 sec 
  3. Method 3: Cost 0.64013385772705 sec


    結論:
            方法三可以解決方法一的連鎖失敗和方法二的所需時間過長的問題,是目前我所使用的方式,但如果不考慮連續失敗的問題(單一指令)時,可以直接使用方法一,或者不考慮密碼會發生錯誤的情況下,直接使用方法三最內層的方式也是一種相當快的方式(scp 回應時間大概是0.3 sec),如果有錯請幫忙指正一下~感恩!