shell技巧





Shell作爲Unix系操作系統當中最有魅力且不可或缺的組件,經過數十載的洗禮不僅沒有被淘汰,而且愈加變得成熟穩健,究其原因,大概因爲它是個非常穩固的粘合劑,能夠把大量功能強大的組件任意配搭,總能很好很快地完成用戶的任務。


本文的一些命令很可能看起來是”雕蟲小技”,我們只好仰慕一下Shell大牛了,但是有些細節我會稍加發掘加以說明,遇到有趣的地方希望能博您一笑了。


1.以SUDO運行上條命令


    $ sudo !!


大家應該都知sudo,不解釋。但通常出現的情況是,敲完命令執行後報錯才發現忘了sudo。這時候,新手用戶就會:按上箭頭,按左箭頭,盯着光標回到開始處,輸入sudo,回車;高手用戶就蛋定多了,按Ctrl-p,按Ctrl-a,輸入sudo,回車。


這裏介紹這個是天外飛仙級別的,對,就直接sudo !!。


當然這幾種解決方式效果是完全一樣的,只是款不一樣,嗯,不解釋。


兩個感嘆號其實是bash的一個特性,稱爲事件引用符(event designators)。!!其實相當於!-1,引用前一條命令,當然也可以!-2,!-50。默認情況下bash會在~/.bash_history 文件內記錄用戶執行的最近500條命令,history命令可以顯示這些命令。


關於事件引用符的更多用法可以深入閱讀 The Definitive Guide to Bash Command Line History。


2.以HTTP方式共享當前文件夾的文件


    $ python -m SimpleHTTPServer


這命令啓動了Python的SimpleHTTPServer模塊,考慮到Python在絕大多數的Linux發行版當中都默認安裝,所以這個命令很可能是最簡單的跨平臺傳文件的方法。


命令執行後將在本機8000端口開放HTTP服務,在其他能訪問本機的機器的瀏覽器打開ttp://ip:8000即打開一個目錄列表,點擊即可下載。


3.在以普通用戶打開的VIM當中保存一個ROOT用戶文件


    :w !sudo tee %


這題目讀起來糾結,其實是很常見的,常常忘記了sudo就直接用vim編輯/etc內的文件,(不過也不一定,vim發現保存的文件無法保存時候會提示)等編輯好了,保存時候才發現沒權限。曲線方法是先保存個臨時文件,退出後再sudo cp回去。不過實際上在vim裏面可以直接完成這個過程的,命令就是如此。


查閱vim的文檔(輸入:help :w),會提到命令:w!{cmd},讓vim執行一個外部命令{cmd},然後把當前緩衝區的內容從stdin傳入。


tee是一個把stdin保存到文件的小工具。


而%,是vim當中一個只讀寄存器的名字,總保存着當前編輯文件的文件路徑。


所以執行這個命令,就相當於從vim外部修改了當前編輯的文件,好完工。


4.切換回上一個目錄


    $ cd -


應該不少人都知道這個,橫杆-代表上一個目錄的路徑。


實際上cd -就是cd $OLDPWD的簡寫,bash的固定變量$OLDPWD總保存着之前一個目錄的路徑。


相對地,$PWD總保存着當前目錄的路徑。這些變量在編寫shell腳本時候相當有用。


5.替換上一條命令中的一個短語


    $ ^foo^bar^


又是另外一個事件引用符(event designator),可以把上一條命令當中的foo替換成bar。


在需要重複運行調試一道長長的命令,需要測試某個參數時候,用這個命令會比較實用;但多數人會首先選擇按上箭頭提出上道命令,再移動光標去修改某參數,這樣更直觀,但效率上就不夠使用引用符高,而且在腳本中用這個方法可以簡化很多。


這道命令的原始樣式應該是這樣的:


    !!:s/foo/bar/


本文一開始介紹過!!,後面的一段大家應該很熟悉,vim、sed的替換操作都是這樣的語法。


關於事件引用符的更多用法可以深入閱讀The Definitive Guide to Bash Command Line History


6.快速備份一個文件


    $ cp filename{,.bak}


這道命令把filename文件拷貝成filename.bak,大家應該在一些比較複雜的安裝教程裏面見過這樣的用法。其原理就在於bash對大括號的展開操作,filename{,.bak}這一段會被展開成filename filename.bak再傳給cp,於是就有了備份的命令了。


大括號在bash裏面是一個排列的意義,可以試試這個:


    $ echo {a,b,c}{a,b,c}{a,b,c}


