so true

          心懷未來,開創(chuàng)未來!
          隨筆 - 160, 文章 - 0, 評(píng)論 - 40, 引用 - 0
          數(shù)據(jù)加載中……

          Linux學(xué)習(xí)菁華

          @import url(http://www.aygfsteel.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); gdb中顯示長(zhǎng)字符串:

          1.       Gdb中可以調(diào)用printf做格式化打印:

          printf "%.2000s",s

          x /3uc 0x2341234 #打印地址0x2341234開始的3個(gè)單元,每個(gè)單元1個(gè)byte長(zhǎng),以u(píng)nsigned int類型顯示出來
          p /t 23423 #以二進(jìn)制形式打印23423
          2000表示最多打印2000個(gè)字符。如果需要打印更長(zhǎng)的字符,可以增大該數(shù)據(jù)。

          break write if $rdi == 2 #如果stderr上有輸出的話,就會(huì)break, 引自:https://blogs.oracle.com/ksplice/entry/8_gdb_tricks_you_should

           

          2.       Gdb可以將交互輸出到文件。需要調(diào)用如下兩個(gè)命令:

          set logging on

          set logging file xxx.txt

          以上兩個(gè)命令配合可以起到將長(zhǎng)字符串打印到文件的作用。

          但是如果字符串中有若干不可見字符,就不能使用這種方法了。這時(shí)候我們需要把數(shù)據(jù) dump到文件中。命令如下:

          dump binary memory s.txt s s+1000

           s是一個(gè)字符串指針,表示dump的起始位置,s+1000表示dump的末尾。S.txt表示結(jié)果
          dump的文件名具體的參數(shù)意義可以看gdbmannual


          3.打印東西的長(zhǎng)度設(shè)置項(xiàng)為

          (gdb) set print elements

          (gdb) set print elements 0

          為全部打出。
          3.1 所有打印的控制都是通過set print來進(jìn)行的,例如set print pretty on,如果打開printf pretty這個(gè)選項(xiàng),那么當(dāng)GDB顯示結(jié)構(gòu)體時(shí)會(huì)比較漂亮。

          4. 對(duì)于內(nèi)存版本的字符串,比如char buffer[1000],可以p buffer@300表示從300后開始打印

          gdb能調(diào)試,pstack能打印堆棧信息,core dump文件里有堆棧信息,以及運(yùn)行時(shí)變量的值信息,這些都?xì)w功于symbol table,symbole不光是指變量,也包括函數(shù)以及文件名等等,沒有symbol table上述的一切都不可能。gdb里可以通過symbole-file命令來加載一個(gè)symbol文件,它可以是可執(zhí)行的程序,也可以是僅僅含有symbol的文件,舉個(gè)例子來說:你把strip test -o test.stripped之后的test.stripped文件給別人去用,一旦core掉了,那個(gè)人把core文件給你,你可以用gdb test.stripped core來調(diào)試,并通過symbol-file test這個(gè)命令來加載symbol table,這樣依然可以正常debug。 當(dāng)然你也可以只保留test里面的symbol table,通過strip --only-keep-debug test -o test.dbg來生成這個(gè)文件,然后gdb test.stripped core,通過symbol-file test.dbg就可以了。
          在這里也提一下生成core文件,調(diào)用exit(1)是退出,調(diào)用abort()是會(huì)產(chǎn)生core文件的(當(dāng)然要ulimit -c unlimited)。

           

          pbt () {
              yes | gdb -p $1 --eval-command='thread apply all bt full' --eval-command='q'
          }

          bt #查看堆棧信息
          bt full #查看堆棧信息,并同時(shí)打印local變量
          f 2 #切換到當(dāng)前堆棧的第2層
          info locals #查看當(dāng)前的臨時(shí)變量
          info thread #查看目前所有的線程
          thread 2 #切換到2號(hào)線程
          break file.c:100 thread 3 #只在3號(hào)線程設(shè)置斷點(diǎn)
          set scheduler-locking on #只調(diào)試當(dāng)前線程,即不會(huì)在調(diào)試過程中被其他線程切進(jìn)來
          info macro DEBUG 你可以查看DEBUG這個(gè)宏在哪些文件里被引用了,以及宏定義是什么樣的。 macro DEBUG 你可以查看DEBUG宏展開的樣子;但需要在GCC編譯程序的時(shí)候,加上-ggdb3參數(shù),這樣,你就可以調(diào)試宏了。
           
          info source可以看到當(dāng)前運(yùn)行位置對(duì)應(yīng)的源文件信息;
          info sources可以看到當(dāng)前運(yùn)行程序所有的源文件列表;
          info frame可以看到當(dāng)前運(yùn)行位置的rip,args位置,棧(存放臨時(shí)變量)開始位置

          (gdb) set $idx = 0
          (gdb) p a[$idx++]  #然后就可以一路回車下去了,哈哈
          有時(shí)候需要打印一個(gè)范圍內(nèi)的變量值,可以這樣搞:
          while $idx < upper_limit
          p a[$idx++]
          end
          設(shè)置條件斷點(diǎn):b 234 if page == 48
          修改變量的值,用set var a=3,也可以用p a=3

          x/x 以十六進(jìn)制輸出 x/d 以十進(jìn)制輸出 x/c 以單字符輸出 x/i  反匯編 – 通常,我們會(huì)使用 x/10i $ip-20 來查看當(dāng)前的匯編($ip是指令寄存器)x/s 以字符串輸出 bt #查看堆棧信息
          bt full #查看堆棧信息,并同時(shí)打印local變量
          f 2 #切換到當(dāng)前堆棧的第2層
          info locals #查看當(dāng)前的臨時(shí)變量
          info thread #查看目前所有的線程
          thread 2 #切換到2號(hào)線程
          break file.c:100 thread 3 #只在3號(hào)線程設(shè)置斷點(diǎn)
          set scheduler-locking on #只調(diào)試當(dāng)前線程,即不會(huì)在調(diào)試過程中被其他線程切進(jìn)來
          info macro DEBUG 你可以查看DEBUG這個(gè)宏在哪些文件里被引用了,以及宏定義是什么樣的。 macro DEBUG 你可以查看DEBUG宏展開的樣子;但需要在GCC編譯程序的時(shí)候,加上-ggdb3參數(shù),這樣,你就可以調(diào)試宏了。
             
          (gdb) set $idx = 0
          (gdb) p a[$idx++]  #然后就可以一路回車下去了,哈哈

          gdb -c core.2234 //可以從打印到屏幕上的信息的最后部分看到產(chǎn)生這個(gè)core文件的命令包括參數(shù)
          gdb a.out core.2234 //可以查看bt信息,也可以看到產(chǎn)生core文件的命令和參數(shù),然后運(yùn)行set args XXXX就可以設(shè)定參數(shù)了,然后run就可以重新跑起來,可以在core之前設(shè)定breakpoints,當(dāng)運(yùn)行到要產(chǎn)生core的那一行(例如是38行),可以用jump 39來跳過該行的執(zhí)行,這么調(diào)試的好處在于可以隨時(shí)print 一個(gè)函數(shù)的運(yùn)行結(jié)果,例如print obj.do(),而程序沒有正在運(yùn)行時(shí),是無法print一個(gè)函數(shù)的執(zhí)行結(jié)果的.

          gdb里查看源代碼需要增加額外路徑:
          (gdb) show directories 
          Source directories searched: $cdir:$cwd
          (gdb) directory //這個(gè)命令會(huì)清空所有路徑,最好別這么干
          (gdb) directory XXX/XXX //這個(gè)命令會(huì)增加一個(gè)搜索的路徑
          gdb查看指針類型時(shí),如果是基類指針,希望看到到底是哪個(gè)子類時(shí),使用:
          (gdb) set print object //這個(gè)命令可以讓print一個(gè)基類指針時(shí),可以看到其到底是哪個(gè)子類指針
          gdb查看一個(gè)變量的類型,簡(jiǎn)單點(diǎn)可以用whatis,如果要查看其完整的聲明,用ptype,如果只想看里面的成員變量,用p *XXX;
          gdb里調(diào)用函數(shù),需要程序當(dāng)前在run才行,例如p str.length();對(duì)于std::string類型,調(diào)試core文件時(shí)用下面命令查看里面的內(nèi)容:
          printf "String \t\t\t= \"%s\"\n", $arg0._M_dataplus._M_p
          printf "String size/length \t= %u\n", (((std::string::_Rep*) ($arg0._M_dataplus._M_p))[-1])._M_length
          printf "String capacity \t= %u\n", (((std::string::_Rep*) ($arg0._M_dataplus._M_p))[-1])._M_capacity
          printf "String ref-count \t= %d\n", (((std::string::_Rep*) ($arg0._M_dataplus._M_p))[-1])._M_refcount
          完整的.gdbinit文件請(qǐng)參見另外一篇帖子http://www.aygfsteel.com/bacoo/archive/2012/11/07/390979.html

          x/x 以十六進(jìn)制輸出 x/d 以十進(jìn)制輸出 x/c 以單字符輸出 x/i  反匯編 – 通常,我們會(huì)使用 x/10i $ip-20 來查看當(dāng)前的匯編($ip是指令寄存器)x/s 以字符串輸出

          如果需要調(diào)試stl里面的東西,即可以step into libstdc++中,在ubuntu下的方法如下:
          1。安裝libgcc1-dbg和libstdc++6-4.4-dbg;安裝完之后會(huì)發(fā)現(xiàn)在/usr/lib/debug/下多了些東西:lib  libstdc++.a  libstdc++.so  libstdc++.so.6  libstdc++.so.6.0.13
          2。$ gdb --quiet test
          (gdb) start
          Temporary breakpoint 1 at 0x8048977: file t5.cpp, line 14.
          Starting program: /home/bacoo/test
          [Thread debugging using libthread_db enabled]

          Temporary breakpoint 1, main (argc=1, argv=0xbfffed64) at t5.cpp:14
          14          size_t pos, begin_pos = 0;
          (gdb) info sharedlibrary
          From        To          Syms Read   Shared Object Library
          0x00110830  0x001277af  Yes (*)     /lib/ld-linux.so.2
          0x00133610  0x0013fad8  Yes (*)     /lib/libpthread.so.0
          0x0018d2e0  0x001fecd8  Yes (*)     /usr/lib/libstdc++.so.6
          0x002374b0  0x002517f8  Yes (*)     /lib/libm.so.6
          0x0025bf50  0x00272438  Yes         /lib/libgcc_s.so.1
          0x0028cac0  0x00396a74  Yes (*)     /lib/libc.so.6
          (*): Shared library is missing debugging information.
          (gdb) show debug-file-directory
          The directory where separate debug symbols are searched for is "/usr/lib/debug".
          (gdb)
          注意,上面的libgcc_s.so.1和libstdc++.so.6兩個(gè)lib,其中l(wèi)ibgcc已經(jīng)有symbol了,而libstdc++還沒有symbol(這個(gè)是根據(jù)Yes之后是否有(*)看出來的),
          如果是這種情況的話,那退出gdb,然后執(zhí)行:
          $ LD_LIBRARY_PATH=/usr/lib/debug gdb --quiet test
          (gdb) start
          Temporary breakpoint 1 at 0x8048977: file t5.cpp, line 14.
          Starting program: /home/bacoo/test
          [Thread debugging using libthread_db enabled]

          Temporary breakpoint 1, main (argc=1, argv=0xbfffed44) at t5.cpp:14
          14          size_t pos, begin_pos = 0;
          (gdb) info sharedlibrary
          From        To          Syms Read   Shared Object Library
          0x00110830  0x001277af  Yes (*)     /lib/ld-linux.so.2
          0x00133610  0x0013fad8  Yes (*)     /lib/libpthread.so.0
          0x001913a0  0x00212b58  Yes         /usr/lib/debug/libstdc++.so.6
          0x0024c4b0  0x002667f8  Yes (*)     /lib/libm.so.6
          0x00270f50  0x00287438  Yes         /lib/libgcc_s.so.1
          0x002a1ac0  0x003aba74  Yes (*)     /lib/libc.so.6
          (*): Shared library is missing debugging information.
          (gdb)
          哈哈,libstdc++也有了symbol了,這樣就可以設(shè)置斷點(diǎn),然后step into就可以跟蹤到stl的內(nèi)部了。

          ============================================
          linux下用vpn,安裝openconnect這個(gè)包,
          sudo /usr/bin/openconnect --script=/etc/vpnc/vpnc-script Your-Vpn-Server-Address
          ============================================
          > cat close.gdb
          p close(1)
          p close(2)
          #p dup2(open("/dev/null",0),1) #another way to close stdout
          #p dup2(open("/dev/null",0),2) #another way to close stderr
          #p open("/dev/pts/4", 1)     #redirect stdout to another tty
          #p open("/tmp/myerrlog", 1)  #redirect stdout to another file
          detach
          q
          > gdb -p 3465 -x close.gdb

          如果希望每次程序中斷后可以看到即將被執(zhí)行的下一條匯編指令,可以使用命令
          "display /i $pc"
          其中 $pc 代表當(dāng)前匯編指令,/i 表示以十六進(jìn)行顯示。當(dāng)需要關(guān)心匯編代碼時(shí),此命令相當(dāng)有用。
          undispaly,取消先前的display設(shè)置,編號(hào)從1開始遞增。
          b *main”在 main 函數(shù)的 prolog 代碼處設(shè)置斷點(diǎn)(prolog、epilog,分別表示編譯器在每個(gè)函數(shù)的開頭和結(jié)尾自行插入的代碼)
          info registers #查看所有寄存器變量
          info registers rax #查看寄存器rax的值
          p $rax #查看寄存器rax的值
          disassemble #查看匯編代碼
          set disassembly-flavor intel # 設(shè)置反匯編格式
          x/1uw $rbp-0x8 #查看某個(gè)內(nèi)存地址里的值
          info proc mappings #查看進(jìn)程地址空間中各塊內(nèi)存的分配
          set follow-fork-mode child #調(diào)試子進(jìn)程
          layout src #使用tui(Text User Interface),打開src和cmd兩個(gè)窗口
          layout split #使用tui,打開src,assemble,cmd三個(gè)窗口
          使用ctrl+x ctrl+a 或者 ctrl+x A 關(guān)閉tui
          使用ctrl+x o來切換active的窗口
          set environment varname [=value] 設(shè)置環(huán)境變量。如:set env USER=user
          部分引用自:http://laokaddk.blog.51cto.com/368606/945057 以及http://blog.csdn.net/kuike/article/details/2065999
          打印符號(hào)所處的源代碼位置:
          info line <function_name>
          python (lambda s: [print(i.symtab,":",i.line) for i in gdb.lookup_static_symbols(s)])("one")
          python (lambda s: print(s.symtab,":",s.line))(gdb.lookup_symbol("<variable_name>")[0])
          ============================================================================================
          如果有部分swap內(nèi)存被使用了,而這個(gè)時(shí)候主存還有地方,可以把swap里的內(nèi)容挪動(dòng)到主存里,方法是:
          sudo swapoff -a && sudo swapon -a

           

          =============================================================================================

          在本機(jī)假設(shè)一個(gè)最簡(jiǎn)單的http server的方法是:python -m SimpleHTTPServer &  #會(huì)偵聽本機(jī)的8000端口,服務(wù)目錄就是當(dāng)前目錄
          用netstat查看tcp協(xié)議監(jiān)聽的端口:netstat -nlpt
          用netstat查看udp協(xié)議監(jiān)聽的端口:netstat -nlpu
          當(dāng)然也可以用netstat -nlptu一并查看tcp和udp協(xié)議監(jiān)聽的端口

          用netstat查看tcp的連接:netstat -anpt
          用netstat查看udp的連接:netstat -anpu
          當(dāng)然也可以用netstat -anptu一并查看tcp和udp協(xié)議的連接

          探測(cè)一臺(tái)remote機(jī)器是否打開了某個(gè)端口,一般我們用telnet ip port,但這種方法不成功的時(shí)候并不能肯定這個(gè)端口就一定是closed,而且對(duì)于udp協(xié)議的端口,該方法也不奏效,正確的方法是:
          nc -z ip port && echo tcp port open || (nc -z ip port && echo udp port open || echo no tcp/udp port open)
          或許一些機(jī)器上沒有安裝nc,可以試試看是否安裝了netcat,這兩個(gè)工具是一樣的。
          再簡(jiǎn)要說說netcat這個(gè)工具,這個(gè)工具很有用,從名字上就看得出來它的用途,我們知道cat是針對(duì)文件進(jìn)行bytes流的in/out,而netcat是針對(duì)網(wǎng)絡(luò)端口進(jìn)行bytes流的in/out。
          比如
          1。netcat -l -p 13001 > t3.3 &   #listening 0.0.0.0:13001,把收到的內(nèi)容重定向到t3.3文件中,或許該命令需要修改為netcat -l 127.0.0.1 13001 > t3.3 &
          2。echo "hello world" | netcat 127.0.0.1 13001  #向127.0.0.1:13001端口灌入一定的bytes
          3。cat t3.3  #t3.3中的內(nèi)容就是hello world
          網(wǎng)絡(luò)上有一篇介紹基于udp的ssh tunnel的文章,就是用到了netcat這個(gè)工具:http://zarb.org/~gc/html/udp-in-ssh-tunneling.html

          可以通過tcpdump來查看一個(gè)端口上收發(fā)的所有包:
          tcpdump -vv -n -i lo 'tcp port 10000'

          ===================================================================

          vi小技巧:

          先按q再按:,則會(huì)出現(xiàn)歷史命令

          使用sudo權(quán)限保存w !sudo tee %

          在命令模式下,Ctrl+w,然后再按q即可退出,ZZ也可以退出

          Ctrl+o是退回到上次編輯的位置

          Ctrl+g可以顯示當(dāng)前編輯的文件名以及編輯的行數(shù)和列數(shù)

          %是匹配括號(hào)

          在~/.vimrc中輸入以下兩行可以實(shí)現(xiàn)再次打開文件時(shí)光標(biāo)位置被保存:

          " 打開文件時(shí),按照 viminfo 保存的上次關(guān)閉時(shí)的光標(biāo)位置重新設(shè)置光標(biāo)
          au BufReadPost * if line("'\"") > 0|if line("'\"") <= line("$")|exe("norm '\"")|else|exe "norm $"|endif|endif

          命令行Readline的快捷鍵:

          Ctrl+a/e:跳到行首/尾;Ctrl+u/k:刪除前/后面的內(nèi)容;Ctrl+h/d:刪除前/后一個(gè)字符;Ctrl+b/f:移動(dòng)前/后一個(gè)字符;Ctrl+p/n:查看前/后一條命令;Ctrl+Esc+r:恢復(fù)該行最初始的狀態(tài);Ctrl+r/s:向前/后根據(jù)搜索詞在歷史命令中進(jìn)行搜索(其實(shí)還有 Ctrl+s 是正向增量查找的,但是由于這個(gè)快捷鍵被終端預(yù)設(shè)成鎖屏幕了,沒有效果。不過可以使用命令 stty -ixon -ixoff來解除綁定,恢復(fù)可以用stty ixon ixoff<其此處的設(shè)置對(duì)應(yīng)了Ctrl+s/q這組命令,即鎖定/解鎖屏幕,尤其用在屏幕上出現(xiàn)飛速的碼流的時(shí)候有效果>);Alt+b/f:向前/后移動(dòng)一個(gè)單詞;Alt+Backspace/d:向前/后刪除一個(gè)單詞;要想了解更多這方面的快捷鍵可以使用bind -P

          syndaemon -d -i 4可以使得:當(dāng)你輸入文字時(shí),觸摸板失效4秒

          showkey -a可以顯示鍵盤上任意一個(gè)鍵的ascii碼值,Ctrl+v加Ctrl+<key>能顯示該鍵的鍵盤碼

          grep的-I選項(xiàng)(大寫的i)可以讓它不搜索binary文件,而-a選項(xiàng)是搜索所有文件,binary文件也會(huì)當(dāng)成文本文件去搜索,此外還可以配合--exclude/include=GLOB來排除文件或者搜索特定文件,--exclude-dir=DIR可以排除一個(gè)或多個(gè)文件夾,-o選項(xiàng)只搜索出匹配的部分,比如你要在~目錄下搜索隱藏文件中的配置文件中的一些信息,可以這樣: grep <searchword> -RI --include=.*  --exclude-dir=.ies4linux .

          在所有命令中查找匹配的命令: ls ${PATH//:/\ /} | grep <searchword>

          有關(guān)對(duì)readline的控制,強(qiáng)烈推薦下面這兩篇文章:

          http://blog.chinaunix.net/u1/43271/showart_340284.html

          http://hi.baidu.com/riant/blog/item/aacf7cd9d0f91fe939012f88.html

          這里我對(duì)bind命令作一下說明,舉個(gè)例子好了,設(shè)定Ctrl+t是正向搜索歷史命令(相對(duì)于Ctrl+r反向搜索):如果臨時(shí)使用,那么bind '"\C-t": forward-search-history'即可;如果長(zhǎng)久保存,那么首先在~/.bashrc中設(shè)定export INPUTRC=/etc/inputrc,然后編輯/etc/inputrc,增加一行:"\C-t": forward-search-history即可。我還在/etc/inputrc中設(shè)定了"C-xf": dump-functions和"C-xv": dump-variables以及"C-xm": dump-macros三行,分別用于打印出所有可以設(shè)置的函數(shù)、變量、以及宏。注意:每次你修改完/etc/inputrc文件后,需要Ctrl-x然后Ctrl-r才能使修改發(fā)揮作用。

          在X的終端里,Ctrl+Shift+up/down可以實(shí)現(xiàn)屏幕的上下滾動(dòng),一行一行的滾動(dòng);shift+pageup/pagedown實(shí)現(xiàn)一屏一屏的滾動(dòng)

          ls的小技巧:

          alias ls='ls --color=tty'
          alias ll='ls -l --color=tty'
          alias l.='ls -a -d .* --color=tty'
          alias lD='ls -a -d --color=tty .*/; ls -d */ --color=tty'
          alias la='ls -A'

          strace -p <PID>可以看到該進(jìn)程執(zhí)行的系統(tǒng)調(diào)用,其實(shí)該命令會(huì)把一個(gè)進(jìn)程先attach然后分析,最后再釋放。

          還是bind的使用,我們可以配置ctrl+m來選擇一個(gè)目錄下的文件,這個(gè)特性對(duì)于那些文件名字特別難輸入的文件或目錄特別有幫助,你可以設(shè)想一下當(dāng)在字符終端上沒有鼠標(biāo),且沒安裝中文輸入法時(shí),你想打開一個(gè)含有中文文件名的文件是多么困難,但是有了這個(gè)特性,你就可以自由選擇了。實(shí)施方法如下:

          編輯/etc/inputrc,找到類似這行的(沒有就添加):
          代碼:
          $if mode=emacs
          "\C-o": menu-complete

          或者在命令行直接使用bind '"\C-o":menu-complete'也可以。

          ================================

          mv foo.{jpeg,jpg}#這個(gè)命令將把foo.jpeg改名為foo.jpg。
          !! 是整條命令和所有參數(shù)
          !* 將代替上一個(gè)命令的所有參數(shù)
          !$ 上一條命令的最后一個(gè)參數(shù)
          !:3  上一條命令的第3個(gè)參數(shù) 

          ===========================================

          vi學(xué)習(xí)
          :r !command: 將命令command的輸出結(jié)果放到當(dāng)前行
          :e filename: 打開文件filename進(jìn)行編輯(會(huì)關(guān)閉當(dāng)前文檔重新打開新文檔,可以使用Ctrl+O/I來切換)
          :n1,n2 d: 將 n1行到n2行之間的內(nèi)容刪除
          :r filename: 將文件中的內(nèi)容全部插入到當(dāng)前位置

          Ctrl+a: 如果當(dāng)前光標(biāo)下的字符串中,從當(dāng)前位置起能在后續(xù)連續(xù)的字符串中找到數(shù)字,那么按一次Ctrl+a就會(huì)使得該數(shù)字加1,比如abc23, 那么就會(huì)使得23變?yōu)?4
          s: 刪除當(dāng)前字符,并切換到插入模式,可以允許你輸入文本
          H: 光標(biāo)移至屏幕頂行
          M: 光標(biāo)移至屏幕中間行
          L: 光標(biāo)移至屏幕最后行
          nz: 將第n行滾至屏幕頂部,不指定n時(shí)將當(dāng)前行滾至屏幕頂部,注意需要回車一下才生效。

          vi +n filename: 打開文件,并將光標(biāo)置于第n行首
          ?pattern: 從光標(biāo)開始處向文件首搜索pattern

          w或W : 光標(biāo)右移一個(gè)字至字首
          b或B : 光標(biāo)左移一個(gè)字至字首
          dw: 刪除右邊的一個(gè)字
          db: 刪除左邊的一個(gè)字

          browse vs/split: 用瀏覽窗口輔助你打開文件
          Ctrl+w,w  用于窗口間切換, 用Ctrl+w,Ctrl+w也可以, 這里主要考慮到了按鍵方便
          Ctrl+w,o  只保留當(dāng)前窗口, 關(guān)閉其他窗口
          Ctrl+w,=  平均分配各個(gè)窗口
          Ctrl+w,數(shù)字<  在垂直切分窗口時(shí),縮小當(dāng)前窗口尺寸
          Ctrl+w,數(shù)字>  在垂直切分窗口時(shí),放大當(dāng)前窗口尺寸
          Ctrl+w,數(shù)字-  在水平切分窗口時(shí),縮小當(dāng)前窗口尺寸
          Ctrl+w,數(shù)字+  在水平切分窗口時(shí),放大當(dāng)前窗口尺寸
          Ctrl+w,c  關(guān)閉當(dāng)前窗口
          Ctrl+w,s  將當(dāng)前窗口橫著切割出另一個(gè)窗口, Ctrl+w,n也可以
          Ctrl+w,v  將當(dāng)前窗口豎著切割出另一個(gè)窗口
          :split 文件名  用于在當(dāng)前窗口中橫著切割出一個(gè)新的窗口, 并且將文件打開
          :vs 文件名  用于在當(dāng)前窗口中豎著切割出一個(gè)新的窗口, 并且將文件打開

          mark標(biāo)記: 新建一個(gè)標(biāo)記用m, 后面可接數(shù)字或字母,  小寫字母僅能用于本文件中根據(jù)標(biāo)記定位光標(biāo)位置, 大寫字母可以實(shí)現(xiàn)文件之間的切換, 例如ma,m3,mA; 定位一個(gè)標(biāo)記用單引號(hào), 例如'a,'3,'A. 這里再舉個(gè)應(yīng)用mark的例子, 在命令行模式下:'a,'b d用于刪除從'a到'b之間所有的行. 查看所有的mark的命令是:marks

          vi的寄存器: 用雙引號(hào)來建立, vim常用的寄存器有:
          ""     無名寄存器,包含最近刪除或抽出的文本
          "%     當(dāng)前文件名
          "#     輪換文件名
          "*     剪貼板內(nèi)容 (X11中表示 鼠標(biāo)選擇的區(qū)域)
          "+     剪貼板內(nèi)容
          "/     最近的搜索模式
          ":     最近的命令行
          ".     最近插入的文本
          "_     黑洞
          更為詳細(xì)的內(nèi)容請(qǐng)參見http://blog.chinaunix.net/u/553/showart_361240.html和http://blog.chinaunix.net/u/9465/showart_448822.html
          調(diào)用寄存器時(shí), 在普通模式可以用雙引號(hào)來調(diào)用, 如"a, 在插入模式下可以用Ctrl+r,a來調(diào)用寄存器a;對(duì)于用大寫字母表示的寄存器比如A, 代表向寄存器a中追加內(nèi)容; 查看所有寄存器的內(nèi)容用:reg
          "+y用于把vi中選中的部分復(fù)制到系統(tǒng)剪貼板上; "+yy用于把當(dāng)前行復(fù)制到系統(tǒng)剪貼板上;"+p用于把系統(tǒng)剪貼板上的東西復(fù)制到當(dāng)前位置

          查看所有對(duì)文件的改動(dòng)用:changes

          vi使用ctags和taglist:
          在工程的頂層目錄下ctags -R
          vi –t main//可以打開所有定義了main函數(shù)的cpp文件
          :ts//會(huì)列出所有定義了main函數(shù)的位置, 你可以通過鍵入數(shù)字來選擇
          :tp//會(huì)在選擇下一個(gè)出現(xiàn)了main函數(shù)的cpp文件來顯示
          :tn//會(huì)在選擇上一個(gè)出現(xiàn)了main函數(shù)的cpp文件來顯示
          說明: 上面的ts,tp,tn都是針對(duì)vi -t main這個(gè)應(yīng)用來談的, 其實(shí)它們也可以脫離這種場(chǎng)景去使用, 總之它們就是構(gòu)建在ctags之上的, 用于搜索所有源文件中定義的變量或函數(shù)名之類的東西.

          WEB相對(duì)于web來說是長(zhǎng)單詞移動(dòng)命令,即只認(rèn)識(shí)空格和換行
          {/}到上/下一段落
          [[/]]到上/下一個(gè)代碼塊{...}的開始處
          [{/]}到當(dāng)前代碼塊{...}的{/}
          (/)移動(dòng)到句首/尾
          S在當(dāng)前行的任何一個(gè)位置運(yùn)行該命令,可以把當(dāng)前行的內(nèi)容清空,然后移動(dòng)到行首進(jìn)入插入模式等待你輸入字符, 該命令等同于cc命令
          3S把當(dāng)前的三行內(nèi)容清空,并移動(dòng)到行首且進(jìn)入插入模式等待輸入
          s清空當(dāng)前字符,并進(jìn)入插入模式等你輸入字符
          10s清空當(dāng)前的10個(gè)字符,并進(jìn)入插入模式等你輸入字符,實(shí)際上對(duì)s和S的比較標(biāo)準(zhǔn)的翻譯是s多字符替換單字符,S整行替換
          .可以重復(fù)執(zhí)行上一次的改變, 所謂改變指的是插入(i)或者刪除(d)或者替換(r)或者改變(c)的一次原子操作, 也就是不能將先刪除(d)3個(gè)字符再插入(i)5個(gè)字符這件事作為一個(gè)整體來對(duì)待, 如果想把這種情況用一次原子操作來完成, 你可以用c命令, 該命令會(huì)先直接把你想要改變的那個(gè)3個(gè)字符刪掉再允許你輸入5個(gè)字符作為替換
          qa開始錄制宏,并報(bào)存在寄存器a中,再次輸入q即可停止錄制宏,錄制宏的時(shí)候要注意在使用hjkl這些移動(dòng)光標(biāo)的命令時(shí)確保應(yīng)用宏的時(shí)候不會(huì)有什么偏差,建議最好使用命令能定位光標(biāo),比如fFtT這樣的一行內(nèi)的查找命令,有一篇文章舉的例子非常好:http://autodev.net/autodev/discuz/viewthread.php?tid=33
          :ab可以list出目前所有已經(jīng)有的縮寫
          :ab hl hello world!可以用hl這個(gè)縮寫來代替hello world!,當(dāng)你在insert模式下輸入hl后,再鍵入空格或者換行時(shí)就會(huì)發(fā)生上述的替換
          :unab hl撤銷hl這個(gè)縮寫
          d3w將刪除光標(biāo)后 3 個(gè)單詞
          d2j將刪除當(dāng)前行和下兩行
          :%s/regexp/replacement/gc可以讓你在替換之前確認(rèn)一下
          <</>>將當(dāng)前行向左/右縮進(jìn)一次,縮進(jìn)一次的大小取決于tabstop被設(shè)定的大小
          Ctrl+d/t在插入模式下向左/右縮進(jìn)當(dāng)前行
          ^移動(dòng)到當(dāng)前行的第一個(gè)非空白字符
          -/+移動(dòng)到上/下一行的第一個(gè)非空白字符
          ]p粘貼的時(shí)候會(huì)考慮到縮進(jìn)

          下面這個(gè)映射能夠使得在可視模式下選擇的文本,當(dāng)你按下'/'鍵時(shí)由擴(kuò)展可視范圍改為搜索選擇的文本

          :vmap / y/<C-R>"<CR>

          下面的鍵映射能夠使得在insert mode下移動(dòng)光標(biāo):

          " 在插入模式下,移動(dòng)光標(biāo)
          imap <C-h> <C-o>h
          imap <C-j> <C-o>j
          imap <C-k> <C-o>k
          " to the left character, this way can go to the behind of last character
          imap <C-l> <ESC>la
          " to the begin of line
          imap <C-a> <ESC>0i
          " to the end of line
          imap <C-u> <ESC>A


          set list
          set listchars=tab:>-,trail:-
          highlight WhitespaceEOL ctermbg=magenta guibg=magenta
          match WhitespaceEOL /\s\+$\|\t/
          "highlight __SPACE ctermbg=yellow guibg=yellow
          "2match __SPACE / /

          ====================================
          ls -sSh
          ====================================
          發(fā)現(xiàn)驚天大秘密:呵呵,以前總覺得^A^B這些東西很奇怪,現(xiàn)在不覺得奇怪了,其實(shí)是有這樣一種邏輯在里面的:^A代表ascii碼為1的不可見字符,^B代表ascii碼為2的不可見字符,以此類推,因此我們最最熟悉的^M就代表ascii碼為13的字符了,也就是回車符號(hào),而在linux的文本中都是使用換行符號(hào)作為行與行之間的分隔符的,因此^J就代表了換行符號(hào),你可以用showkey -a來驗(yàn)證我說的這些東西,但^這個(gè)符號(hào)要用ctrl鍵來代替,因此你要輸入ctrl+m才能看到效果。

          =============================
          top使用:
          f/o:選擇其他列;F/O:選擇要按之排序的列;R:反向排序;c:顯示完整的命令
          行;u:指定顯示某個(gè)用戶相關(guān)的信息;1:數(shù)字1顯示分開顯示多核 CPU;k:殺死
          某個(gè)PID;s:設(shè)置刷新的時(shí)間間隔;A:分四屏從不同角度顯示;G:從四種可供選
          擇的顯示組合中選定一種特定的顯示組合;B:加粗顯示 head里的數(shù)字信息;z:
          切換為紅黃顏色顯示;Z:選擇顏色顯示;</>:默認(rèn)按照%CPU排序,選定的排序的
          列向左/右移動(dòng)一列。
          ========================
          info的使用:
          b是到開頭,e是到結(jié)尾;到了某個(gè)結(jié)點(diǎn)回車是進(jìn)入,u是返回上級(jí);l(小寫的L)相當(dāng)于后退;空格是向下翻頁,page up/down是向上/下翻頁;?是幫助;n和p分別是到下一個(gè)或上一個(gè)結(jié)點(diǎn)。
          ===========================
          screen使用:
          配置~/.screenrc為:

          altscreen on
          startup_message off
          defscrollback 100000
          #escape ^Xx
          backtick 1 0 0 sh -c 'echo $(ifconfig | grep Mask: | cut -d: -f2 | cut -d" " -f1 | grep -v 127.0.0.1; curl -s ifconfig.me)'
          backtick 2 60 60 sh -c 'uptime | sed -e "s/.*up *//" -e "s/,.*//"'
          #caption always "%{= wk} %{= KY} [%n]%t @ %H %{-} %= %{= KR} %l %{-} | %{= KG} %Y-%m-%d %{-} "
          ##hardstatus alwayslastline " %-Lw%{= Bw}%n%f %t%{-}%+Lw %=| %0c:%s "
          hardstatus alwayslastline "%{= KY} %-Lw%{= Bw}%n%f %t%{-}%+Lw %=@%H(%1`) %{=b KG}||%{-} %m/%d %0c %{=b KG}||%{-} up %2` %{=b KG}||%{-} %l"
          # mouse tracking allows to switch region focus by clicking, and you can't select texts by double-click texts if you open this flag
          # mousetrack on
          # get rid of silly xoff stuff
          bind s split
          # layouts
          layout autosave on
          # layout one region
          layout new one
          select 1
          # layout two region
          layout new two
          select 1
          split
          resize -v +8
          focus down
          select 4
          focus up
          # layout three region
          layout new three
          select 1
          split
          resize -v +7
          focus down
          select 3
          split -v
          resize -h +10
          focus right
          select 4
          focus up
          layout attach one
          layout select one
          # navigating regions with Ctrl-arrows
          bindkey "^[[1;5D" focus left
          bindkey "^[[1;5C" focus right
          bindkey "^[[1;5A" focus up
          bindkey "^[[1;5B" focus down
          # switch windows with F3 (prev) and F4 (next)
          bindkey "^[OR" prev
          bindkey "^[OS" next
          # switch layouts with Ctrl+F3 (prev layout) and Ctrl+F4 (next)
          bindkey "^[[1;5R" layout prev
          bindkey "^[[1;5S" layout next
          # F2 puts Screen into resize mode. Resize regions using hjkl keys.
          bindkey "^[OQ" eval "command -c rsz" # enter resize mode
          # use hjkl keys to resize regions
          bind -c rsz h eval "resize -h -5" "command -c rsz"
          bind -c rsz j eval "resize -v -5" "command -c rsz"
          bind -c rsz k eval "resize -v +5" "command -c rsz"
          bind -c rsz l eval "resize -h +5" "command -c rsz"
          # quickly switch between regions using tab and arrows
          bind -c rsz \t    eval "focus"       "command -c rsz" # Tab
          bind -c rsz -k kl eval "focus left"  "command -c rsz" # Left
          bind -c rsz -k kr eval "focus right" "command -c rsz" # Right
          bind -c rsz -k ku eval "focus up"    "command -c rsz" # Up
          bind -c rsz -k kd eval "focus down"  "command -c rsz" # Down

          使用時(shí),新建一個(gè)tab是ctrl+a,c;退出一個(gè)tab是ctrl+d(其實(shí)就是正常退出即可,當(dāng)然你也可以使用screen為你提供的ctrl+a,k來實(shí)現(xiàn));退出所有的tab是ctrl+a,:quit或者是ctrl+a,ctrl+\也可以; 想退出screen干點(diǎn)別的事,但是卻不終止screen里面的進(jìn)程,這叫detach,用ctrl+a,d可以實(shí)現(xiàn),下次再想進(jìn)入那個(gè)screen的時(shí)候,需要screen -ls一下看看當(dāng)前都有那些screen, 然后screen -r <名字>來進(jìn)入你想進(jìn)入的screen, 當(dāng)然你也可以在啟動(dòng)screen的時(shí)候這么干: screen -S hello,當(dāng)你detach screen之后想再次進(jìn)入,那就screen -r hello即可.
          ctrl+a,': select a tab;
          ctrl+a,": open window manager to select a tab;

          Ctrl+a S split terminal horizontally into regions Ctrl+a c to create new window there
          Ctrl+a | split terminal vertically into regions Requires debian/ubuntu patched screen 4.0
          Ctrl+a :resize resize region  
          Ctrl+a :fit fit screen size to new terminal size Ctrl+a F is the same. Do after resizing xterm
          Ctrl+a :remove remove region Ctrl+a X is the same
          Ctrl+a tab Move to next region

          admin login
          screen -S class1
          Ctrl-a :multiuser on
          Ctrl-a :acladd lili

          lili login
          screen -x admin/session
          Ctrl-a :aclchg lili -w "#"

          Ctrl-a :wall message

          For detail info, plz refer to: http://www.linux.com/archive/feed/56443
          如果screen的sock文件被刪了(默認(rèn)是在/tmp/下),導(dǎo)致無法attach,可以重建sock文件,方法是kill -CHLD 30860 #30860為screen進(jìn)程的pid
          ===============================
          對(duì)于sudo這個(gè)命令,修改配置文件/etc/sudoers時(shí)直接用visudo就可以了,連文件名都省略了,而且還可以幫助你檢查格式,關(guān)于怎么寫配置文件的內(nèi)容,請(qǐng)使用man sudoers,在幫助的最后部分給出了大量的實(shí)例,足夠你使用了,如果覺得看英文不爽,網(wǎng)上有很多這份man sudoers的中文版,比如http://www.fengnet.com/showart.asp?art_id=587&cat_id=10 我來總結(jié)一下,其實(shí)定義的格式就是who hosts = (可以偽裝成的用戶) [NOPASSWD:] commands
          ==============================
          對(duì)于sort命令, 最復(fù)雜的莫過于對(duì)POS1和POS2的設(shè)定了, 先給出結(jié)構(gòu):
          -k POS1,POS2 -k POS3,POS4, 例如sort -t : -n -k 5b,5b -k 3,3 /etc/passwd
          多個(gè)-k可以指定多個(gè)排序的鍵, 通常我們很少使得排序的鍵是跨越field的, 因此通常你會(huì)看到像上面那個(gè)例子里描述的那樣, 兩個(gè)5, 兩個(gè)3
          下面就來說一下POS的規(guī)則, 分為新標(biāo)準(zhǔn)和舊標(biāo)準(zhǔn), 新標(biāo)準(zhǔn):F[.C][Mbdfinr], 詳細(xì)說明如下:
          F是數(shù)字,代表第幾個(gè)Field;
          C是數(shù)字,代表Field內(nèi)部的第幾個(gè)字符;
          Mbdfinr代表選項(xiàng), 與sort -[Mbdfinr]一樣, 只不過前者只對(duì)當(dāng)前POS有效, 后者對(duì)所有有效, 不過前者的優(yōu)先級(jí)高于后者, 此處還有一點(diǎn)要說明: 因?yàn)橐粋€(gè)-k會(huì)指定兩個(gè)POS,只要有一個(gè)POS中指定了Mbdfinr即可, 兩個(gè)都指定同一個(gè)也行
          再說說舊標(biāo)準(zhǔn): +POS1 -POS2
          POS的規(guī)則和前面一樣, 但舊標(biāo)準(zhǔn)就只能指定一個(gè)key了, 不能像-k那樣可以搞出多個(gè)來; 而且在舊標(biāo)準(zhǔn)中的Field采用的是間隔的方式, 如果你期望按照第一個(gè)key來排序,那么就得使用+0 -1來實(shí)現(xiàn), 而在新標(biāo)準(zhǔn)中是采用 -k 1,1
          ==================================
          簡(jiǎn)要說說lsof最常用的幾種方法:
          lsof 文件 ==>查看文件被那些進(jìn)程占用
          lsof -c bash ==>查看被進(jìn)程名以bash開頭的進(jìn)程占用的文件
          lsof -u root ==>查看root用戶使用到的文件
          lsof -p 2343 ==>查看被進(jìn)程2343打開的文件
          lsof 目錄名 ==>查看目錄下打開的文件, 不遞歸, 深度為1
          lsof +D 目錄名 ==>查看目錄下打開的文件, 遞歸
          lsof -i ==>顯示所有端口建立的連接
          lsof -i :80 ==>顯示所有打開80端口的連接
          lsof -d 4==> 顯示fd為4的進(jìn)程
          lsof -a -d4 -p $$ ==>這里的選項(xiàng)a表示將對(duì)d選項(xiàng)和p選項(xiàng)的結(jié)果的AND操作
          ========================
          關(guān)閉筆記本的屏幕的方法: xset dpms force off
          ================================
          vim 提供 6中折疊方式
                    manual           手工定義折疊(默認(rèn),常用)
                    indent             更多的縮進(jìn)表示更高級(jí)別的折疊(常用)
                    expr                用表達(dá)式來定義折疊
                    syntax             用語法高亮來定義折疊(常用)
                    diff                  對(duì)沒有更改的文本進(jìn)行折疊
                    marker            對(duì)文中的標(biāo)志折疊

          set fdm=indent
          如果使用了indent方式,vim會(huì)自動(dòng)的對(duì)大括號(hào)的中間部分進(jìn)行折疊,我們可以直接使用這些現(xiàn)成的折疊成果。
          indent 對(duì)應(yīng)的折疊代碼有:
          zc      折疊
          zC     對(duì)所在范圍內(nèi)所有嵌套的折疊點(diǎn)進(jìn)行折疊
          zo      展開折疊
          zO     對(duì)所在范圍內(nèi)所有嵌套的折疊點(diǎn)展開
          [z       到當(dāng)前打開的折疊的開始處。
          ]z       到當(dāng)前打開的折疊的末尾處。
          zj       向下移動(dòng)。到達(dá)下一個(gè)折疊的開始處。關(guān)閉的折疊也被計(jì)入。
          zk      向上移動(dòng)到前一折疊的結(jié)束處。關(guān)閉的折疊也被計(jì)入。

          set fdm=manual
          可以使用下面的命令來創(chuàng)建和刪除折疊:
          zf      創(chuàng)建折疊,比如在marker方式下:
                             zf56G,創(chuàng)建從當(dāng)前行起到56行的代碼折疊;
                             10zf或10zf+或zf10↓,創(chuàng)建從當(dāng)前行起到后10行的代碼折疊。
                             10zf-或zf10↑,創(chuàng)建從當(dāng)前行起到之前10行的代碼折疊。
                             在括號(hào)處zf%,創(chuàng)建從當(dāng)前行起到對(duì)應(yīng)的匹配的括號(hào)上去((),{},[],<>等)。
          zd      刪除 (delete) 在光標(biāo)下的折疊。僅當(dāng) 'foldmethod' 設(shè)為 "manual" 或 "marker" 時(shí)有效。
          zD     循環(huán)刪除 (Delete) 光標(biāo)下的折疊,即嵌套刪除折疊。
                    僅當(dāng) 'foldmethod' 設(shè)為 "manual" 或 "marker" 時(shí)有效。
          zE     除去 (Eliminate) 窗口里“所有”的折疊。
                    僅當(dāng) 'foldmethod' 設(shè)為 "manual" 或 "marker" 時(shí)有效。
                 因此,對(duì)于fdm=indent之后,如果想消除通篇的折疊,簡(jiǎn)單方法就是set fdm=manual,然后zE
          可以通過下面兩個(gè)來控制通篇折疊的啟停:
          :set nofoldenable
          :set foldenable

          ===============================================================
          vim的幫助很詳細(xì),但若不了解有時(shí)的確不知道應(yīng)該如何輸入關(guān)鍵詞,所以總結(jié)一下:
          -----------------------------------------------------------------------------
          條目                                      前綴                       例子
          -----------------------------------------------------------------------------
          Normal模式命令                    無                          :h k
          CTRL控制字符                       CTRL-                     :h CTRL-r
          Visual視圖模式                      v                            :h v_u
          Insert插入模式命令                i                             :h i_CTRL-o
          ex-模式命令                           :                            :h :set                                                                                         
          Command-line命令行編輯     c                            :h c_<BS>
          命令參數(shù)                                -                            :h -m
          選項(xiàng)                                      '                             :h 'winminwidth'
          ------------------------------------------------------------------------------
          哦,還有一些關(guān)鍵詞是用尖括號(hào)<>括起來的,如
          :h <Left>
          :h <CR>
          :h <Up>
          :helpg[rep] {pattern}  搜索所有的幫助文本并給出一個(gè)匹配 {pattern} 行的列表, 用:cw打開quickfix窗口看到所有的匹配位置, :cn/p用于向后/前翻看

          另外,在輸入關(guān)鍵詞的時(shí)候,可以按Tab鍵補(bǔ)全,ctrl-d列出與光標(biāo)前面的關(guān)鍵詞所匹配的名字,ctrl-a列出全部模式
          =======================================
          在安裝了vim的插件之后,雖然幫助文檔已經(jīng)放到doc目錄下了,但是還是需要調(diào)用vim的一個(gè)命令才能讓help找到,該命令是::helptags ~/.vim/doc
          =======================================
           vim里面的tab:
          vim *.cpp -p //用多個(gè)tab打開多個(gè)文件
          在normal模式下:
            gt //切換到下一個(gè)tab
            gT //切換到上一個(gè)tab
            Ctrl-w T //把當(dāng)前的window放到一個(gè)新的tab中打開
          在command模式下:
            :tabnew [filename] //打開一個(gè)新的tab
            :tabn //切換到下一個(gè)tab
            :tabp //切換到上一個(gè)tab
            :tabs //list出當(dāng)前所有的tab

          vim里面的gf:
          在noraml模式下:
            gf //打開鼠標(biāo)下的文件
            gF //打開鼠標(biāo)下的文件,并且跳轉(zhuǎn)到指定的行(例如 t1.cpp 20)
            Ctrl+w f //水平切分出一個(gè)新的窗口,里面打開鼠標(biāo)下的文件
            Ctrl+w F //水平切分出一個(gè)新的窗口,里面打開鼠標(biāo)下的文件,并且跳轉(zhuǎn)到指定的行(例如 t1.cpp 20)
            Ctrl+w gf //打開一個(gè)新的tab,里面打開鼠標(biāo)下的文件
            Ctrl+w gF //打開一個(gè)新的tab,里面打開鼠標(biāo)下的文件,并且跳轉(zhuǎn)到指定的行(例如 t1.cpp 20)
          gf, gF, Ctrl+w gf, Ctrl+w gF均支持在visual模式下,只處理visual部分對(duì)應(yīng)的文件
          ======================================================================
          gcc/g++步驟拆解:
          gcc -E hello.c -o hello.i//使用cpp命令
          gcc -S hello.i -o hello.s//使用cc1命令
          gcc -c hello.s -o hello.o//使用as命令
          gcc hello.o -o hello//使用ld命令
          注意事項(xiàng):
          1. 這些步驟是對(duì)文件名的后綴有要求的,例如-E產(chǎn)生hello.E,然后在-S步驟是不行的;
          2. 用g++可以對(duì)cpp文件做同樣的步驟;
          gcc 參數(shù):
          -S: 生成匯編文件
          -E: 輸出預(yù)編譯結(jié)果 或者 用cpp t.cpp也行; 基本上g++ -E就等于cpp
          -H: 編譯并打印出引用的頭文件
          -E -dD: 預(yù)編譯, 并且將用到的宏擴(kuò)展都給列了出來
          -###: 打印出編譯gcc時(shí)用到的參數(shù)
          # 與宏有關(guān)的
          gcc -dM -E - <<< '' -o a.E #查看gcc builtin的宏
          gcc -dM -E a.cpp -o a.dM #查看所有相關(guān)的宏定義
          gcc -dD -E a.cpp -o a.dD #查看所有相關(guān)的宏定義,并且指明出處
          gcc -E a.cpp -o a.E #查看宏替換完成,預(yù)編譯后的結(jié)果
          # 與頭文件有關(guān)的
          gcc -H a.cpp -o a.H #查看所有依賴的頭文件,而且引用關(guān)系通過行前綴.的多少能夠體現(xiàn)出來
          gcc -M a.cpp -o a.M #查看所有依賴的文件
          gcc -MM a.cpp -o a.MM #查看所有依賴的文件,但不包括系統(tǒng)頭文件
          gcc -MM -MP -MD -MF a.dep a.cpp -c -o a.o #正常編譯,但同時(shí)產(chǎn)出一個(gè)附屬品a.dep用于描述編譯a.cpp所有依賴的東西,a.dep可用于Makefile檢測(cè)a.cpp依賴是否有變化,這會(huì)比我們通常寫的a.o: a.cpp這種要強(qiáng)大的多;-MD是為了讓編譯繼續(xù)(-E會(huì)導(dǎo)致停在預(yù)編譯階段,-M/-MM/-MP等都會(huì)暗含-E參數(shù),加上-MD則會(huì)又把-E給省略掉);-MP是為了讓a.dep里除了a.cpp的所有依賴之外,還能有每一個(gè)依賴的phony target;-MF是用于指定附屬品的文件名,如果沒有這個(gè)參數(shù),默認(rèn)會(huì)使用a.d(a.d的由來是根據(jù)-o a.o得來的,如果是-o XXX.o,那么就是XXX.d)
          生成靜態(tài)庫(kù)用ar crs libtest.a *.o;還可以生成thin archive,用ar crsT libtest.a *.o. thin archive只是存了真正的.o的位置,因此體積很小,而且ar crsT libtest.a libanother.a會(huì)把libanother.a中的.o的位置提取出來放到libtest.a中,對(duì)于local build,thin archive非常棒。
          對(duì)于從靜態(tài)庫(kù)生成動(dòng)態(tài)庫(kù),標(biāo)準(zhǔn)的方法是ar x libtest.a(注意thin archive是不能ar x的,這里的libtest.a是普通的archive),然后再g++ -shared -o libtest.so *.o,但也可以直接用.a來生成.so,如果是普通archive,需要用-Wl,--whole-archive libtest.a -Wl,--no-whole-archive -lpthread -ld(這種方法,當(dāng)多個(gè).a中含有相同符號(hào)時(shí),會(huì)出現(xiàn)沖突,因?yàn)樵摲绞綍?huì)把.a中的所有符號(hào)都鏈接進(jìn)來);除了可以用--whole-archive方法,還可以用-Wl,--start-group *.a -Wl,--end-group,這種方法會(huì)解決repeated查找中間那些.a文件中的符號(hào),可以解決交叉依賴的問題,但要注意的是位于--start-group和--end-group之間的那些.a,它們只是被用于從中抽取必須的symbol,至于哪些symbol需要被用到,這個(gè)是由為生成.so所顯示指定的.o來決定的,如果不指定任何.o,僅僅用一大堆.a,那么生成的.so中不會(huì)有任何有用的symbol,例如g++ -shared -o libt28.so -Wl,--start-group libt28_1.a libt28_2.a libdict.a -Wl,--end-group產(chǎn)生的libt28.so中就不會(huì)含有l(wèi)ibt28_1.a libt28_2.a libdict.a中的任何symbol;但如果是g++ -shared -o libt28.so -Wl,--start-group libt28_1.a libt28_2.a libdict.a test.o -Wl,--end-group,那么會(huì)根據(jù)test.o中哪些symbol需要從libt28_1.a libt28_2.a libdict.a中得到來決定哪些symbol進(jìn)入最終的libt28.so。雖然.a的本質(zhì)就是.o的集合,但ld對(duì)待.a和.o是很不一樣的。ld還有一個(gè)鏈接選項(xiàng)是-u,可以顯示讓某個(gè)symbol變?yōu)閡ndified。
          ==========================================
          清除log中的顏色控制字符:sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"
          ================================
          more或less里面,默認(rèn)搜索的時(shí)候是大小寫*不敏感*的, 要想改為*敏感*的, 直接在正常狀態(tài)下鍵入-i即可, 再次鍵入-i即可切換到*不敏感*; 在vi里面默認(rèn)搜索是大小寫*敏感*的, 可以在搜索的時(shí)候通過添加\c的suffix改為*不敏感*, 例如輸入/abc\c
          =========================================
          svn merge -r 854:853 test.cpp
          svn diff --summarize -r 853:854
          svn pg svn:externals .
          svn ps svn:externals 'seg_tc https://bj-scm.tencent.com/search/search_discuz_rep/discuz_code_proj/trunk/rela_content/encode3.0/seg_tc' .
          svn ps svn:externals -F svn.externals .
          =========================================
          awk中的map真的很好使,此前沒用到這個(gè)東西,以后要多加利用了,哈哈。
          netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
          =========================================
          ps -eo pid,ppid,lstart,etime,cmd  | grep XXX #lstart代表進(jìn)程開始執(zhí)行的時(shí)間,etime是進(jìn)程運(yùn)行到現(xiàn)在歷時(shí)多久
          ps -ef 可以看到ppid
          =========================================
          grep -P 'a\tb'
          grep "a"$'\t'"b"
          grep 'a    b' #tab鍵的輸入方法是Ctrl+v,然后按tab鍵
          =============================================
          find -size +1000c -size -2000c #查找文件大小在(1000,2000)之間的文件
          find -size 1000c #查找文件大小正好等于1000的文件
          find -mmin -1 #查找近1分鐘之內(nèi)修改過的文件
          find -amin -1 #查找近1分鐘之內(nèi)訪問過的文件
          find -empty #查找空文件或空目錄

          ==============================================

          cat input_file | python -c "import zlib,sys;print zlib.compress(sys.stdin.read())" #用于壓縮,當(dāng)然改為uncompress就可用于解壓縮

          ==================================================

          1. 查看內(nèi)核版本命令:
          cat /proc/version
          uname -a
          2. 查看Linux版本:
          lsb_release -a
          cat /etc/issue
          cat /etc/*release*
          =====================================================
          vim下的cursorline和cursorcolumn
          set   cursorline
          highlight CursorLine ctermbg=lightmagenta term=bold cterm=bold
          "set   cursorcolumn                                                                                                                                                                                                                            
          "set   startofline! "當(dāng)cursorcolumn激活時(shí),當(dāng)ctrl+f/b翻頁時(shí),光標(biāo)會(huì)跑,取消了這個(gè)選項(xiàng)后,光標(biāo)就不跑了
          highlight CursorColumn ctermbg=lightmagenta term=bold cterm=bold

          ==================================================================
          在vi中執(zhí)行命令處理當(dāng)前文檔的內(nèi)容

          :! ls #執(zhí)行一下ls命令
          :.! for i in {1..100}; do echo $i; done #.代表當(dāng)前行,即把當(dāng)前行的內(nèi)容輸入給!后面的命令,!后面的命令用處理后的結(jié)果替換當(dāng)前行
          :%!sort | uniq -c #%代表所有行,即把所有行的內(nèi)容作為input給sort | uniq -c,輸出的結(jié)果再替換原有的所有行的內(nèi)容
          :23,28!grep ok #把23行到28行之間的內(nèi)容輸入給grep ok命令,用處理后的結(jié)果替換23行到28行之間的內(nèi)容
          :%! sudo tee % #第一個(gè)%代表該文檔的所有行,第2個(gè)%代表當(dāng)前的文件名,這個(gè)命令相當(dāng)于cat current_file | sudo tee current_file,其實(shí)就是相當(dāng)于用sudo權(quán)限重新把當(dāng)前內(nèi)容寫到文檔里,這對(duì)于我們忘記了用sudo vi current_file的人來說是多么美妙的一件事情啊

           ==============================================

          nm -C //demangle symbol
          nm -D -C //just dynamic symbol, 該選項(xiàng)用于查看so文件中的可以導(dǎo)出的符號(hào),即便so被strip也沒問題
          nm -l -C //print line number

          ==========================================

          編譯時(shí),第一步一般都是./configure
          這個(gè)shell腳本里面是通過pkg-config工具來辨認(rèn)依賴的包是否已經(jīng)安裝,configure過程的日志記錄在config.log文件中,如果configure失敗,可以查看該文件來進(jìn)行診斷
          ./configure --help | grep '\(dis\|en\)able' #查看可以配置的features
          pkg-config工具會(huì)讀取/usr/share/pkgconfig/目錄下的*.pc文件,*.pc文件中記錄了編譯包時(shí)的CFlags以及這個(gè)包在當(dāng)前機(jī)器里的includedir和libdir等信息。有時(shí)候通過dpkg -l會(huì)發(fā)現(xiàn)包已經(jīng)安裝,但卻沒有包對(duì)應(yīng)的pc文件,這個(gè)時(shí)候需要安裝該包的dev版。
          可以通過apt-file search XXX.pc來找到包含該文件的安裝包。
          如果某些時(shí)候無法通過apt-get install來安裝dev版的包,可以下載一個(gè)源碼包,然后./configure && make, make -n install可以查看都哪些文件要install,確認(rèn)之后make install,默認(rèn)是安裝到/usr/local/XXX/下面,這時(shí)可以cp /usr/local/XXX/lib/pkgconfig/XXX.pc /usr/share/pkgconfig/下,然后安裝;更好的方法是mkdir here_installation; ./configure --prefix=$PWD/here_installation; make; make install;然后export PKG_CONFIG_PATH=/home/admin/zbar-0.10+doc/ImageMagick-6.8.6-8/here_installation/lib/pkgconfig/,然后再編譯zbar-0.10+doc即可找到需要的pc文件了。
          cmake也是通過pkg-config來檢測(cè)包的安裝情況的,它的配置文件是CMakeLists.txt。
          下面這種編譯方式可以編譯出來debug版本的,而且只有靜態(tài)庫(kù):
          ./configure --prefix=$PWD/here_installation --disable-shared CFLAGS="-g -O0" CPPFLAGS="-g -O0" CXXFLAGS="-g -O0"
          ======================================================
          如果ssh連接很慢,可以用ssh -v來看一下debug信息,試試配置一下/etc/ssh/ssh_config文件里的GSSAPIAuthentication no選項(xiàng)。
          ======================================================
          sort -R file 或者shuf file可以random打亂文件順序,可以設(shè)置一個(gè)random的seed通過--random-source=FILE
          ======================================================
          通過gzip壓縮得到的*.gz文件和通過zlib庫(kù)壓縮出來的東西不一樣,前者通過zcat或者gunzip可以解壓縮,后者必須通過zlib庫(kù)來解壓縮,沒有現(xiàn)成的工具,不過可以使用cat XXX | python -c "import zlib,sys;print repr(zlib.decompress(sys.stdin.read()))"
          =======================================================

           

          wget -e http-proxy=proxy.satwe.com:8080 --proxy=on --proxy-user=hamo --proxy-passwd=8888 -c http://www.satwe.com
          =======================================================

           

          ssh-copy-id user@host

           

          man less | col -b > less.txt #這個(gè)命令可以讓你把man文件轉(zhuǎn)成純文本文件
          PAGER=cat man less > less.txt #這個(gè)命令可以讓你把man文件轉(zhuǎn)成純文本文件
          vim scp://username@host//path/to/somefile #vim一個(gè)遠(yuǎn)程文件
          curl ifconfig.me #當(dāng)你的機(jī)器在內(nèi)網(wǎng)的時(shí)候,可以通過這個(gè)命令查看外網(wǎng)的IP
          wget --random-wait -r -p -e robots=off -U mozilla http://www.example.com #下載整個(gè)www.example.com網(wǎng)站
          screen -d -m -S some_name ping my_router #后臺(tái)運(yùn)行一段不終止的程序,并可以隨時(shí)查看它的狀態(tài)。-d -m參數(shù)啟動(dòng)“分離”模式,-S指定了一個(gè)session的標(biāo)識(shí)。可以通過-R命令來重新“掛載”一個(gè)標(biāo)識(shí)的session。更多細(xì)節(jié)請(qǐng)參考screen用法 man screen
          ssh user@host cat /path/to/remotefile | diff /path/to/localfile - #比較一個(gè)遠(yuǎn)程文件和一個(gè)本地文件
          ssh user@server bash < /path/to/local/script.sh #在遠(yuǎn)程機(jī)器上運(yùn)行一段腳本。這條命令最大的好處就是不用把腳本拷到遠(yuǎn)程機(jī)器上
          man ascii #顯示ascii碼表
          mtr coolshell.cn #mtr命令比traceroute要好
          echo "ls -l" | at midnight #在某個(gè)時(shí)間運(yùn)行某個(gè)命令
          curl -u username -s "https://mail.google.com/mail/feed/atom" | perl -ne 'print "\t" if /<name>/; print "$2\n" if /<(title|name)>(.*)<\/\1>/;' #檢查你的gmail未讀郵件
          tr -c "[:digit:]" " " < /dev/urandom | dd cbs=$COLUMNS conv=unblock | GREP_COLOR="1;32" grep --color "[^ ]" #想看看Marix的屏幕效果嗎?
          echo 123456 | dd cbs=2 conv=unblock #把一行內(nèi)的字符按照固定寬度切分為多行
          ls | xargs -P 5 -i echo "This is:{}" #并行度為5來執(zhí)行命令

          ======================================================================

          搭建web-based ssh terminal
          參考:http://en.wikipedia.org/wiki/Web-based_SSH
          下載https://code.google.com/p/shellinabox/,運(yùn)行:sudo ./shellinaboxd -t -b -q --css=shellinabox/white-on-black.css
          =======================================================================
          jar的使用:
          jar tvf XX.jar;
          jar xvf XX.jar;
          jar cvf XX.jar a.class;
          javac的使用:
          javac -classpath /home/admin/a/b.jar:a/b/c.jar a.java
          使用jode把*.class文件反編譯成*.java文件:
          下載地址:http://jode.sourceforge.net/download.php
          jar xvf jode-1.1.2-pre1.jar
          java jode.decompiler.Main a.jar
          java的使用:
          java -h
          Usage: java [-options] class [args...]
                     (to execute a class)
             or  java [-options] -jar jarfile [args...]
                     (to execute a jar file)
          java jode.decompiler.Main a.jar #如果jode-1.1.2-pre1.jar里的META-INF/MANIFEST.MF文件里是這么寫的Main-Class: jode.decompiler.Main,那么也可以用java -jar jode-1.1.2-pre1.jar a.jar
          java -jar a.jar arg1 arg2 arg3
          =========================================================
          如果聲音異常,重啟聲卡:
          sudo alsa force-reload
          ===========================================================
          sudo apt-add-repository ppa:werner-jaeger/ppa-werner-vpn
          sudo apt-get update
          sudo apt-get install l2tp-ipsec-vpn

           

          ===========================================================
          man -l XXX.1 可以對(duì)指定文件用man
          ===========================================================
          今天觸發(fā)了一個(gè)bug,當(dāng)只有.a文件時(shí),下面兩種編譯是不一樣的:
          g++ -o WpuServer -Ithrift-0.9.0/here_installation/include/ -Iboost_1_53_0  -I../gen-cpp -Lthrift-0.9.0/here_installation/lib/ -pthread -lrt WpuServer.cpp ../gen-cpp/WorkitemProcessUnit.cpp ../gen-cpp/wpu_types.cpp ../gen-cpp/wpu_constants.cpp -lthrift #ld ok
          g++ -o WpuServer -Ithrift-0.9.0/here_installation/include/ -Iboost_1_53_0  -I../gen-cpp -Lthrift-0.9.0/here_installation/lib/ -pthread -lrt -lthrift WpuServer.cpp ../gen-cpp/WorkitemProcessUnit.cpp ../gen-cpp/wpu_types.cpp ../gen-cpp/wpu_constants.cpp #ld error
          ===========================================================
          hadoop fs -cat /home/mr/hadoop/tmp/mapred/system/job_201306051048_50459/job.jar | jar x #用于拿到任務(wù)相關(guān)的所有信息,包括map/reduce相關(guān)的程序和配置以及數(shù)據(jù)文件
          ===========================================================
          perl -e "alarm 2; exec @ARGV" "sleep 3; echo 35" #設(shè)置超時(shí)來運(yùn)行命令
          ===========================================================
          cat myfile | perl -MList::Util=shuffle -e 'print shuffle(<STDIN>);' #替代shuf命令
          ===========================================================
          tac #按照行reverse
          rev #行內(nèi)按照字符reverse
          diff #按照行進(jìn)行diff
          cmp #按照字符進(jìn)行diff
          > test.txt echo "hello world!" #輸出到test.txt文件中
          < test.txt cat #從text.txt文件中讀取內(nèi)容
          cat <(echo "abcd") #cat讀的是一個(gè)文件
          cat < <(echo "abcd") #cat讀的是stdin
          cat <<<"abcd" #cat讀的是stdin
          cat <<{{
          abcd
          {{ #cat讀的是stdin
          cat <<{{ test.txt
          abcd
          {{ #cat讀的是stdin和test.txt文件
          cmp -bl <(echo "abcde") <(echo "abCdE") #比較兩個(gè)等長(zhǎng)的字符串,并打印出不同的字符
          =============================================================
          echo a我bc' | grep -P "[\x20-\x7F]"
          grep -o -P '(?<=<text><!\[CDATA\[).*?(?=\]\]></text>)'
          regex有BRE(Basic Regular Expression),ERE(Extended Regular Expression),PCRE(Perl Compatible Regular Expression)三種,GNU的BRE和ERE是一樣的,PCRE支持正反向預(yù)查以及非貪婪模式,上面那個(gè)正則用于從xml中找出<text>...</text>之間的文字,注意.*?,這里的?是表示非貪婪匹配,即盡可能短的去匹配。

          ==============================================================

          $ printf "\xe6\x88\x91\xe4\xbb\xac\n" 
          我們
          $ printf "%'d\n" 23423423423
          23,423,423,423
          < t1.cpp tee >(column -t > t3.3) >(cat -n > t3.4) >/dev/null
          paste -d'@' t3.3 t3.4
          $ echo {1..8} | sed 's/ /\n/' | xargs -n 2
          1 2
          3 4
          5 6
          7 8
          $ echo {1..8} | sed 's/ /\n/g' | xargs -L 2
          1 2
          3 4
          5 6
          7 8
          =============================================================
          screen usage:
          {Ctrl+a x} lock screen
          {Ctrl+a "} select window from list
          {Ctrl+a X} remove one region that is generated by {Ctrl+a S} or {Ctrl+a |}
          {Ctrl+a [} or {Ctrl+a Esc} enter copy mode,
          After enter copy mode, how to mark characters and copy them:
          1. copy one line, Y;
          2. copy one word, W;
          3. copy a range from specific pos in one line: <space> firstly, move cursor, <space> secondly;
          4. copy multiple lines: y, move cursor, <space>;
          {Ctrl+a ]} or {Esc} exit copy mode
          {Ctrl+a >} write paste buffer to file(/tmp/screen-exchange)
          {Ctrl+a <} read from file(/tmp/screen-exchange) into paste buffer
          {Ctrl+a ]} paste buffer into current cmdline

          ================================================================

          如何更改一個(gè)已經(jīng)運(yùn)行的程序的輸入輸出
          gdb attach 1323
          (gdb) call creat("/tmp/myprog.stdout",0600)
          $1 = 7
          (gdb) call dup2(7,1)
          $2 = 1
          (gdb) call creat("/tmp/myprog.stderr",0600)
          $3 = 8
          (gdb) call dup2(8,2)
          $4 = 2 

           ================
          useradd或usermod添加當(dāng)前用戶到某個(gè)group之后,通過id命令發(fā)現(xiàn)自身仍然不在那個(gè)group里,可以用如下命令:newgrp - new_group_name
          =============

          解決`locale -a`發(fā)現(xiàn)en_US.UTF-8缺失的問題:localedef -i en_US -f UTF-8 en_US.UTF-8
          =============

           

          所有man文件里搜索:
          man -wK FIFO
          man -wK --regex 'call.*main'

          posted on 2009-06-13 11:14 so true 閱讀(2104) 評(píng)論(0)  編輯  收藏 所屬分類: Linux

          主站蜘蛛池模板: 陈巴尔虎旗| 高密市| 若尔盖县| 久治县| 竹溪县| 广平县| 四子王旗| 温泉县| 长春市| 卫辉市| 沐川县| 福海县| 铜川市| 嘉义县| 澳门| 利川市| 花莲市| 磐安县| 兰考县| 桐柏县| 宜阳县| 介休市| 泊头市| 靖边县| 清远市| 徐水县| 昌吉市| 荥阳市| 鄂托克前旗| 宁陕县| 鄂尔多斯市| 措美县| 盐边县| 黄骅市| 涟水县| 荔浦县| 灌阳县| 雅江县| 安庆市| 芜湖县| 高邮市|