修改.vimrc文件,讓其支持 gb2312就行
          "設定文件編碼類型,徹底解決中文編碼問題
          let &termencoding=&encoding
          set fileencodings=utf-8,gbk,ucs-bom,cp936
          略微查了一下.vimrc中添加內容的含意,這篇文章有相關解釋。
          http://blog.dawnh.net/comment.php?type=trackback&entry_id=59
          內容如下:
          vim中編輯不同編碼的文件時需要注意的一些地方
          此文講解的是vim編輯多字節編碼文檔(中文)所要了解的一些基礎知識,注意其沒有涉及gvim,純指字符終端下的vim。
          vim編碼方面的基礎知識:
          1,存在3個變量:
          encoding----該選項使用于緩沖的文本(你正在編輯的文件),寄存器,Vim 腳本文件等等。你可以把 'encoding' 選項當作是對 Vim 內部運行機制的設定。
          fileencoding----該選項是vim寫入文件時采用的編碼類型。
          termencoding----該選項代表輸出到客戶終端(Term)采用的編碼類型。
          2,此3個變量的默認值:
          encoding----與系統當前locale相同,所以編輯文件的時候要考慮當前locale,否則要設置的東西就比較多了。
          fileencoding----vim打開文件時自動辨認其編碼,fileencoding就為辨認的值。為空則保存文件時采用encoding的編碼,如果沒有修改encoding,那值就是系統當前locale了。
          termencoding----默認空值,也就是輸出到終端不進行編碼轉換。
          由此可見,編輯不同編碼文件需要注意的地方不僅僅是這3個變量,還有系統當前locale和、文件本身編碼以及自動編碼識別、客戶運行vim的終端所使用的編碼類型3個關鍵點,這3個關鍵點影響著3個變量的設定。
          如果有人問:為什么我用vim打開中文文檔的時候出現亂碼?
          答案是不確定的,原因上面已經講了,不搞清楚這3個關鍵點和這3個變量的設定值,出現亂碼是正常的,倒是不出現亂碼那反倒是湊巧的。
          再來看一下常見情況下這三個關鍵點的值以及在這種情況下這3個變量的值:
          1,locale----目前大部分Linux系統已經將utf-8作為默認locale了,不過也有可能不是,例如有些系統使用中文locale
          zh_CN.GB18030。在locale為utf-8的情況下,啟動vim后encoding將會設置為utf-8,這是兼容性最好的方式,因為內部
          處理使用utf-8的話,無論外部存儲編碼為何都可以進行無缺損轉換。locale決定了vim內部處理數據的編碼,也就是encoding。
          2,文件的編碼以及自動編碼識別----這方面牽扯到各種編碼的規則,就不一一細講了。但需要明白的是,文件編碼類型并不是保存在文件內的,也
          就是說沒有任何描述性的字段來記錄文檔是何種編碼類型的。因此我們在編輯文檔的時候,要么必須知道這文檔保存時是以什么編碼保存的,要么通過另外的一些手
          段來斷定編碼類型,這另外的手段,就是通過某些編碼的碼表特征來斷定,例如每個字符占用的字節數,每個字符的ascii值是否都大于某個字段來斷定這個文
          件屬于何種編碼。這種方式vim也使用了,這就是vim的自動編碼識別機制了。但這種機制由于編碼各式各樣,不可能每種編碼都有顯著的特征來辨別,所以是
          不可能
          100%準確的。對于我們GB2312編碼,由于其中文是使用了2個acsii值高于127的字符組成漢字字符的,因此不可能把gb2312編碼的文件與
          latin1編碼區分開來,因此自動識別編碼的機制對于gb2312是不成功的,它只會將文件辨識為latin1編碼。此問題同樣出現在gbk,big5
          上等。因此我們在編輯此類文檔時,需要手工設定encoding和fileencoding。如果文檔編碼為utf-8時,一般vim都能自動識別正確的
          編碼。
          3,客戶運行vim的終端所使用的編碼類型----同第二條一樣,這也是一個比較難以斷定的關鍵點。第二個關鍵點決定著從文件讀取內容和寫入內容
          到文件時使用的編碼,而此關鍵點則決定vim輸出內容到終端時使用的編碼,如果此編碼類型和終端認為它收到的數據的編碼類型不同,則又會產生亂碼問題。在
          linux本地X環境下,一般終端都認為其接收的數據的編碼類型和系統locale類型相符,因此不需關心此方面是否存在問題。但如果牽涉到遠程終端,例
          如ssh登錄服務器,則問題就有可能出現了。例如從1臺locale為GB2310的系統(稱作客戶機)ssh到locale為utf-8的系統(稱作服
          務器)并開啟vim編輯文檔,在不加任何改動的情況下,服務器返回的數據為utf-8的,但客戶機認為服務器返回的數據是gb2312的,按照
          gb2312來解釋數據,則肯定就是亂碼了,這時就需要設置termencoding為gb2312來解決這個問題。此問題更多出現在我們的
          windows
          desktop機遠程ssh登錄服務器的情況下,這里牽扯到不同系統的編碼轉換問題。所以又與windows本身以及ssh客戶端有很大相關性。在
          windows下存在兩種編碼類型的軟件,一種是本身就為unicode編碼方式編寫的軟件,一種是ansi軟件,也就是程序處理數據直接采用字節流,不
          關心編碼。前一種程序可以在任何語言的windows上正確顯示多國語言,而后一種則編寫在何種語言的系統上則只能在何種語言的系統上顯示正確的文字。對
          于這兩種類型的程序,我們需要區別對待。以ssh客戶端為例,我們使用的putty是unicode軟件,而secure CRT則是ansi
          軟件。對于前者,我們要正確處理中文,只要保證vim輸出到終端的編碼為utf-8即可,就是termencoding=utf-8。但對于后者,一方面
          我們要確認我們的windows系統默認代碼頁為cp936(中文windows默認值),另一方面要確認vim設置的termencoding=
          cp936。
          最后來看看處理中文文檔最典型的幾種情況和設置方式:
          1,系統locale是utf-8(很多linux系統默認的locale形式),編輯的文檔是GB2312或GBK形式的(Windows記事
          本默認保存形式,大部分編輯器也默認保存為這個形式,所以最常見),終端類型utf-8(也就是假定客戶端是putty類的unicode軟件)
          則vim打開文檔后,encoding=utf-8(locale決定的),fileencoding=latin1(自動編碼判斷機制不準導致的),termencoding=空(默認無需轉換term編碼),顯示文件為亂碼。
          解決方案1:首先要修正fileencoding為cp936或者euc-cn(二者一樣的,只不過叫法不同),注意修正的方法不是:set
          fileencoding=cp936,這只是將文件保存為cp936,正確的方法是重新以cp936的編碼方式加載文件為:edit
          ++enc=cp936,可以簡寫為:e ++enc=cp936。
          解決方案2:臨時改變vim運行的locale環境,方法是以LANG=zh_CN vim
          abc.txt的方式來啟動vim,則此時encoding=euc-cn(locale決定的),fileencoding=空(此locale下文件
          編碼自動判別功能不啟用,所以fileencoding為文件本身編碼方式不變,也就是euc-cn),termencoding=空(默認值,為空則等
          于encoding)此時還是亂碼的,因為我們的ssh終端認為接受的數據為utf-8,但vim發送數據為euc-cn,所以還是不對。此時再用命令:
          set termencoding=utf-8將終端數據輸出為utf-8,則顯示正常。
          2,情況與1基本相同,只是使用的ssh軟件為secure CRT類ansi類軟件。
          vim打開文檔后,encoding=utf-8(locale決定的),fileencoding=latin1(自動編碼判斷機制不準導致的),termencoding=空(默認無需轉換term編碼),顯示文件為亂碼。
          解決方案1:首先要保證運行secure CRT的windows機器的默認代碼頁為CP936,這一點中文windows已經是默認設置了。其他的與上面方案1相同,只是要增加一步,:set termencoding=cp936
          解決方案2:與上面方案2類似,不過最后一步修改termencoding省略即可,在此情況下需要的修改最少,只要以locale為zh_CN
          開啟
          vim,則encoding=euc-cn,fileencoding和termencoding都為空即為encoding的值,是最理想的一種情況。
          可見理解這3個關鍵點和3個參數的意義,對于編碼問題有很大助力,以后就可以隨心所欲的處理文檔了,同時不僅僅是應用于vim,在其他需要編碼轉換的環境里,都可以應用類似的思路來處理問題解決問題。
          posted @ 2009-07-28 10:12 小馬歌 閱讀(182) | 評論 (0)編輯 收藏
           

          好兄弟友情支持的虛擬主機最近老出問題,仔細詢問了緣由,看來還是技術維護人員不到位造成,且服務器是Win2003+IIS,不穩定之余對PHP的支持也存在些微的問題. 不想去埋怨什么,期待早點完成維護即可.

            今天上午挺意外的發現服務器恢復,但我的Movie Castle頁面顯示卻很奇怪...全屏,且上方多了一行小空行,測試瀏覽器為IE7.然后去Firefox下查看,發現頁面的Width正常,但上方的小空行依然存在-.-

            我是善于Google的人,于是遇到不明白的先詢問這本百科全書. 得到的答案是主題PHP文件編碼是UTF-8 with bom造成的,至于這個bom是什么,看下這個中文解釋吧.

            在UCS 編碼中有一個叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,所以不應該出現在實際傳輸中。UCS規范建議我們在傳輸字節流前,先傳輸 字符"ZERO WIDTH NO-BREAK SPACE"。這樣如果接收者收到FEFF,就表明這個字節流是Big-Endian的;如果收到FFFE,就表明這個字節流是Little- Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被稱作BOM。

            UTF-8不需要BOM來表明字節順序,但可以用BOM來表明編碼方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF。所以如果接收者收到以EF BB BF開頭的字節流,就知道這是UTF-8編碼了。

            Windows就是使用BOM來標記文本文件的編碼方式的。

           

            很顯然...我的小空行是因為這個bom而產生的.

            找到問題后的就是解決問題.去WP群里問了聲,得到了一些建議,但個人覺得CSS樣式之前在相同的環境下沒有一點問題,沒理由現在突然顯示不了! 還是先解決已知問題吧...Google告訴我了很多去除bom的方法,但操作上來講都有點煩,最后終于找到了個稱心如意滴~muhahaha 一個自動移除bom的小程序...備份后大膽的試用,果然問題立刻解決.

           

          <?php
          //remove the utf-8 boms
          //by magicbug at gmail dot com

          if (isset($_GET['dir'])){ //config the basedir
          $basedir=$_GET['dir'];
          }else{
          $basedir = '.';
          }

          $auto = 1;

          checkdir($basedir);

          function checkdir($basedir){
          if ($dh = opendir($basedir)) {
             while (($file = readdir($dh)) !== false) {
              if ($file != '.' && $file != '..'){
               if (!is_dir($basedir."/".$file)) {
                echo "filename: $basedir/
          $file ".checkBOM("$basedir/$file")." <br>";
               }else{
                $dirname = $basedir."/".
          $file;
                checkdir($dirname);
               }
              }
             }
          closedir($dh);
          }
          }

          function checkBOM ($filename) {
          global $auto;
          $contents = file_get_contents($filename);
          $charset[1] = substr($contents, 0, 1);
          $charset[2] = substr($contents, 1, 1);
          $charset[3] = substr($contents, 2, 1);
          if (ord($charset[1]) == 239 && ord($charset[2]) == 187 &&
          ord($charset[3]) == 191) {
             if ($auto == 1) {
              $rest = substr($contents, 3);
              rewrite ($filename, $rest);
              return ("<font color=red>BOM found,
          automatically removed.</font>");
             } else {
              return ("<font color=red>BOM found.
          </font>");
             }
          }
          else return ("BOM Not Found.");
          }

          function rewrite ($filename, $data) {
          $filenum = fopen($filename, "w");
          flock($filenum, LOCK_EX);
          fwrite($filenum, $data);
          fclose($filenum);
          }
          ?>

          posted @ 2009-07-11 14:51 小馬歌 閱讀(521) | 評論 (0)編輯 收藏
           
          tcpdump采用命令行方式,它的命令格式為:
            tcpdump [ -adeflnNOpqStvx ] [ -c 數量 ] [ -F 文件名 ]
                    [ -i 網絡接口 ] [ -r 文件名] [ -s snaplen ]
                    [ -T 類型 ] [ -w 文件名 ] [表達式 ]

            1. tcpdump的選項介紹
             -a    將網絡地址和廣播地址轉變成名字;
             -d    將匹配信息包的代碼以人們能夠理解的匯編格式給出;
             -dd    將匹配信息包的代碼以c語言程序段的格式給出;
             -ddd    將匹配信息包的代碼以十進制的形式給出;
             -e    在輸出行打印出數據鏈路層的頭部信息;
             -f    將外部的Internet地址以數字的形式打印出來;
             -l    使標準輸出變為緩沖行形式;
             -n    不把網絡地址轉換成名字;
             -t    在輸出的每一行不打印時間戳;
             -v    輸出一個稍微詳細的信息,例如在ip包中可以包括ttl和服務類型的信息;
             -vv    輸出詳細的報文信息;
             -c    在收到指定的包的數目后,tcpdump就會停止;
             -F    從指定的文件中讀取表達式,忽略其它的表達式;
             -i    指定監聽的網絡接口;
             -r    從指定的文件中讀取包(這些包一般通過-w選項產生);
             -w    直接將包寫入文件中,并不分析和打印出來;
             -T    將監聽到的包直接解釋為指定的類型的報文,常見的類型有rpc (遠程過程
          調用)和snmp(簡單       網絡管理協議;)

            2. tcpdump的表達式介紹
             表達式是一個正則表達式,tcpdump利用它作為過濾報文的條件,如果一個報文滿足表
          達式的條件,則這個報文將會被捕獲。如果沒有給出任何條件,則網絡上所有的信息包將會
          被截獲。
             在表達式中一般如下幾種類型的關鍵字,一種是關于類型的關鍵字,主要包括host,
          net,port, 例如 host 210.27.48.2,指明 210.27.48.2是一臺主機,net 202.0.0.0 指明
          202.0.0.0是一個網絡地址,port 23 指明端口號是23。如果沒有指定類型,缺省的類型是
          host.
             第二種是確定傳輸方向的關鍵字,主要包括src , dst ,dst or src, dst and src ,
          這些關鍵字指明了傳輸的方向。舉例說明,src 210.27.48.2 ,指明ip包中源地址是210.27.
          48.2 , dst net 202.0.0.0 指明目的網絡地址是202.0.0.0 。如果沒有指明方向關鍵字,則
          缺省是src or dst關鍵字。
             第三種是協議的關鍵字,主要包括fddi,ip ,arp,rarp,tcp,udp等類型。Fddi指明是在
          FDDI(分布式光纖數據接口網絡)上的特定的網絡協議,實際上它是"ether"的別名,fddi和e
          ther具有類似的源地址和目的地址,所以可以將fddi協議包當作ether的包進行處理和分析。
          其他的幾個關鍵字就是指明了監聽的包的協議內容。如果沒有指定任何協議,則tcpdump將會
          監聽所有協議的信息包。
             除了這三種類型的關鍵字之外,其他重要的關鍵字如下:gateway, broadcast,less,
          greater,還有三種邏輯運算,取非運算是 'not ' '! ', 與運算是'and','&&';或運算 是'o
          r' ,'||';
             這些關鍵字可以組合起來構成強大的組合條件來滿足人們的需要,下面舉幾個例子來
          說明。
             (1)想要截獲所有210.27.48.1 的主機收到的和發出的所有的數據包:
              #tcpdump host 210.27.48.1
             (2) 想要截獲主機210.27.48.1 和主機210.27.48.2 或210.27.48.3的通信,使用命令
          :(在命令行中適用   括號時,一定要
              #tcpdump host 210.27.48.1 and \ (210.27.48.2 or 210.27.48.3 \)
             (3) 如果想要獲取主機210.27.48.1除了和主機210.27.48.2之外所有主機通信的ip包
          ,使用命令:
              #tcpdump ip host 210.27.48.1 and ! 210.27.48.2
             (4)如果想要獲取主機210.27.48.1接收或發出的telnet包,使用如下命令:
              #tcpdump tcp port 23 host 210.27.48.1

            3. tcpdump 的輸出結果介紹
             下面我們介紹幾種典型的tcpdump命令的輸出信息
             (1) 數據鏈路層頭信息
             使用命令#tcpdump --e host ice
             ice 是一臺裝有linux的主機,她的MAC地址是0:90:27:58:AF:1A
             H219是一臺裝有SOLARIC的SUN工作站,它的MAC地址是8:0:20:79:5B:46;上一條
          命令的輸出結果如下所示:
          21:50:12.847509 eth0 < 8:0:20:79:5b:46 0:90:27:58:af:1a ip 60: h219.33357 > ice.
          telne
          t 0:0(0) ack 22535 win 8760 (DF)
            分析:21:50:12是顯示的時間, 847509是ID號,eth0 <表示從網絡接口eth0 接受該
          數據包,eth0 >表示從網絡接口設備發送數據包, 8:0:20:79:5b:46是主機H219的MAC地址,它
          表明是從源地址H219發來的數據包. 0:90:27:58:af:1a是主機ICE的MAC地址,表示該數據包的
          目的地址是ICE . ip 是表明該數據包是IP數據包,60 是數據包的長度, h219.33357 > ice.
          telnet 表明該數據包是從主機H219的33357端口發往主機ICE的TELNET(23)端口. ack 22535
          表明對序列號是222535的包進行響應. win 8760表明發送窗口的大小是8760.

            (2) ARP包的TCPDUMP輸出信息
             使用命令#tcpdump arp
             得到的輸出結果是:
            22:32:42.802509 eth0 > arp who-has route tell ice (0:90:27:58:af:1a)
            22:32:42.802902 eth0 < arp reply route is-at 0:90:27:12:10:66 (0:90:27:58:af
          :1a)
            分析: 22:32:42是時間戳, 802509是ID號, eth0 >表明從主機發出該數據包, arp表明是
          ARP請求包, who-has route tell ice表明是主機ICE請求主機ROUTE的MAC地址。 0:90:27:5
          8:af:1a是主機ICE的MAC地址。

            (3) TCP包的輸出信息
             用TCPDUMP捕獲的TCP包的一般輸出信息是:
            src > dst: flags data-seqno ack window urgent options
            src > dst:表明從源地址到目的地址, flags是TCP包中的標志信息,S 是SYN標志, F (F
          IN), P (PUSH) , R (RST) "." (沒有標記); data-seqno是數據包中的數據的順序號, ack是
          下次期望的順序號, window是接收緩存的窗口大小, urgent表明數據包中是否有緊急指針.
          Options是選項.

            (4) UDP包的輸出信息
             用TCPDUMP捕獲的UDP包的一般輸出信息是:
            route.port1 > ice.port2: udp lenth
            UDP十分簡單,上面的輸出行表明從主機ROUTE的port1端口發出的一個UDP數據包到主機
          ICE的port2端口,類型是UDP, 包的長度是lenth


          應用:
          TCPDUMP簡介

          在傳統的網絡分析和測試技術中,嗅探器(sniffer)是最常見,也是最重要的技術之一。sniffer工具首先是為網絡管理員和網絡程序員進行網絡分析而設計的。對于網絡管理人員來說,使用嗅探器可以隨時掌握網絡的實際情況,在網絡性能急劇下降的時候,可以通過sniffer工具來分析原因,找出造成網絡阻塞的來源。對于網絡程序員來說,通過sniffer工具來調試程序。

          用過windows平臺上的sniffer工具(例如,netxray和sniffer pro軟件)的朋友可能都知道,在共享式的局域網中,采用sniffer工具簡直可以對網絡中的所有流量一覽無余!Sniffer工具實際上就是一個網絡上的抓包工具,同時還可以對抓到的包進行分析。由于在共享式的網絡中,信息包是會廣播到網絡中所有主機的網絡接口,只不過在沒有使用sniffer工具之前,主機的網絡設備會判斷該信息包是否應該接收,這樣它就會拋棄不應該接收的信息包,sniffer工具卻使主機的網絡設備接收所有到達的信息包,這樣就達到了網絡監聽的效果。

          Linux作為網絡服務器,特別是作為路由器和網關時,數據的采集和分析是必不可少的。所以,今天我們就來看看Linux中強大的網絡數據采集分析工具——TcpDump。

          用簡單的話來定義tcpdump,就是:dump the traffice on a network,根據使用者的定義對網絡上的數據包進行截獲的包分析工具。

          作為互聯網上經典的的系統管理員必備工具,tcpdump以其強大的功能,靈活的截取策略,成為每個高級的系統管理員分析網絡,排查問題等所必備的東東之一。

          顧名思義,TcpDump可以將網絡中傳送的數據包的“頭”完全截獲下來提供分析。它支持針對網絡層、協議、主機、網絡或端口的過濾,并提供and、or、not等邏輯語句來幫助你去掉無用的信息。

          tcpdump提供了源代碼,公開了接口,因此具備很強的可擴展性,對于網絡維護和入侵者都是非常有用的工具。tcpdump存在于基本的FreeBSD系統中,由于它需要將網絡界面設置為混雜模式,普通用戶不能正常執行,但具備root權限的用戶可以直接執行它來獲取網絡上的信息。因此系統中存在網絡分析工具主要不是對本機安全的威脅,而是對網絡上的其他計算機的安全存在威脅。

          普通情況下,直接啟動tcpdump將監視第一個網絡界面上所有流過的數據包。
          -----------------------
          bash-2.02# tcpdump
          tcpdump: listening on eth0
          11:58:47.873028 202.102.245.40.netbios-ns > 202.102.245.127.netbios-ns: udp 50
          11:58:47.974331 0:10:7b:8:3a:56 > 1:80:c2:0:0:0 802.1d ui/C len=43
          0000 0000 0080 0000 1007 cf08 0900 0000
          0e80 0000 902b 4695 0980 8701 0014 0002
          000f 0000 902b 4695 0008 00
          11:58:48.373134 0:0:e8:5b:6d:85 > Broadcast sap e0 ui/C len=97
          ffff 0060 0004 ffff ffff ffff ffff ffff
          0452 ffff ffff 0000 e85b 6d85 4008 0002
          0640 4d41 5354 4552 5f57 4542 0000 0000
          0000 00
          ^C
          ------------------------

          首先我們注意一下,從上面的輸出結果上可以看出來,基本上tcpdump總的的輸出格式為:系統時間 來源主機.端口 > 目標主機.端口 數據包參數

          TcpDump的參數化支持

            tcpdump支持相當多的不同參數,如使用-i參數指定tcpdump監聽的網絡界面,這在計算機具有多個網絡界面時非常有用,使用-c參數指定要監聽的數據包數量,使用-w參數指定將監聽到的數據包寫入文件中保存,等等。

            然而更復雜的tcpdump參數是用于過濾目的,這是因為網絡中流量很大,如果不加分辨將所有的數據包都截留下來,數據量太大,反而不容易發現需要的數據包。使用這些參數定義的過濾規則可以截留特定的數據包,以縮小目標,才能更好的分析網絡中存在的問題。tcpdump使用參數指定要監視數據包的類型、地址、端口等,根據具體的網絡問題,充分利用這些過濾規則就能達到迅速定位故障的目的。請使用man tcpdump查看這些過濾規則的具體用法。

            顯然為了安全起見,不用作網絡管理用途的計算機上不應該運行這一類的網絡分析軟件,為了屏蔽它們,可以屏蔽內核中的bpfilter偽設備。一般情況下網絡硬件和TCP/IP堆棧不支持接收或發送與本計算機無關的數據包,為了接收這些數據包,就必須使用網卡的混雜模式,并繞過標準的TCP/IP堆棧才行。在FreeBSD下,這就需要內核支持偽設備bpfilter。因此,在內核中取消bpfilter支持,就能屏蔽tcpdump之類的網絡分析工具。

            并且當網卡被設置為混雜模式時,系統會在控制臺和日志文件中留下記錄,提醒管理員留意這臺系統是否被用作攻擊同網絡的其他計算機的跳板。

            May 15 16:27:20 host1 /kernel: fxp0: promiscuous mode enabled

            雖然網絡分析工具能將網絡中傳送的數據記錄下來,但是網絡中的數據流量相當大,如何對這些數據進行分析、分類統計、發現并報告錯誤卻是更關鍵的問題。網絡中的數據包屬于不同的協議,而不同協議數據包的格式也不同。因此對捕獲的數據進行解碼,將包中的信息盡可能的展示出來,對于協議分析工具來講更為重要。昂貴的商業分析工具的優勢就在于它們能支持很多種類的應用層協議,而不僅僅只支持tcp、udp等低層協議。

            從上面tcpdump的輸出可以看出,tcpdump對截獲的數據并沒有進行徹底解碼,數據包內的大部分內容是使用十六進制的形式直接打印輸出的。顯然這不利于分析網絡故障,通常的解決辦法是先使用帶-w參數的tcpdump 截獲數據并保存到文件中,然后再使用其他程序進行解碼分析。當然也應該定義過濾規則,以避免捕獲的數據包填滿整個硬盤。

          TCP功能

          數據過濾

          不帶任何參數的TcpDump將搜索系統中所有的網絡接口,并顯示它截獲的所有數據,這些數據對我們不一定全都需要,而且數據太多不利于分析。所以,我們應當先想好需要哪些數據,TcpDump提供以下參數供我們選擇數據:

          -b 在數據-鏈路層上選擇協議,包括ip、arp、rarp、ipx都是這一層的。

          例如:tcpdump -b arp 將只顯示網絡中的arp即地址轉換協議信息。

          -i 選擇過濾的網絡接口,如果是作為路由器至少有兩個網絡接口,通過這個選項,就可以只過濾指定的接口上通過的數據。例如:

          tcpdump -i eth0 只顯示通過eth0接口上的所有報頭。

          src、dst、port、host、net、ether、gateway這幾個選項又分別包含src、dst 、port、host、net、ehost等附加選項。他們用來分辨數據包的來源和去向,src host 192.168.0.1指定源主機IP地址是192.168.0.1,dst net 192.168.0.0/24指定目標是網絡192.168.0.0。以此類推,host是與其指定主機相關無論它是源還是目的,net是與其指定網絡相關的,ether后面跟的不是IP地址而是物理地址,而gateway則用于網關主機。可能有點復雜,看下面例子就知道了:

          tcpdump src host 192.168.0.1 and dst net 192.168.0.0/24

          過濾的是源主機為192.168.0.1與目的網絡為192.168.0.0的報頭。

          tcpdump ether src 00:50:04:BA:9B and dst……

          過濾源主機物理地址為XXX的報頭(為什么ether src后面沒有host或者net?物理地址當然不可能有網絡嘍)。

          Tcpdump src host 192.168.0.1 and dst port not telnet

          過濾源主機192.168.0.1和目的端口不是telnet的報頭。

          ip icmp arp rarp 和 tcp、udp、icmp這些選項等都要放到第一個參數的位置,用來過濾數據報的類型。
          例如:

          tcpdump ip src……

          只過濾數據-鏈路層上的IP報頭。

          tcpdump udp and src host 192.168.0.1

          只過濾源主機192.168.0.1的所有udp報頭。

          數據顯示/輸入輸出

          TcpDump提供了足夠的參數來讓我們選擇如何處理得到的數據,如下所示:

          -l 可以將數據重定向。

          如tcpdump -l >tcpcap.txt將得到的數據存入tcpcap.txt文件中。

          -n 不進行IP地址到主機名的轉換。

          如果不使用這一項,當系統中存在某一主機的主機名時,TcpDump會把IP地址轉換為主機名顯示,就像這樣:eth0 < ntc9.1165> router.domain.net.telnet,使用-n后變成了:eth0 < 192.168.0.9.1165 > 192.168.0.1.telnet。

          -nn 不進行端口名稱的轉換。

          上面這條信息使用-nn后就變成了:eth0 < ntc9.1165 > router.domain.net.23。

          -N 不打印出默認的域名。

          還是這條信息-N 后就是:eth0 < ntc9.1165 > router.telnet。

          -O 不進行匹配代碼的優化。
          -t 不打印UNIX時間戳,也就是不顯示時間。
          -tt 打印原始的、未格式化過的時間。
          -v 詳細的輸出,也就比普通的多了個TTL和服務類型。

           
          TCPDUMP的安裝

           在linux下tcpdump的安裝十分簡單,一般由兩種安裝方式。一種是以rpm包的形式來進行安裝。另外一種是以源程序的形式安裝。
            1. rpm包的形式安裝
              #rpm -ivh tcpdump-3_4a5.rpm
            這樣tcpdump就順利地安裝到你的linux系統中。怎么樣,很簡單吧。
            2. 源程序的安裝
               #tar xvfz tcpdump-3_4a5.tar.Z
              rpm的包可以使用如下命令安裝:
               #rpm -ivh tcpdump-3_4a5.src.rpm
              這樣就把tcpdump的源代碼解壓到/usr/src/redhat/SOURCES目錄下.

          第二步 做好編譯源程序前的準備活動

          在編譯源程序之前,最好已經確定庫文件libpcap已經安裝完畢,這個庫文件是tcpdump軟件所需的庫文件 。同樣,你同時還要有一個標準的c語言編譯器。在linux下標準的c 語言編譯器一般是gcc。 在tcpdump的源程序目錄中。有一個文件是Makefile.in,configure命令就是從Makefile.in文件中自動產生Makefile文件。在Makefile.in文件中,可以根據系統的配置來修改BINDEST 和 MANDEST 這兩個宏定義,缺省值是
                BINDEST = @sbindir@
                MANDEST = @mandir@
           
          第一個宏值表明安裝tcpdump的二進制文件的路徑名,第二個表明tcpdump的man 幫助頁的路徑名,你可以修改它們來滿足系統的需求。

            第三步 編譯源程序
           
          使用源程序目錄中的configure腳本,它從系統中讀出各種所需的屬性。并且根據Makefile.in文件自動生成Makefile文件,以便編譯使用.make 命令則根據Makefile文件中的規則編譯tcpdump的源程序。使用make install命令安裝編譯好的tcpdump的二進制文件。
           
          總結一下就是:
           
                # tar xvfz tcpdump-3_4a5.tar.Z
                # vi Makefile.in
                # . /configure
                # make
                # make install
          posted @ 2009-07-10 12:44 小馬歌 閱讀(144) | 評論 (0)編輯 收藏
           
          調用:
          strace [ -dffhiqrtttTvxx ] [ -acolumn ] [ -eexpr ] ...
          [ -ofile ] [ -ppid ] ... [ -sstrsize ] [ -uusername ] [ command [ arg ... ] ]

          strace -c [ -eexpr ] ... [ -Ooverhead ] [ -Ssortby ] [ command [ arg ... ] ]
          功能:
          跟蹤程式執行時的系統調用和所接收的信號.通常的用法是strace執行一直到commande結束.
          并且將所調用的系統調用的名稱、參數和返回值輸出到標準輸出或者輸出到-o指定的文件.
          strace是一個功能強大的調試,分析診斷工具.你將發現他是一個極好的幫手在你要調試一個無法看到源碼或者源碼無法在編譯的程序.
          你將輕松的學習到一個軟件是如何通過系統調用來實現他的功能的.而且作為一個程序設計師,你可以了解到在用戶態和內核態是如何通過系統調用和信號來實現程序的功能的.
          strace的每一行輸出包括系統調用名稱,然后是參數和返回值.這個例子:
          strace cat /dev/null
          他的輸出會有:
          open(\\"/dev/null\\",O_RDONLY) = 3
          有錯誤產生時,一般會返回-1.所以會有錯誤標志和描述:
          open(\\"/foor/bar\\",)_RDONLY) = -1 ENOENT (no such file or directory)
          信號將輸出喂信號標志和信號的描述.跟蹤并中斷這個命令\\"sleep 600\\":
          sigsuspend({}
          --- SIGINT (Interrupt) ---
          +++ killed by SIGINT +++
          參數的輸出有些不一致.如shell命令中的 \\">>tmp\\",將輸出:
          open(\\"tmp\\",O_WRONLY|O_APPEND|A_CREAT,0666) = 3
          對于結構指針,將進行適當的顯示.如:\\"ls -l /dev/null\\":
          lstat(\\"/dev/null\\",{st_mode=S_IFCHR|0666},st_rdev=makdev[1,3],...}) = 0
          請注意\\"struct stat\\" 的聲明和這里的輸出.lstat的第一個參數是輸入參數,而第二個參數是向外傳值.
          當你嘗試\\"ls -l\\" 一個不存在的文件時,會有:
          lstat(/foot/ball\\",0xb004) = -1 ENOENT (no such file or directory)
          char*將作為C的字符串類型輸出.沒有字符串輸出時一般是char* 是一個轉義字符,只輸出字符串的長度.
          當字符串過長是會使用\\"...\\"省略.如在\\"ls -l\\"會有一個gepwuid調用讀取password文件:
          read(3,\\"root::0:0:System Administrator:/\\"...,1024) = 422
          當參數是結構數組時,將按照簡單的指針和數組輸出如:
          getgroups(4,[0,2,4,5]) = 4
          關于bit作為參數的情形,也是使用方括號,并且用空格將每一項參數隔開.如:
          sigprocmask(SIG_BLOCK,[CHLD TTOU],[]) = 0
          這里第二個參數代表兩個信號SIGCHLD 和 SIGTTOU.如果bit型參數全部置位,則有如下的輸出:
          sigprocmask(SIG_UNBLOCK,~[],NULL) = 0
          這里第二個參數全部置位.

          參數說明:
          -c 統計每一系統調用的所執行的時間,次數和出錯的次數等.
          -d 輸出strace關于標準錯誤的調試信息.
          -f 跟蹤由fork調用所產生的子進程.
          -ff 如果提供-o filename,則所有進程的跟蹤結果輸出到相應的filename.pid中,pid是各進程的進程號.
          -F 嘗試跟蹤vfork調用.在-f時,vfork不被跟蹤.
          -h 輸出簡要的幫助信息.
          -i 輸出系統調用的入口指針.
          -q 禁止輸出關于脫離的消息.
          -r 打印出相對時間關于,,每一個系統調用.
          -t 在輸出中的每一行前加上時間信息.
          -tt 在輸出中的每一行前加上時間信息,微秒級.
          -ttt 微秒級輸出,以秒了表示時間.
          -T 顯示每一調用所耗的時間.
          -v 輸出所有的系統調用.一些調用關于環境變量,狀態,輸入輸出等調用由于使用頻繁,默認不輸出.
          -V 輸出strace的版本信息.
          -x 以十六進制形式輸出非標準字符串
          -xx 所有字符串以十六進制形式輸出.
          -a column
          設置返回值的輸出位置.默認為40.
          -e expr
          指定一個表達式,用來控制如何跟蹤.格式如下:
          [qualifier=][!]value1[,value2]...
          qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用來限定的符號或數字.默認的qualifier是 trace.感嘆號是否定符號.例如:
          -eopen等價于 -e trace=open,表示只跟蹤open調用.而-etrace!=open表示跟蹤除了open以外的其他調用.有兩個特殊的符號 all 和 none.
          注意有些shell使用!來執行歷史記錄里的命令,所以要使用\\\\.
          -e trace=set
          只跟蹤指定的系統調用.例如:-e trace=open,close,rean,write表示只跟蹤這四個系統調用.默認的為set=all.
          -e trace=file
          只跟蹤有關文件操作的系統調用.
          -e trace=process
          只跟蹤有關進程控制的系統調用.
          -e trace=network
          跟蹤與網絡有關的所有系統調用.
          -e strace=signal
          跟蹤所有與系統信號有關的系統調用
          -e trace=ipc
          跟蹤所有與進程通訊有關的系統調用
          -e abbrev=set
          設定strace輸出的系統調用的結果集.-v 等與 abbrev=none.默認為abbrev=all.
          -e raw=set
          將指定的系統調用的參數以十六進制顯示.
          -e signal=set
          指定跟蹤的系統信號.默認為all.如signal=!SIGIO(或者signal=!io),表示不跟蹤SIGIO信號.
          -e read=set
          輸出從指定文件中讀出的數據.例如:
          -e read=3,5
          -e write=set
          輸出寫入到指定文件中的數據.
          -o filename
          strace的輸出寫入文件filename
          -p pid
          跟蹤指定的進程pid.
          -s strsize
          指定輸出的字符串的最大長度.默認為32.文件名一直全部輸出.
          -u username
          以username的UID和GID執行被跟蹤的命令.

          strace調試程序

               在理想世界里,每當一個程序不能正常執行一個功能時,它就會給出一個有用的錯誤提示,告訴你在足夠的改正錯誤的線索。但遺憾的是,我們不是生活在理想世界里,起碼不總是生活在理想世界里。有時候一個程序出現了問題,你無法找到原因。

          這就是調試程序出現的原因。strace是一個必不可少的調試工具,strace用來監視系統調用。你不僅可以調試一個新開始的程序,也可以調試一個已經在運行的程序(把strace綁定到一個已有的PID上面)。

          首先讓我們看一個真實的例子:

          [BOLD]啟動KDE時出現問題[/BOLD]

          前一段時間,我在啟動KDE的時候出了問題,KDE的錯誤信息無法給我任何有幫助的線索。

          代碼:

          _KDE_IceTransSocketCreateListener: failed to bind listener
          _KDE_IceTransSocketUNIXCreateListener: ...SocketCreateListener() failed
          _KDE_IceTransMakeAllCOTSServerListeners: failed to create listener for local

          Cannot establish any listening sockets DCOPServer self-test failed.

          對我來說這個錯誤信息沒有太多意義,只是一個對KDE來說至關重要的負責進程間通信的程序無法啟動。我還可以知道這個錯誤和ICE協議(Inter Client Exchange)有關,除此之外,我不知道什么是KDE啟動出錯的原因。

          我決定采用strace看一下在啟動dcopserver時到底程序做了什么:

          代碼:

          strace -f -F -o ~/dcop-strace.txt dcopserver

          這里 -f -F選項告訴strace同時跟蹤fork和vfork出來的進程,-o選項把所有strace輸出寫到~/dcop-strace.txt里面,dcopserver是要啟動和調試的程序。

          再次出現錯誤之后,我檢查了錯誤輸出文件dcop-strace.txt,文件里有很多系統調用的記錄。在程序運行出錯前的有關記錄如下:

          代碼:

          27207 mkdir("/tmp/.ICE-unix", 0777) = -1 EEXIST (File exists)
          27207 lstat64("/tmp/.ICE-unix", {st_mode=S_IFDIR|S_ISVTX|0755, st_size=4096, ...}) = 0
          27207 unlink("/tmp/.ICE-unix/dcop27207-1066844596") = -1 ENOENT (No such file or directory)
          27207 bind(3, {sin_family=AF_UNIX, path="/tmp/.ICE-unix/dcop27207-1066844596"}, 3 = -1 EACCES (Permission denied)
          27207 write(2, "_KDE_IceTrans", 13) = 13
          27207 write(2, "SocketCreateListener: failed to "..., 46) = 46
          27207 close(3) = 0 27207 write(2, "_KDE_IceTrans", 13) = 13
          27207 write(2, "SocketUNIXCreateListener: ...Soc"..., 59) = 59
          27207 umask(0) = 0 27207 write(2, "_KDE_IceTrans", 13) = 13
          27207 write(2, "MakeAllCOTSServerListeners: fail"..., 64) = 64
          27207 write(2, "Cannot establish any listening s"..., 39) = 39

          其中第一行顯示程序試圖創建/tmp/.ICE-unix目錄,權限為0777,這個操作因為目錄已經存在而失敗了。第二個系統調用(lstat64)檢查 了目錄狀態,并顯示這個目錄的權限是0755,這里出現了第一個程序運行錯誤的線索:程序試圖創建屬性為0777的目錄,但是已經存在了一個屬性為 0755的目錄。第三個系統調用(unlink)試圖刪除一個文件,但是這個文件并不存在。這并不奇怪,因為這個操作只是試圖刪掉可能存在的老文件。

          但是,第四行確認了錯誤所在。他試圖綁定到/tmp/.ICE-unix/dcop27207-1066844596,但是出現了拒絕訪問錯誤。. ICE_unix目錄的用戶和組都是root,并且只有所有者具有寫權限。一個非root用戶無法在這個目錄下面建立文件,如果把目錄屬性改成0777, 則前面的操作有可能可以執行,而這正是第一步錯誤出現時進行過的操作。

          所以我運行了chmod 0777 /tmp/.ICE-unix之后KDE就可以正常啟動了,問題解決了,用strace進行跟蹤調試只需要花很短的幾分鐘時間跟蹤程序運行,然后檢查并分析輸出文件。

          說明:運行chmod 0777只是一個測試,一般不要把一個目錄設置成所有用戶可讀寫,同時不設置粘滯位(sticky bit)。給目錄設置粘滯位可以阻止一個用戶隨意刪除可寫目錄下面其他人的文件。一般你會發現/tmp目錄因為這個原因設置了粘滯位。KDE可以正常啟動 之后,運行chmod +t /tmp/.ICE-unix給.ICE_unix設置粘滯位。

          解決庫依賴問題

          starce 的另一個用處是解決和動態庫相關的問題。當對一個可執行文件運行ldd時,它會告訴你程序使用的動態庫和找到動態庫的位置。但是如果你正在使用一個比較老 的glibc版本(2.2或更早),你可能會有一個有bug的ldd程序,它可能會報告在一個目錄下發現一個動態庫,但是真正運行程序時動態連接程序 (/lib/ld-linux.so.2)卻可能到另外一個目錄去找動態連接庫。這通常因為/etc/ld.so.conf和 /etc/ld.so.cache文件不一致,或者/etc/ld.so.cache被破壞。在glibc 2.3.2版本上這個錯誤不會出現,可能ld-linux的這個bug已經被解決了。

          盡管這樣,ldd并不能把所有程序依賴的動態庫列出 來,系統調用dlopen可以在需要的時候自動調入需要的動態庫,而這些庫可能不會被ldd列出來。作為glibc的一部分的NSS (Name Server Switch)庫就是一個典型的例子,NSS的一個作用就是告訴應用程序到哪里去尋找系統帳號數據庫。應用程序不會直接連接到NSS庫,glibc則會通 過dlopen自動調入NSS庫。如果這樣的庫偶然丟失,你不會被告知存在庫依賴問題,但這樣的程序就無法通過用戶名解析得到用戶ID了。讓我們看一個例 子:

          whoami程序會給出你自己的用戶名,這個程序在一些需要知道運行程序的真正用戶的腳本程序里面非常有用,whoami的一個示例輸出如下:
          代碼:

          # whoami
          root

          假設因為某種原因在升級glibc的過程中負責用戶名和用戶ID轉換的庫NSS丟失,我們可以通過把nss庫改名來模擬這個環境:
          代碼:

          # mv /lib/libnss_files.so.2 /lib/libnss_files.so.2.backup
          # whoami
          whoami: cannot find username for UID 0

          這里你可以看到,運行whoami時出現了錯誤,ldd程序的輸出不會提供有用的幫助:
          代碼:

          # ldd /usr/bin/whoami
          libc.so.6 => /lib/libc.so.6 (0x4001f000)
          /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

          你只會看到whoami依賴Libc.so.6和ld-linux.so.2,它沒有給出運行whoami所必須的其他庫。這里時用strace跟蹤whoami時的輸出:
          代碼:

          strace -o whoami-strace.txt whoami

          open("/lib/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
          open("/lib/i686/mmx/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
          stat64("/lib/i686/mmx", 0xbffff190) = -1 ENOENT (No such file or directory)
          open("/lib/i686/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
          stat64("/lib/i686", 0xbffff190) = -1 ENOENT (No such file or directory)
          open("/lib/mmx/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
          stat64("/lib/mmx", 0xbffff190) = -1 ENOENT (No such file or directory)
          open("/lib/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
          stat64("/lib", {st_mode=S_IFDIR|0755, st_size=2352, ...}) = 0
          open("/usr/lib/i686/mmx/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
          stat64("/usr/lib/i686/mmx", 0xbffff190) = -1 ENOENT (No such file or directory)
          open("/usr/lib/i686/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)

          你可以發現在不同目錄下面查找libnss.so.2的嘗試,但是都失敗了。如果沒有strace這樣的工具,很難發現這個錯誤是由于缺少動態庫造成的。現在只需要找到libnss.so.2并把它放回到正確的位置就可以了。

          限制strace只跟蹤特定的系統調用

          如果你已經知道你要找什么,你可以讓strace只跟蹤一些類型的系統調用。例如,你需要看看在configure腳本里面執行的程序,你需要監視的系統調用就是execve。讓strace只記錄execve的調用用這個命令:

          代碼:

          strace -f -o configure-strace.txt -e execve ./configure

          部分輸出結果為:
          代碼:

          2720 execve("/usr/bin/expr", ["expr", "a", ":", "(a)"], [/* 31 vars */]) = 0
          2725 execve("/bin/basename", ["basename", "./configure"], [/* 31 vars */]) = 0
          2726 execve("/bin/chmod", ["chmod", "+x", "conftest.sh"], [/* 31 vars */]) = 0
          2729 execve("/bin/rm", ["rm", "-f", "conftest.sh"], [/* 31 vars */]) = 0
          2731 execve("/usr/bin/expr", ["expr", "99", "+", "1"], [/* 31 vars */]) = 0
          2736 execve("/bin/ln", ["ln", "-s", "conf2693.file", "conf2693"], [/* 31 vars */]) = 0

          你 已經看到了,strace不僅可以被程序員使用,普通系統管理員和用戶也可以使用strace來調試系統錯誤。必須承認,strace的輸出不總是容易理 解,但是很多輸出對大多數人來說是不重要的。你會慢慢學會從大量輸出中找到你可能需要的信息,像權限錯誤,文件未找到之類的,那時strace就會成為一 個有力的工具了。
          posted @ 2009-07-10 12:27 小馬歌 閱讀(576) | 評論 (0)編輯 收藏
           

          from : http://hi.baidu.com/xiaochongs/blog/item/23a70b5592e662c4b645aef2.html

          Windows系統一樣Linux也有靜態/動態鏈接庫,下面介紹創建和使用方法: 
             

          假設有下面幾個文件: 
          頭文件String.h,聲明相關函數原形,內容如下: 
          Strlen.c
          :函數Strlen的實現,獲取給定字符串的長度,內容如下: 
          Strlnen.c
          :函數StrNlen的實現,獲取給定字符串的長度,如果輸入字符串的長度大于指定的最大長度,則返回最大長度,否者返回字符串的實際長度,內容如下: 
          生成靜態庫: 
           
          利用GCC生成對應目標文件: 
          gcc –c Strlen.c Strnlen.c 
          如果對應的文件沒有錯誤,gcc會對文件進行編譯生成Strlen.oStrnlen.o兩個目標文件(相當于windows下的obj文件)。然后用ar創建一個名字為libstr.a的庫文件,并把Strlen.o Strnlen.o的內容插入到對應的庫文件中。,相關命令如下: 
          ar –rc libstr.a Strlen.o Strnlen.o 
          命令執行成功以后,對應的靜態庫libstr.a已經成功生成。 

          /*********************************** 
          Filename : String.h 
          Description : 
          Author   : HCJ 
          Date     : 2006-5-7 
          ************************************/ 

          int Strlen(char *pStr); 
          int StrNlen(char *pStr, unsigned long ulMaxLen); 



          /************************************** 
          Filename    : get string length 
          Description  :  
          Author      : HCJ 
          Date        : 2006/5/7 
          **************************************/ 
          #include<stdio.h> 
          #include<assert.h> 
          int Strlen(char *pStr) 

              unsigned long ulLength; 
              assert(NULL != pStr); 
              ulLength = 0; 
              while(*pStr++) 
              { 
                  ulLength++; 
              } 
              return ulLength; 




          ********************************************** 
          Fileneme: mystrnlen.c 
          Description: get input string length,if string large 
                       max length input return max length, 
                       else real length 
          Author: HCJ 
          Date  : 2006-5-7 
          **********************************************/ 
          #include<stdio.h> 
          #include<assert.h> 
          int StrNlen(char *pStr, unsigned long ulMaxLen) 

              unsigned long ulLength; 
              assert(NULL != pStr); 
              if(ulMaxLen <= 0) 
              { 
                  printf("Wrong Max Length!\n"); 
                  return -1; 
              } 
              ulLength = 0; 
              while(*pStr++ &&  ulLength < ulMaxLen) 
              { 
                  ulLength++; 
              } 
              return ulLength; 
          }




          生成動態鏈接庫: 
           gcc  -fpic -shared -o libstr.so  Strlen.c Strnlen.c 
          -fpic 
          使輸出的對象模塊是按照可重定位地址方式生成的。 
          -shared
          指定把對應的源文件生成對應的動態鏈接庫文件libstr.so文件。 
          對應的鏈接庫已經生成,下面看一下如何使用對應的鏈接庫。 
          靜態庫的使用: 
          假設有下面的文件要使用對應的的靜態庫
          編譯生成對應的目標文件: 
          gcc -c -I/home/hcj/xxxxxxxx main.c  
          生成可執行文件: 
          gcc -o main1 -L/home/hcj/xxxxxxxx main.o libstr.a  
          其中-I/home/hcj/xxxxxxxx-L/home/hcj/xxxxxxxx是通過-I-L指定對應的頭文件和庫文件的路徑。libstr.a是對應的靜態庫的名稱。這樣對應的靜態庫已經編譯到對應的可執行程序中。執行對應的可執行文件便可以對應得函數調用的結果。 

          /***************************************** 
          FileName: main.c 
          Description: test static/dynamic library 
          Author: HCJ 
          Date  : 2005-5-7 
          ******************************************/ 
          #include<stdio.h> 
          #include <String.h>   //
          靜態庫對應函數的頭文件 
          int main(int argc, char* argv[]) 

              char str[] = {"hello world"}; 
              unsigned long ulLength = 0; 
              printf("The string is : %s\n", str); 
              ulLength = Strlen(str); 
              printf("The string length is : %d(use Strlen)\n", ulLength); 
              ulLength = StrNlen(str, 10); 
              printf("The string length is : %d(use StrNlen)\n", ulLength); 
              return 0; 




          動態庫的分為隱式調用和顯式調用兩種調用方法: 
          隱式調用的使用使用方法和靜態庫的調用差不多,具體方法如下: 
          gcc -c -I/home/hcj/xxxxxxxx main.c  
          gcc -o main1 -L/home/hcj/xxxxxxxx main.o libstr.so  //
          這里是*.so 
          在這種調用方式中,需要維護動態鏈接庫的配置文件/etc/ld.so.conf來讓動態鏈接庫為系統所使用,通常將動態鏈接庫所在目錄名追加到動態鏈接庫配置文件中。否則在執行相關的可執行文件的時候就會出現載入動態鏈接庫失敗的現象。在編譯所引用的動態庫時,可以在gcc采用 –l-L選項或直接引用所需的動態鏈接庫方式進行編譯。在Linux里面,可以采用ldd命令來檢查程序依賴共享庫。 
          顯式調用: 

          /***************************************** 
          FileName: main2.c 
          Description: test static/dynamic library 
          Author: HCJ 
          Date  : 2005-5-7 
          ******************************************/ 
          #include<stdio.h> 
          #include<dlfcn.h> 
          int main(int argc, char* argv[]) 

              //define function pointor 
              int (*pStrlenFun)(char* pStr);     //
          聲明對應的函數的函數指針 
              int (*pStrnlenFun)(char* pStr, int ulMaxLen); 
              char str[] = {"hello world"}; 
              unsigned long ulLength = 0; 
              void *pdlHandle; 
              char *pszErr; 
              pdlHandle = dlopen("./libstr.so", RTLD_LAZY);  //
          加載鏈接庫/libstr.so 
              if(!pdlHandle) 
              { 
                  printf("Failed load library\n"); 
              } 
              pszErr = dlerror(); 
              if(pszErr != NULL) 
              { 
                  printf("%s\n", pszErr); 
                  return 0; 
              } 
              //get function from lib 
              pStrlenFun = dlsym(pdlHandle, "Strlen"); //
          獲取函數的地址 
              pszErr = dlerror(); 
              if(pszErr != NULL) 
              { 
                  printf("%s\n", pszErr); 
                  return 0; 
              } 
              pStrnlenFun = dlsym(pdlHandle, "StrNlen"); 
              pszErr = dlerror(); 
              if(pszErr != NULL) 
              { 
                  printf("%s\n", pszErr); 
                  return 0; 
              } 
              printf("The string is : %s\n", str); 
              ulLength = pStrlenFun(str);   //
          調用相關的函數 
              printf("The string length is : %d(use Strlen)\n", ulLength); 
              ulLength = pStrnlenFun(str, 10); 
              printf("The string length is : %d(use StrNlen)\n", ulLength); 
           dlclose(pdlHandle); 
              return 0; 





          gcc -o mian2 -ldl main2.c 

          gcc編譯對應的源文件生成可執行文件,-ldl選項,表示生成的對象模塊需要使用共享庫。執行對應得文件同樣可以得到正確的結果。 
          相關函數的說明如下: 
          (1)dlopen() 
          第一個參數:指定共享庫的名稱,將會在下面位置查找指定的共享庫。 
          -環境變量LD_LIBRARY_PATH列出的用分號間隔的所有目錄。 
          -文件/etc/ld.so.cache中找到的庫的列表,用ldconfig維護。 
          -目錄usr/lib 
          -目錄/lib 
          -當前目錄。 
          第二個參數:指定如何打開共享庫。 
          RTLD_NOW:將共享庫中的所有函數加載到內存 
          RTLD_LAZY:會推后共享庫中的函數的加載操作,直到調用dlsym()時方加載某函數 
          (2)dlsym() 
          調用dlsym時,利用dlopen()返回的共享庫的phandle以及函數名稱作為參數,返回要加載函數的入口地址。 
          (3)dlerror() 
          該函數用于檢查調用共享庫的相關函數出現的錯誤。 
           
          這樣我們就用簡單的例子說明了在Linux下靜態/動態庫的創建和使用。                                                                                                                                                                                                                                                      

          posted @ 2009-07-10 11:54 小馬歌 閱讀(284) | 評論 (0)編輯 收藏
           
          from :http://blog.163.com/qj_l12@126/blog/static/35930826200852724816969/

          本文將討論在PHP4環境下如何使用進程間通訊機制——IPC(Inter-Process-Communication)。本文討論的軟件環境是linux+php4.0.4或更高版本。首先,我們假設你已經裝好了PHP4和UNIX, 為了使得php4可以使用共享內存和信號量,必須在編譯php4程序時激活shmop和sysvsem這兩個擴展模塊。

            實現方法:在PHP設定(configure)時加入如下選項。

          --enable-shmop --enable-sysvsem 

            這樣就使得你的PHP系統可以處理相關的IPC函數了。

            IPC是什么?

            IPC (Inter-process communication) 是一個Unix標準通訊機制,它提供了使得在同一臺主機不同進程之間可以互相通訊的方法。基本的IPC處理機制有3種:它們分別是共享內存、信號量和消息隊列。本文中我們主要討論共享內存和信號量的使用。關于消息隊列,筆者在不久的將來還會專門介紹。

            在PHP中使用共享內存段

            在不同的處理進程之間使用共享內存是一個實現不同進程之間相互通訊的好方法。如果你在一個進程中向所共享的內存寫入一段信息,那么所有其他的進程也可以看到這段被寫入的數據。非常方便。在PHP中有了共享內存的幫助,你可以實現不同進程在運行同一段PHP腳本時返回不同的結果。或實現對PHP同時運行數量的實時查詢等等。

            共享內存允許兩個或者多個進程共享一給定的存儲區。因為數據不需要在客戶機和服務器之間復制,所以這是最快的一種IPC。使用共享內存的唯一竅門是多個進程對一給定存儲區的同步存取。

            如何建立一個共享內存段呢?下面的代碼可以幫你建立共享內存。

          $shm_id = shmop_open($key, $mode, $perm, $size);

            注意,每個共享內存段都有一個唯一的ID, 在PHP中,shmop_open會把建立好的共享內存段的ID返回,這里我們用$shm_id記錄它。而$key是一個我們邏輯上表示共享內存段的 Key值。不同進程只要選擇同一個Key id就可以共享同一段存儲段。習慣上我們用一個串(類似文件名一樣的東西)的散列值作為key id. $mode指明了共享內存段的使用方式。這里由于是新建,因此值為’c’ –取create之意。如果你是訪問已經建立過的共享內存那么請用’a’,-- 取access之意。$perm參數定義了訪問的權限,8進制,關于權限定義請看UNIX文件系統幫助。$size定義了共享內存的大小。盡管有點象 fopen(文件處理)你可不要當它同文件處理一樣。后面的描述你將看到著一點。

            例如:

          $shm_id = shmop_open(0xff3, "c", 0644, 100);

            這里我們打開了一個共享內存段 鍵值0xff3 –rw-r—r—格式,大小為100字節。

            如果需要訪問已有的共享內存段,你必須在調用shmop_open中設第3、4個參數為0。

            IPC工作狀態的查詢

            在Unix下,你可以用一個命令行程序ipcs查詢系統所有的IPC資源狀態。不過有些系統要求需要超級用戶方能執行。下圖是一段ipcs的運行結果。

            上圖中系統顯示了4個共享內存段,注意其中第4個鍵值為0x00000ff3的就是我們剛剛運行過的PHP程序所創建的。關于ipcs的用法請參考UNIX用戶手冊。

            如何釋放共享內存呢

            釋放共享內存的辦法是調用PHP指令:shmop_delete($id)

          shmop_delete($id);

            $id 就是你調用shmop_open所存的shmop_op的返回值。還有一個辦法就是用UNIX的管理指令:

            ipcrm id, id就是你用ipcs看到的ID.和你程序中的$id不一樣。不過要小心,如果你用ipcrm直接刪除共享內存段那么有可能導致其他不知道這一情況的進程在引用這個已經不復存在的共享內存器時出現一些不可預測的錯誤(往往結果不妙)。

            如何使用(讀寫)共享內存呢

            使用如下所示函數向共享內存寫入數據

          int shmop_write (int shmid, string data, int offset)

            其中shmid是用shmop_open返回的句柄。$Data變量存放了要存放的數據。$offset描述了寫入從共享內存的開始第一個字節的位置(以0開始)。

            讀取操作是:

          string shmop_read (int shmid, int start, int count)

            同樣,指明$shmid,開始偏移量(以0開始)、總讀取數量。返回結果串。這樣,你就可以把共享內存段當作是一個字節數組。讀幾個再寫幾個,想干嘛就干嘛,十分方便。

            多進程問題的考慮

            現在,在單獨的一個PHP進程中讀寫、創建、刪除共享內存方面上你應該沒有問題了。但是,顯然實際運行中不可能只是一個PHP進程在運行中。如果在多個進程的情況下你還是沿用單個進程的處理方法,你一定會碰到問題 ---- 著名的并行和互斥問題。比如說有2個進程同時需要對同一段內存進行讀寫。當兩個進程同時執行寫入操作時,你將得到一個錯誤的數據,因為該段內存將之可能是最后執行的進程的內容,甚至是由2個進程寫入的數據輪流隨機出現的一段混合的四不象。這顯然是不能接受的。為了解決這個問題,我們必須引入互斥機制。互斥機制在很多操作系統的教材上都有專門講述,這里不多重復。實現互斥機制的最簡單辦法就是使用信號燈。信號量是另外一種進程間通訊(IPC)的方式,它同其他IPC機構(管道、FIFO、消息隊列)不同。它是一個記數器,用于控制多進程對共享數據的存儲。同樣的是你可以用ipcs和ipcrm實現對信號燈使用狀態的查詢和對其實現刪除操作。在PHP中你可以用下列函數創建一個新的信號量并返回操作該信號量的句柄。如果該key指向的信號量已經存在, sem_get直接返回操作該信號量的句柄。

          int sem_get (int key [, int max_acquire [, int perm]])

            $max_acquire 指明同時最多可以用幾個進程進入該信號而不必等待該信號被釋放(也就是最大同時處理某一資源的進程數目,一般該值均為一)。$perm指明了訪問權限。

            一旦你成功的擁有了一個信號量,你對它所能做的只有2種:請求、釋放。當你執行釋放操作時, 系統將把該信號值減一。如果小于0那就還設為0。而當你執行請求操作時,系統將把該信號值加一,如果該值大于設定的最大值那么系統將掛起你的處理進程直到其他進程釋放到小于最大值為止。一般情況下最大值設為1,這樣一來當一個進程獲得請求時其他后面的進程只能等待它退出互斥區后釋放信號量才能進入該互斥區并同時設為獨占方式。這樣的信號量常稱為雙態信號量。當然,如果初值是任意一個正數就表明有多少個共享資源單位可供共享應用。

            申請、釋放操作的PHP格式如下:

          int sem_acquire (int sem_identifier) 申請
          int sem_release (int sem_identifier) 釋放
          其中sem_identifier是調用sem_get的返回值(句柄)。 
          一個簡單的互斥協議例子
          下面是一段很簡單的互斥操作規程。
          $semid=sem_get(0xee3,1,0666);
          $shm_id = shmop_open(0xff3, "c", 0644, 100);
          sem_acquire($semid);      //申請
          /* 進入臨界區*/
            這里,對共享內存進行處理
          sem_release($semid);      //釋放

            正如你所看到的,互斥的實現很簡單:申請進入臨界區,對臨界區資源進行操作(比如修改共享內存)退出臨界區并釋放信號。這樣一來就可以保證在同一個時間片中不可能有同時2個進程對同一段共享內存進行操作。因為信號量機制保證一個時間片只能由一個進程進入,其他進程必須等待當前處理的進程完成后方能進入。

            臨界區一般是指那些不允許同時有多個進程并發處理的代碼段。

            要注意的是:在PHP中必須由同一個進程釋放它所占用的信號量。在一般系統中允許進程釋放別的進程占用的信號。在編寫臨界區代碼一定要小心設計資源的分配,避免A等B,B等A的死鎖情況發生。 

            運 用

            IPC的運用是十分廣泛的。比如,在不同進程間保存一個解釋過的復雜的配置文件、或具體設置的用戶等,以避免重復處理。我也曾經用共享內存的技術把一大批PHP腳本必須引用的一個很大的文件放入共享內存,并由此顯著提升了Web服務的速度、消除了部分瓶頸。關于它的使用還有聊天室,多路廣播等等。IPC的威力取決于你的想象力的大小。如果本文對你有一點點啟發,那我不勝榮幸。愿意很你討論這令人入迷的電腦技術。Email: qwyaxm@163.net

          posted @ 2009-07-10 11:50 小馬歌 閱讀(141) | 評論 (0)編輯 收藏
           
          from : http://hi.baidu.com/yancncen/blog/item/b6e0ad38031b06cbd4622547.html

          聯系作者,請加qq:1-1-3-8-5-7-1-5-4

          thrift里的c++ lib支持很多種協議,不過鑒于有些協議在別的語言的thrift lib并沒有得到支持,如php只支持binaryprotocol協議。所以,建議交互都走binaryprotocol協議,在此也只分析binaryprotocol的協議。

          廢話不說了,直入正題

          binaryprotocol協議分析:

          使用工具:
          strace、tcpdump、vi、thrift及其源碼

          (1)0-4個字節:
          協議版本|消息類型 (對于TBinaryProtocol.cpp而言協議版本為0x80010000和消息類型進行或運算)
          其中消息類型包括:call == 1, reply == 2, excetpion == 3

          (2)4-8字節:
          請求的函數名稱的長度,這里假設為functionNameLen


          (3)8-functionNameLen字節{functionNameLen為請求函數名的長度}:
          請求的函數名稱名稱

          (4)functionNameLen-functionNameLen+4個字節:(4個字節)
          請求的序列號
          (貌似生成的代碼里面,不管是哪個請求序列號都為0)


          如果function沒有參數:
          最后一個字節為0

          參數具有以下形式:{類型}{序號}{值}, 詳細請看下面的解釋

          如果function有參數:
          (5)functionNameLen+4-functionNameLen+5個字節:(1個字節)
          參數1的類型, 包括以下類型:

          參數類型表:
          T_STOP       = 0,
          T_VOID       = 1,
          T_BOOL       = 2,
          T_BYTE       = 3,
          T_I08        = 3,
          T_I16        = 6,
          T_I32        = 8,
          T_U64        = 9,
          T_I64        = 10,
          T_DOUBLE     = 4,
          T_STRING     = 11,
          T_UTF7       = 11,
          T_STRUCT     = 12,
          T_MAP        = 13,
          T_SET        = 14,
          T_LIST       = 15,
          T_UTF8       = 16,
          T_UTF16      = 17

          (6)functionNameLen+5-functionNameLen+7個字節:(2個字節)
          參數序號,取決于你定義的idl文件中參數所定義的序號


          (7)接下來的n個字節,取決于參數的類型:

          a)對于以下具有固定長度的簡單數據類型的參數:
          T_STOP       = 0, n==1
          T_VOID       = 1,   n==1
          T_BOOL       = 2, n==1
          T_BYTE       = 3, n==1
          T_I08        = 3, n==1
          T_I16        = 6, n==2
          T_I32        = 8, n==4
          T_U64        = 9, n==8 ? (雖然給出了定義,但是TBinaryProtocol.cpp并沒有實現,
               所以,如果要使用該數據類型的必須注意, 應該使用string類型來代替它
               unsigned long long 類型就需要特別注意了)
          T_I64        = 10, n==8
          T_DOUBLE     = 4, n==8   (double在目標機器上必須是8個字節的,符合IEC-559標準的浮點數,貌似對我們沒有影響)
          這n個字節就是參數的值。


          以下的數據類型被我歸為復合數據類型:

          b)對于String,這n個字節包含以下內容:
          前面4個字節:字符串的長度stringLen
          接下來的stringLen個字節:字符串的內容

          c)對于struct,這n個字節包含以下內容:
             假設這個結構體包含m個字段:(為了便于說明問題,下面所說的字節偏移是相對于struct內部結構而言的)
             0-1字節:字段的數據類型
             1-3字節:字段序號,取決于你定義的idl文件中參數所定義的序號

             接下來的k個字節:goto (7)
             以此類推,直至m個字段
             其實,struct的字段和函數參數具有一樣的編碼方式

          d)對于set,這n個字節包含以下內容:(為了便于說明問題,下面所說的字節偏移是相對于set內部結構而言的)
             0-1字節:set里面的元素的數據類型
             1-5字節:元素個數
             假設元素的數據類型的長度為k個字節,那么接下來每k個字節作為一個元素值,至于元素值的分析,請goto(7)
             注意,這里和函數參數/struct的區別在于,這里不存在元素的序號值

          e)對于list,這n個字節包含以下內容:
          和set類似,這里就不重復累贅了。
          值得注意的一點是,thrift白皮書提到了“list<type> An ordered list of elements.”,實際上,list在映射到stl的list時并不是經過排序的list。

          f)對于map,這n個字節包含以下內容:(為了便于說明問題,下面所說的字節偏移是相對于map內部結構而言的)
          0-1字節:key的數據類型。注意,可能是復合數據類型
          1-2字節:value的數據類型。
          假設key的數據類型的長度為k個字節,value的數據類型的長度為v個字節
          那么接下來每k+v個字節作為一個key-value值,
          至于key的值的分析和value的值的分析,請goto(7)

          總結:
          (1)關于定義idl的一些總結,盡量避免定義過于復雜的數據結構。

          從上面的協議分析來看,復合數據類型的存在著一個遞歸包含的關系。
          不過thrift在生成封/解包的代碼里,并沒有出現遞歸調用來封/解包,而是采用了循環嵌套循環的方式來生成代碼,
          這種做法避免了頻繁遞歸調用封/解包函數,可提高封/解包的效率。同時帶來的問題就是生成的代碼量的急劇膨脹。

          雖然沒有遞歸調用來封/解包, 如果定義太過于復雜的數據結構也會隨之產生多重循環,看下面的例子
          假設定義以下一個數據結構:
          map< string, list< set<string> > >,thrift將會產生類似于以下的循環來進行封/解包:
          foreach (key in map)
          {
          foreach ( set in map[key] )
          {
              foreach (string in set )
                encode()/decode();  
          }
          }

          假設map,list,set的元素各有100個,這將是一個嚴重影響性能的地方,應該避免。

          (2)建議使用了unsigned long long的字段使用string類型,而不是u64類型,因為目前的thrift不支持。

          (3)在網絡IO層一個潛在的瓶頸
          由于thrift的binaryprotocol協議的包頭沒有任何的字節描述了整個網絡包的長度的信息。
          所以thrift的binaryprotocol協議在解包的時候是每次都只能采用從socket讀取一個變量的類型接著讀取變量的值出來這樣的解釋方式。
          這種解包的方式可能引起的潛在問題:
          當請求的client數量非常多,交互的數據量也非常多(這里可能是交互了很多字段,或者使用了太多復合數據類型)時,tcp/ip協議棧的緩沖區可能會被塞滿了
          還沒有被處理的數據,就會嚴重影響服務質量。

          至于為何不提供某些字節來標識整個數據包的長度,是因為thrift的binaryprotocol協議需要支持復雜數據類型,像set,list,map,而這些復合數據類型的大小是難以確定的。
          為了支持標識整個數據包長度,封包前需要知道set,list,map的總體大小,那么就需要遍歷set,list,map的大小,這是相當不劃算,會增加運算邏輯,而且還會導致協議變得很復雜。


          (4)如何做到兼容舊接口
          當我們的server更新接口的同時,還需要保證舊client能夠和新server交互,那么在定義IDL時就需要特別注意。
          假設,我們定義以下一個這個一個結構體來交互用戶信息。
          struct user
          {
          1:username string,
          2:password string,
          3:sex i16,
          }

          當我們需求變更時,假設以下兩種情況:
          a)需要新增字段, age來表示年齡
          struct user
          {
          1:username string,
          2:password string,
          3:sex i16,
          4:age i32,
          }

          注意,原來字段的序號標識一定不能被改變,1:username string, 不能改成 5:username string。
          此時,如果server是新的,client是舊的,并不影響client的工作,client從server那邊收到的包里包含了age的信息,只是沒有decode出來而已。

          b)刪除字段sex,新增字段age
          struct user
          {
          1:username string,
          2:password string,
          //3:sex i16,
          4:age i32, (注意,為了保證a)所定義的client能夠和b)的server交互,這里的字段序號必須定義為4)
          }

          此時,如果server是新的,client是a)所生成的也并不影響和b)的server交互,因為client從server那邊收到的包雖然沒有包含sex的信息,但是client并不會崩潰,只是缺少了sex的信息。
          因此,我們需求變更時,盡量保存舊的字段不要刪除,做到只增不減的方式來兼容舊接口。

          這里字段序號是唯一標識字段的關鍵。

          posted @ 2009-07-10 11:48 小馬歌 閱讀(8974) | 評論 (0)編輯 收藏
           

          find / -amin -10 # 查找在系統中最后10分鐘訪問的文件
          find / -atime -2 # 查找在系統中最后48小時訪問的文件
          find / -empty # 查找在系統中為空的文件或者文件夾
          find / -group cat # 查找在系統中屬于 groupcat的文件
          find / -mmin -5 # 查找在系統中最后5分鐘里修改過的文件
          find / -mtime -1 #查找在系統中最后24小時里修改過的文件
          find / -nouser #查找在系統中屬于作廢用戶的文件
          find / -user fred #查找在系統中屬于FRED這個用戶的文件
          find / -mtime +2 兩天之前
          find / -mtime -2 兩天以內

          /sbin/iptables -A INPUT-i lo -j ACCEPT
          # Accept EstablishedConnections
          /sbin/iptables -A INPUT-m state --state ESTABLISHED,RELATED -j ACCEPT

          # ICMP Control
          /sbin/iptables -A INPUT-p icmp -m limit --limit 1/s --limit-burst 10 -j ACCEPT

          watch -n 1 "ifconfig eth0|grep bytes" 查看網卡速率
          rpm -i --test *.rpm 查詢 rpm 包是否可以被安裝
          tar 小結
          1.#查看tar包中的內容
          tar -tf XXX.tar來查看tar包中的內容
          2.#刪除tar包中的目錄
          tar --delete (tar包中目錄) -vf XXX.tar
          3.#打包時排除個別目錄
          tar -zcvf XXX.tar.gz --exclude=test/XXX1 --exclude=test/XXX2 test
          要注意的有3點
          1. "-f"參數后要緊跟文件名
          2."tar.gz" 包不能用tar --delete刪除其中目錄(先用gzip -d解開.gz)
          3.配合是用file命令查看文件類型,到底是tar包,還是tar.gz

          1.如果主機的 tar 是 GNU 的版本,exclude 參數就要放在前面了:
          2.注意--exclude后面的排除目錄后不能帶/ ,否則不起作用。

          # export PATH=$PATH:/usr/local/mysql/bin
          檢查下 PATH 中是否寫入了 /usr/local/mysql/bin 路徑:
          # echo $PATH
          /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/mysql/bin

          小注意點:在進行./configure安裝配置軟件的時候,此時會用/tmp目錄,如果此時/tmp被掛載別的設備,此時./configure就無法進行,會出錯.我發生過/tmp掛載光盤, 在./configure安裝別的軟件是發生錯誤.[root@localhost ~]# ifconfig eth0 |awk '/HWaddr/{print $5}'
          00:0C:29:0F:C7:D8

          [root@localhost ~]# ifconfig eth0 |awk '/inet addr/{print $2}'|awk -F: '{print $2}'
          192.168.187.129
          查看是否中了arp欺騙方法:發現網關的mac在變化
          arping -I eth0 網關地址
          如sh# arping 192.168.0.125
          ARPING 192.168.0.125 from 192.168.0.1 eth0
          Unicast reply from 192.168.0.125 [00:E0:4D:06:5C:C4] 0.700ms
          Unicast reply from 192.168.0.125 [00:E0:4D:06:5C:C4] 0.677ms
          Unicast reply from 192.168.0.125 [00:E0:4C:00:32:F9] 837.700ms

          查看是否中的洪水syn flood:查看是否有大量請求來自同一個主機
          netstat -ant | wc -l
          netstat -ant | grep -c SYN_RECV

          查看節點號inode
          stat filename
          ls -i filename
          df -i

          給CentOS YUM加速
          CentOS 5.x下 安裝 yum-fastestmirror (yum install yum-fastestmirror)
          CentOS 4.x下 安裝 yum-plugin-fastestmirror (yum install yum-plugin-fastestmirror)
          確保/etc/yum.conf里有 plugins=1 一行

          curl -I www.badiu.com
          curl --head www.baidu.com
          host/nslookup/dig
          www.baidu.com
          netstat -an |awk '/^tcp/{++a[$NF]}END{for(i in a)print i, a[i]}'

          # netstat -lntp # 查看所有監聽端口
          # netstat -antp # 查看所有已經建立的連接
          # netstat -s # 查看網絡統計信息

          rpm -qpl 包名,查看包中內容

          rpm -qf /bin/ping 可以查看命令屬于那個包
          redhat/solaris下允許root通過telnet登錄
          在redhat中對于遠程login的限制,體現在/etc/pam.d/login文件中,缺省有一行:
           auth required /lib/security/pam_security.so注釋該行,任何限制都沒有,root當然可以直接telnet登陸echo 1 > /proc/sys/net/ipv4/ip_forward
          echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
          vi /etc/sysctl.conf

          file /sbin/init   或 file /bin/ls查看系統是32位還是64位的(os) ,i386,i686都是32位的, x86_64 x86_64 x86_64 是64位的
          dd if=/etc/passwd of=/tmp/passwd.bak    備份
          gcc -v    查看GCC版本
          chattr +i filename 禁止刪除   chattr -i filename 取消禁止
          lsattr    顯示隱藏檔屬性
          ifdown eth0 關閉網卡
          ifup eth0    開啟網卡
          clear    清屏
          history    歷史記錄       !55 執行第55個指令
          stty   設置終端    stty -a
          fdisk /mbr   刪除GRUB
          at     僅進行一次的工作排程
          jobs    觀看后臺暫停的程序   jobs -l
          kill    結束進程 kill -9 PID [9]強制結束,[15]正常結束,[l]列出可用的kill信號
          top     查看后臺程序   top -d 2    每兩秒更新一次        top -d 2 -p10604   觀看某個PID
                   top -b -n 2 > /tmp/top.txt ----->將 top 的資訊進行 2 次,然後將結果輸出到 /tmp/top.txt   
          pstree   以樹狀圖顯示程序    [A]以 ASCII 來連接, [u]列出PID, [p]列出帳號
          killall   要刪除某個服務    killall -9 httpd
          free      顯示內存狀態     free -m -------->以M為單位顯示
          uptime    顯示目前系統開機時間
          netstat   顯示網絡狀態    netstat -tulnp------>找出目前系統上已在監聽的網路連線及其 PID
          nice      設置優先權      nice -n -5 vi & ----->用 root 給一個 nice 植為 -5 ,用於執行 vi
          runlevel 顯示目前的runlevel
          depmod    分析可載入模塊的相依性
          lsmod     顯示已載入系統的模塊
          modinfo   顯示kernel模塊的信息
          insmod    載入模塊
          modprobe   自動處理可載入模塊 modprobe -l
          rmmod     刪除模塊
          chkconfig   檢查,設置系統的各種服務     chkconfig --list ----->列出各項服務狀態
          ntsysv     設置系統的各種服務
          cpio      備份文件
          vi一般用法
          一般模式              編輯模式                  指令模式
          h 左               a,i,r,o,A,I,R,O             :w 保存
          j 下                進入編輯模式                :w! 強制保存
          k 上                dd 刪除光標當前行           :q! 不保存離開
          l 右                ndd 刪除n行                 :wq! 保存后離開
          0 移動到行首        yy 復制當前行                :e! 還原原始檔
          $ 移動到行尾        nyy 復制n行                  :w filename 另存為
          H 屏幕最上          p,P 粘貼                     :set nu 設置行號
          M 屏幕中央          u 撤消                      :set nonu 取消行號
          L 屏幕最下          [Ctrl]+r 重做上一個動作       ZZ 保存離開
          G 檔案最后一行      [ctrl]+z 暫停退出            :set nohlsearch   永久地關閉高亮顯示
          /work 向下搜索                                   :sp 同時打開兩個文檔
          ?work 向上搜索                                   [Ctrl]+w 兩個文檔設換
          gg 移動到檔案第一行                              :nohlsearch    暫時關閉高亮顯示
          有用:
          G 檔案最后一行
          gg 移動到檔案第一行
          H 屏幕最上
          M 屏幕中央
          L 屏幕最下

          4yl是向后復制4個字符,l是用來指明方向的吧? 4yh用向前復制四個字符。

          通過vim 編輯文件,用V   進行塊選

          alias 顯示當前所有的命令別名  
          alias lm="ls -al"   命令別名 unalias lm 取消命令別
          type      類似which
          exprot    設置或顯示環境變量
          exprot PATH="$PATH":/sbin 添加/sbin入PATH路徑
          echo $PATH    顯示PATH路徑
          bash      進入子程序
          name=yang     設定變量
          unset name    取消變量
          echo $name    顯示變量的內容
          myname="$name its me"   &   myname='$name its me'     單引號時$name失去變量內容
          ciw=/etc/sysconfig/network-scripts/     設置路徑
          env      列出所有環境變量
          echo $RANDOM    顯示隨意產生的數
          set      設置SHELL
          PS1='[\u@\h \w \A #\#]\$ '     提示字元的設定
          [root@linux ~]# read [-pt] variable     -----------讀取鍵盤輸入的變量
             參數:
              -p :後面可以接提示字元!
              -t :後面可以接等待的『秒數!』
          declare    聲明 shell 變量
          ulimit -a   顯示所有限制資料
          ls /tmp/yang && echo "exist" || echo "not exist"
          意思是說,當 ls /tmp/yang 執行後,若正確,就執行echo "exist" ,若有問題,就執行echo "not exist"
          echo $PATH | cut -d ':' -f 5       以:為分隔符,讀取第5段內容
          export | cut -c 10-20      讀取第10到20個字節的內容
          last | grep 'root'    搜索有root的一行,加[-v]反向搜索
          cat /etc/passwd | sort    排序顯示
          cat /etc/passwd | wc      顯示『行、字數、字節數』
          正規表示法
          [root@test root]# grep [-acinv] '搜尋字串' filename
              參數說明:
                  -a :將 binary 檔案以 text 檔案的方式搜尋資料
                  -c :計算找到 '搜尋字串' 的次數
                  -i :忽略大小寫的不同,所以大小寫視為相同
                  -n :順便輸出行號
                  -v :反向選擇,亦即顯示出沒有 '搜尋字串' 內容的那一行!
          grep -n 'the' 123.txt     搜索the字符 -----------搜尋特定字串      
          grep -n 't[ea]st' 123.txt    搜索test或taste兩個字符---------利用 [] 來搜尋集合字元
          grep -n '[^g]oo' 123.txt     搜索前面不為g的oo-----------向選擇 [^]
          grep -n '[0-9]' 123.txt 搜索有0-9的數字
          grep -n '^the' 123.txt 搜索以the為行首-----------行首搜索^
          grep -n '^[^a-zA-Z]' 123.txt 搜索不以英文字母開頭
          grep -n '[a-z]$' 123.txt    搜索以a-z結尾的行---------- 行尾搜索$
          grep -n 'g..d' 123.txt     搜索開頭g結尾d字符----------任意一個字元 .
          grep -n 'ooo*' 123.txt     搜索至少有兩個oo的字符---------重複字元 *
          sed    文本流編輯器    利用腳本命令來處理文本文件
          awk    模式掃描和處理語言
          nl 123.txt | sed '2,5d'   刪除第二到第五行的內容
          nl 123.txt | sed -n '2,5p'顯示2-5行內容
          diff     比較文件的差異
          cmp      比較兩個文件是否有差異
          patch    修補文件
          pr       要打印的文件格式化
          sudo       以其他身份來執行指令
          visudo     編輯/etc/sudoers      加入一行『 test ALL=(ALL) ALL 』
                      %wheel ALL = (ALL) ALL               系統里所有wheel群組的用戶都可用sudo
                      %wheel ALL = (ALL) NOPASSWD: ALL     wheel群組所有用戶都不用密碼NOPASSWD
                  User_Alias ADMPW = vbird, dmtsai, vbird1, vbird3         加入ADMPW組
                  ADMPW ALL = NOPASSWD: !/usr/bin/passwd, /usr/bin/passwd [A-Za-z]*, \
                  !/usr/bin/passwd root      可以更改使用者密碼,但不能更改root密碼 (在指令前面加入 ! 代表不可)
          PAM (Pluggable Authentication Modules, 嵌入式模組)
          who & w     看誰在線                    
          last        最近登陸主機的信息
          lastlog     最近登入的時間    讀取 /var/log/lastlog    這點重要
          talk        與其他用戶交談
          write       發送信息    write test   [ctrl]+d 發送
          mesg        設置終端機的寫入權限    mesg n 禁止接收     mesg y
          wall        向所有用戶發送信息    wall this is q test
          mail        寫mail  
          /etc/default/useradd    家目錄默認設置
          quota      顯示磁盤已使用的空間與限制     quota -guvs ----->秀出目前 root 自己的 quota 限制值
                      quota -vu   查詢
          quotacheck   檢查磁盤的使用空間與限制     quotacheck -avug ----->將所有的在 /etc/mtab 內,含有 quota

          支援的 partition 進行掃瞄
                        [-m] 強制掃描
                quota一定要是獨立的分區,要有quota.user和quota.group兩件文件,在/etc/fstab添加一句:
                /dev/hda3 /home ext3 defaults,usrquota,grpquota 1 2
                chmod 600 quota*         設置完成,重啟生效
          edquota    編輯用戶或群組的quota [u]用戶,[g]群組,[p]復制,[t]設置寬限期限
                      edquota -a yang       edquota -p yang -u young ----->復制   
          quotaon    開啟磁盤空間限制     quotaon -auvg -------->啟動所有的具有 quota 的 filesystem
          quotaoff   關閉磁盤空間限制     quotaoff -a -------->關閉了 quota 的限制
          repquota -av     查閱系統內所有的具有 quota 的 filesystem 的限值狀態
          Quota 從開始準備 filesystem 的支援到整個設定結束的主要的步驟大概是:
          1、設定 partition 的 filesystem 支援 quota 參數:
          由於 quota 必須要讓 partition 上面的 filesystem 支援才行,一般來說, 支援度最好的是 ext2/ext3 ,
          其他的 filesystem 類型鳥哥我是沒有試過啦! 啟動 filesystem 支援 quota 最簡單就是編輯 /etc/fstab ,
          使得準備要開放的 quota 磁碟可以支援 quota 囉;
          2、建立 quota 記錄檔:
          剛剛前面講過,整個 quota 進行磁碟限制值記錄的檔案是 aquota.user/aquota.group,
          要建立這兩個檔案就必須要先利用 quotacheck 掃瞄才行喔!
          3、編輯 quota 限制值資料:
          再來就是使用 edquota 來編輯每個使用者或群組的可使用空間囉;
          4、重新掃瞄與啟動 quota :
          設定好 quota 之後,建議可以再進行一次 quotacheck ,然後再以 quotaon 來啟動吧!

          開機流程簡介
          1、載入 BIOS 的硬體資訊,並取得第一個開機裝置的代號;
          2、讀取第一個開機裝置的 MBR 的 boot Loader (亦即是 lilo, grub, spfdisk 等等) 的開機資訊;
          3、載入 Kernel 作業系統核心資訊, Kernel 開始解壓縮,並且嘗試驅動所有硬體裝置;
          4、Kernel 執行 init 程式並取得 run-level 資訊;
          5、init 執行 /etc/rc.d/rc.sysinit 檔案;
          6、啟動核心的外掛模組 (/etc/modprobe.conf);
          7、init 執行 run-level 的各個批次檔( Scripts );
          8、init 執行 /etc/rc.d/rc.local 檔案;
          9、執行 /bin/login 程式,並等待使用者登入;
          10、登入之後開始以 Shell 控管主機。
          在/etc/rc.d/rc3.d內,以S開頭的為開機啟動,以K開頭的為關閉,接著的數字代表執行順序
          GRUB vga設定
          彩度\解析度 640x480 800x600 1024x768 1280x1024   bit
               256        769      771      773       775      8 bit
              32768       784      787      790       793     15 bit
              65536       785      788      791       794     16 bit
              16.8M       786      789      792       795     32 bit

          ./configure    檢查系統信息       ./configure --help | more 幫助信息
          make clean     清除之前留下的文件
          make           編譯
          make install   安裝
          rpm -q ----->查詢是否安裝             rpm -ql ------>查詢該套件所有的目錄
          rpm -qi ----->查詢套件的說明資料       rpm -qc[d] ----->設定檔與說明檔
          rpm -ivh ---->安裝                    rpm -V -------->查看套件有否更動過
          rpm -e ------>刪除                    rpm -Uvh ------->升級安裝
          --nodeps ----->強行安裝                --test ----->測試安裝
          -pql   查看包中內容    -qf    command 查命令屬于那個包

          posted @ 2009-07-10 11:47 小馬歌 閱讀(364) | 評論 (0)編輯 收藏
           
          修改注冊表鍵值:

          [HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main]

          RunOnceComplete=dword:00000001

          RunOnceHasShown=dword:00000001
          以上查找沒有這個注冊表信息,你新建就可以了,添加上面這兩個就可以修復了
          posted @ 2009-07-07 12:13 小馬歌 閱讀(3320) | 評論 (3)編輯 收藏
           

          需求:
          一個千萬級數據量的服務,不停的插入和刪除記錄,每條記錄需要知道自己的排名,比如SNS中的搶車位,如何讓每個uid能夠知道自己在所有人中的車總價排名?

          致命傷(cache無用論)
          有1000萬個用戶,試想排名第500萬的用戶突然發飆了,把他的車全賣了,那么他之后的500萬個用戶的排名都提高了,也就是cache全部瞬間失效了。。。pity,此時加再多的cache只能是浮云

          解決方法:
          1,劃分子空間,比如k心網,不提供全部用戶的排名,只提供用戶在其好友中的車總價的排名(其實這樣更有意義,不過這是產品層面),這樣即時一個用戶車價變化,影響的也只是其好友的cache,別人不做影響
          2,犧牲實時性,算不過來就離線算唄,這個太容易想到了,比如k心網車總價的排名是每12個小時更新一次的

          BT的需求:
          假如,只是假如,我們就需要uid在所有用戶中的實時準確排名怎么辦??(產品不想犧牲實時性的UE),這時解決問題只能靠更好的算法模型

          擴展的紅黑樹:
          這個結構在一般數據結構書不提,在CLRS是以擴展話題為討論的,在TAOCP中是以課后題出現,但在CLRS的視頻中可是重點介紹,講了一節課呢,所以推薦看這個視頻11.Dynamic.Statistics。拷貝書上的介紹nonsense,所以只是簡單的介紹一下:擴展紅黑樹ERBT中,每個節點不僅有color,link,key信息,還包括了一個很重要的信息=>該節點所有子節點的數目(包括其自身在內),這樣每個節點的排名可以在找到它的那一霎那得到,因為(初始rank(root)=0):
          rank(lnode)=rank(pnode)
          rank(rnode)=children_count(lnode)+1
          而作為補償,同樣需要在更改操作時,維護子節點的數目
          查找和維護的時間復雜度都是log(n)

          解決方案:
          還是車總價的排名顯示問題,我們在內存中維護這樣一顆ERBT,key就是車的總價位,當有用戶的車總價發生變化時,我們就刪除這個節點并插入一個新節點。當需要顯示用戶的車總價排名時,先從uid得到車總價的數值(比如從mysql中),然后拿這個數值到ERBT中做查找,當找到這個值的時候,排名自然得到。

          對于千萬級數據,log(n)基本在20-30,而使mc的話,每秒請求可以到2萬這個級別,我們假設hash的拉鏈平均長度為3,也就是使用ERBT的速度理論上是直接hash的1/10,也就是能夠支撐2000r/s的請求,這樣的能力對于一般的SNS應用也是夠了。當然如果要求更高性能還需要做更多的優化。

          故障恢復:
          首先這個服務就支持分布式,因為每臺機器可以獨立的跑ERBT,另外即時down機了,恢復也很容易,只要從mysql中導入數據一遍則自動生成,我們也可以把ERBT定時按照hash的形式dump出一份,以備意外時訪問

          posted @ 2009-07-03 22:23 小馬歌 閱讀(201) | 評論 (0)編輯 收藏
          僅列出標題
          共95頁: First 上一頁 65 66 67 68 69 70 71 72 73 下一頁 Last 
           
          主站蜘蛛池模板: 堆龙德庆县| 西华县| 肃南| 临海市| 潍坊市| 罗山县| 富蕴县| 金阳县| 伊春市| 诸城市| 德江县| 浏阳市| 连平县| 咸宁市| 蒙阴县| 五指山市| 米泉市| 岑巩县| 内黄县| 旺苍县| 即墨市| 三都| 甘孜县| 高淳县| 苗栗市| 紫金县| 黑山县| 前郭尔| 泗洪县| 喀喇| 土默特右旗| 昌乐县| 崇左市| 漾濞| 冀州市| 南宫市| 长葛市| 济阳县| 安仁县| 江陵县| 全椒县|