將輸出三個集合的全排列:


aaa aab aac aba abb abc aca acb acc
baa bab bac bba bbb bbc bca bcb bcc
caa cab cac cba cbb cbc cca ccb ccc


關於shell當中的集合操作,可深入閱讀”Set Operations in the Unix Shell”


7.免密碼SSH登錄主機


    $ ssh-copy-id remote-machine


這個命令把當前用戶的公鑰串寫入到遠程主機的~/.ssh/authorized_keys內,這樣下次使用ssh登錄的時候,遠程主機就直接根據這串密鑰完成身份校驗,不再詢問密碼了。前提是你當前用戶有生成了公鑰,默認是沒有的,先執行ssh-keygen試試吧!


這個命令如果用手工完成,是這樣的:


    your-machine$ scp ~/.ssh/identity.pub remote-machine:
    your-machine$ ssh remote-machine
    remote-machine$ cat identity.pub >> ~/.ssh/authorized_keys


如果你想刪掉遠程主機上的密鑰,直接打開authorized_keys,搜索你的用戶名,刪除那行,即可。


8.抓取LINUX桌面的視頻


    $ ffmpeg -f x11grab -s wxga -r 25 -i :0.0 -sameq /tmp/out.mpg


我們在一些視頻網站上看到別人的3D桌面怎麼怎麼酷的視頻,通常就是這麼來的,ffmpeg可以直接解碼X11的圖形,並轉換到相應輸出格式。


ffmpeg的通常用法是,根據一堆參數,輸出一個文件,輸出文件通常放最後,下面解析下幾個參數:


-f x11grab 指定輸入類型。因爲x11的緩衝區不是普通的視頻文件可以偵測格式,必須指定後ffmpeg才知道如何獲得輸入。


-s wxga 設置抓取區域的大小。wxga是1366*768的標準說法,也可以換成-s 800×600的寫法。


-r 25 設置幀率,即每秒抓取的畫面數。


-i :0.0 設置輸入源,本地X默認在0.0


-sameq 保持跟輸入流一樣的圖像質量,以用來後期處理。


至於其他ffmpeg的用法,可以參考下面兩篇文章:


   1. How to Extract Audio Tracks from YouTube Videos
   2. Converting YouTube Flash Videos to a Better Format with ffmpeg




1.用你最喜歡的編輯器來敲命令


    command <CTRL-x CTRL-e>


在已經敲完的命令後按 <CTRL-x CTRL-e> ,會打開一個你指定的編輯器(比如vim,通過環境變量$EDITOR指定),裏面就是你剛輸入的命令,然後愛怎麼編輯就怎麼編輯吧,特別是那些參數異常複雜的程序,比如mencoder/ffmpeg,一個命令動輒3、4行的,要修改其中的參數,這個方法最合適不過了,保存退出後自動執行這個程序。


實際上這是readline庫的功能,在默認情況下,bash使用的是emacs模式的命令行操作方式, <CTRL-x CTRL-e>是調用這個功能的一個綁定。如果你習慣使用vi模式,按 <ESC v> 可以實現同樣功能。


如果你喜歡別的編輯器,可以在~/.bashrc裏面放上比如export EDITOR=nano的命令。


另外一個修改命令的方法是使用fc命令(Fix Command),在編輯器裏面打開上一句命令。我們的第一輯連載提過一個^foo^bar^命令可以用fc來實現:fc -s foo=bar。


2.清空或創建一個文件


    > file.txt


>在shell裏面是標準輸出重定向符,即把(前部個命令的)命令行輸出轉往一個文件內,但這裏沒有”前部命令”,輸出爲空,於是就覆蓋(或創建)成一個空文件了。


有些腳本的寫法是:>file.txt,因爲:是bash默認存在的空函數。


單純創建文件也可以用$touch file.txt,touch本來是用作修改文件的時間戳,但如果文件不存在,就自動創建了。


3.用SSH創建端口轉發通道


    ssh -N -L2001:remotehost:80 user@somemachine


這個命令在本機打開了2001端口,對本機2001端口的請求通過somemachine作爲跳板,轉到remotehost的80端口上。


實現效果跟術語反向代理是相似的,實際上就是端口轉發,注意上面的描述涉及了3臺主機,但當然somemachine可以變成localhost。


這個命令比較抽象,但有時候是很有用的,比如因爲衆所周知的原因國內的IP的80端口無法使用,又或者公司的防火牆只給外網開了ssh端口,需要訪問內部服務器一個web應用,以及需要訪問某些限定了來源IP的服務,就可以用上這個方法了。


舉一個具體例子,運行:


    ssh -f -N -L 0.0.0.0:443:twitter.com:443 shell.cjb.net
    ssh -f -N -L 0.0.0.0:80:twitter.com:80 shell.cjb.net


然後在/etc/hosts裏面添加127.0.0.1 twitter.com,好吧剩下的你懂的。


當然通常做這個功能的反向代理,應該要用squid、nginx之類,ssh就算是輕量級的嘗試吧!


4.重置終端


    reset


如果你試過不小心cat了某個二進制文件,很可能整個終端就傻掉了,可能不會換行,沒法回顯,大堆亂碼之類的,這時候敲入reset回車,不管命令有沒有顯示,就能回覆正常了。


實際上reset命令只是輸出了一些特殊字符,我們看BusyBox裏面最簡單的reset程序的實現:


printf(“\033c\033(K\033[J\033[0m\033[?25h”);


輸出的這些字符對Shell是有特殊意義的:


    \033c: “ESC c” – 發送重置命令;


    \033(K: “ESC ( K” – 重載終端的字符映射;


    \033[J: “ESC [ J” – 清空終端內容;


    \033[0m: “ESC [ 0 m” – 初始化字符顯示屬性;


    \033[?25h: “ESC [ ? 25 h” – 讓光標可見;


其中字符顯示屬性經常用來設定打印字符的顏色等,可參考這個博文。


5.在午夜的時候執行某命令


    echo cmd | at midnight


說的就是at這個組件,通常跟cron相提並論,不過at主要用於定時一次性任務,而cron定時週期性任務。


at的參數比較人性化,跟英語語法一樣,可以tomorrow, next week之類的,詳細的查看手冊man at。


6.遠程傳送麥克風語音


    dd if=/dev/dsp | ssh username@host dd of=/dev/dsp


沒錯就是實現一個喊話器的功能。


/dev/dsp是Linux下聲卡的文件映射(Digital Signal Proccessor),從其中讀數據就是錄音,往裏面寫數據就是播放,相當簡單!


dd是常用的數據拷貝程序,如果不同時指定if、of,就直接使用stdin/stdout來傳輸。


如果你沒有遠程主機,可以試試這樣:


    dd if=/dev/dsp of=/dev/dsp


直接回放麥克風的聲音,只是有一點延時。


但是如果有別的程序正在使用聲卡,這個方法就不湊效了,因爲一般的聲卡都不允許多個音頻流同時處理,可以借用alsa組件的工具,arecord跟aplay:


    arecord | ssh username@host aplay


本地回放就是:


    arecord | aplay


如果你想嚇嚇別人:


    cat /dev/urandom | ssh username@host aplay


7.映射一個內存目錄


    mount -t tmpfs -o size=1024m tmpfs /mnt/ram


這個命令開了一塊1G內存來當目錄用。不過放心,如果裏面沒文件,是不會佔用內存的,用多少佔多少。


不過一般來說沒必要手動掛載,因爲多數發行版都會在fstab內預留了一個內存目錄,掛載在/dev/shm,直接使用即可;


最常見的用途是用內存空間來放Firefox的配置,可以讓慢吞吞的FF快很多,參見Shellex的博文:用tmpfs讓Firefox在內存中飛馳,以及後來的改進:用tmpfs讓Firefox在內存中飛馳II,其中提到的腳本來自speeding up firefox with tmpfs and automatic rsync。


那個破爛LinuxQQ也可以用這個方法,減少因爲大量磁盤IO導致的問題。


8.用DIFF對比遠程文件跟本地文件


    ssh user@host cat /path/to/remotefile | diff /path/to/localfile -


diff通常的用法是從參數讀入兩個文件,而命令裏面的-則是指從stdin讀入了。


善用ssh可以讓web開發減少很多繁瑣,還有比如sshfs,可以從編輯-上傳-編輯-上傳的人工循環裏面解脫出來。


9.查看系統中佔用端口的進程


    netstat -tulnp


Netstat是很常用的用來查看Linux網絡系統的工具之一,這個參數可以背下來:


-t: 顯示TCP鏈接信息


-u: 顯示UDP鏈接信息


-l: 顯示監聽狀態的端口


-n: 直接顯示ip,不做名稱轉換


-p: 顯示相應的進程PID以及名稱(要root權限)


如果要查看關於sockets更詳細佔用信息等,可以使用lsof工具。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章