不管是 Mac 或是 Redhat, freebsd, debian ,這些 unix like 的系統,都有內建其本的 Linux 指令,如果你是 Windows 用戶,可以安裝 Cygwin ,這個軟體能夠在 Windows 上模擬 Linux 系統。
請先登入你的 unix like OS ,開始學習以下的指令吧。
路徑操作 pwd, ls, cd
command | description |
---|---|
pwd | print working directory 顯示當前目錄 |
ls | list files 顯示檔案列表 |
ls -l | 最出檔案列表明細 |
ls -lrt | 用 modify time 從小到大排序 |
ls -lrS | 用 file size 從小到大排序 |
cd | change directory 改變當前目錄 |
cd ~ | 回到個人目錄 |
cd - | 回到前一個目錄 |
試試輸入 pwd 然後按 enter ,系統會印出你當前的目錄,例如我的 Account 是 puritys ,平常一登入 Linux 系統,我的當前目錄會是在 /Users/puritys (Mac OS), /home/puritys (Linux)
ps 列出 process 列表
- ps aux
- ps auxw
- [www]$ ps aux |grep http
- USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
- root 5424 0.0 3.1 533380 32056 ? Ss 06:01 0:05 /usr/local/sbin/httpd
- daemon 5430 0.0 2.5 830840 26132 ? Sl 06:01 0:22 /usr/local/sbin/httpd
- daemon 5431 0.0 2.3 830840 24004 ? Sl 06:01 0:20 /usr/local/sbin/httpd
- daemon 5432 0.0 2.1 830840 22120 ? Sl 06:01 0:21 /usr/local/sbin/httpd
- daemon 5433 0.0 2.6 920684 26728 ? Sl 06:01 0:22 /usr/local/sbin/httpd
- daemon 5434 0.0 2.9 920684 29604 ? Sl 06:01 0:21 /usr/local/sbin/httpd
ps 印出來的每個欄位都有它的意義,USER 代表 process 使用的身分, PID 為 process id , CPU、 MEM 代表該 process 使用的比例,TIME 是執行多久, COMMAND 是 process 執行的指令 。
如何找出 CPU 使用量最大的 process.
- [www]$ ps aux | awk '{printf "%s %s\n",$3,$11}' | sort
- 0.0 sshd:
- 0.1 /usr/sbin/notifyd
- 0.1 /usr/sbin/ntpd
- 0.2 /System/Library/CoreServices/ZoomWindow.app/Contents/MacOS/ZoomWindowStarter
- 0.3 /Applications/Google
- 5.4 /Applications/Google
- 9.0 /Applications/Google
kill & killall
kill 是用來砍掉 process 用的,上面的 ps 範例中,有一個 id 5430 的 httpd process,如果我要中止這個 process ,就可以用 kill 5430.
- [www]$ kill 5430
- -bash: kill: (5430) - Operation not permitted
一般來說 Linux 系統的 process 是不能隨便中止的,首先要有 admin 的權限,再來要加上 -9 來強迫中止 Process ,看下面這個範例。
- [www]$ sudo kill -9 5430
- [www]$ ps aux |grep http
- root 5424 0.0 3.1 533380 32056 ? Ss 06:01 0:05 /usr/local/sbin/httpd
- daemon 5431 0.0 2.3 830840 24004 ? Sl 06:01 0:20 /usr/local/sbin/httpd
- daemon 5432 0.0 2.1 830840 22120 ? Sl 06:01 0:21 /usr/local/sbin/httpd
- daemon 5433 0.0 2.6 920684 26728 ? Sl 06:01 0:22 /usr/local/sbin/httpd
- daemon 5434 0.0 2.9 920684 29604 ? Sl 06:01 0:21 /usr/local/sbin/httpd
- //5430 的 process 成功被中止,而消失了
停掉相同的 process ,Apache server 一次會 fork 出多個 process ,可以用 killall 這個指令來一次刪除所有的 process。
- sudo killall -9 /usr/local/sbin/httpd
find
find 是 Linux 系統中很常被用到的指令,因為軟體工程師沒辦法記住每一個龐大系統中,每個檔案的路徑,使用 find 可以快速的幫我們找到每一個檔案
- find [path] -name *.cc
- [www]$ find . -name *.js
- ./hterm/js/hterm.js
- ./hterm/js/hterm_frame.js
- ./hterm/js/hterm_keyboard.js
- [www]$ find /etc/ -name *.conf
- /etc//AFP.conf
- /etc//apache2/extra/httpd-autoindex.conf
- /etc//apache2/extra/httpd-dav.conf
du
du 可以用來計算檔案大小,當系統的硬碟爆炸的時候就會用到它。
- [root]$ du -sh /etc/*
- 4.0K /etc/AFP.conf
- 0B /etc/afpovertcp.cfg
- 4.0K /etc/aliases
- 0B /etc/aliases.db
- 148K /etc/apache2
- 0B /etc/asl
計算資料夾大小的時候,可能會有一種需求,就是我不想要記算副檔案為 conf 的檔案,這時就可以用到 --exclude ( Mac OS 不支援這個功能) 。
- [root]$ du -sh --exclude *.conf /usr/local/*
- 47M /usr/local/bin
- 36K /usr/local/builder
- 808K /usr/local/sbin
- 404M /usr/local/share
cat, zcat
cat 印出檔案原始內容
cat xxx.txt
zcat 印出 gzip 檔的內容,這個指令會先將 tar.gz 解壓縮,然後印出內容。
zcat zzz.gz
tar 打包與解壓縮
tar -zxvf 解開 tar 檔
tar -zxvf xxx.tar.gz
tar -zcvf 將指定的檔案打包成 tar 壓縮檔
tar -zcvf aaa.tar.gz dir/
- -z 代表用 gzip 加解壓縮
- -x 解開 tar 檔
- -c 打包 tar 檔
zip 加解壓縮
gzip test (產生 test.gz)
gunzip test.gz (解開成 test)
tail
即時顯示檔案最新新增的行數
tail -f file
顯示檔案最後 5 行
tail -n 5 file
ctrl+r 搜尋曾經輸入過的指令
ctrl + r 是我超常使用的 Linux 指令,這個指令可以幫你搜尋你最近使用過的 command ,當你按了 ctrl + r ,會看到 reverse-i-search 的訊息,這時你只要輸入你想要搜尋的單母,系統就會在右邊出現 match 到的指令。
例如這個範例,我輸入 ta ,而我最近一次輸入有 ta 字眼的指令是 tail -f ... ,所以系統就會自動幫我找出來,按下 Enter 後,就可以執行這行指令。
- [root]$ (reverse-i-search)`ta': tail -f test
當系統已找到我最近使用的指令,這時我可能還想再找更久之前的指令,我們只要再按一次 ctrl+r ,系統就會自動再往前搜尋一次相關的指令。
grep 搜尋文字
grep 是一個很好用的過瀘與文字搜尋指令。
greg -Ri xxx *.txt
grep -l function *.cc
grep -o name *.txt
- -i case insensitive ,不區分英文字大小寫
- -o 印出符合的字串
- -R Recursive
- -l 印出符合字串的檔名
- [[:blank:]] grep 空白符號
- [[:digit:]] grep 數字
- [[:alpha:]] grep 英文字
- [www]$ echo "abc def" | grep 'abc'
- abc def
- [www]$ echo "abc def" | grep -o 'abc'
- abc
- [www]$ echo -e "Mars \nFeb \nMonk" | grep 'M'
- Mars
- Monk
- [www]$ echo -e "Mars \nFeb \nMonk" | grep 'M\|F'
- Mars
- Feb
- Monk
Awk
awk 是個好用的資料處理指令,一般表格式的資料非常適合用 awk , awk 預設會以空白將資料做分隔,字串會被分割成多個欄位 ,用 $1 代表第一個欄位 ,$2 代表第二個欄位。
首先我要建立一個空白分格的資料,使用簡單的指令 echo -e "a a a\nb b b" ,"\n" 這個符號代表分行,可以資料分成兩行。
再來我用 awk 印出每一行的第一個欄位
- [root]$ echo -e "Jackie 50\nMarry 90" |awk '{print $1}'
- Jackie
- Marry
用 awk 印出每一行的第二個欄位
- [root]$ echo -e "Jackie 50\nMarry 90" |awk '{print $2}'
- 50
- 90
Awk 除了印資料內容之外,也可以用來做資料的加總,範例如下。
- [root]$ echo -e "1 \n 2\n 3" |awk '{sum += $1} END {print sum}'
- 6
sed
sed 是一個文字 replace 的指令,可以讓我們用簡單的 regular express 取代字串,如果我想把文字裡的 "function " 改成 "public function" ,那麼我可以用 sed 's/string/replace to/g' 這個指令,若是我想要取代某個檔案裡的文字,就只要加上 "-i" 即可。
- [www]$ echo "function xxx()" | sed 's/function/public function/g'
- public function xxx()
- [www]$ sed -ri 's/function/public function/g' test.php
- // Mac
- [www]$ grep -l oauth *.php | awk "{printf \"sed 's/oauth/zauth/g' %s > tmp && mv tmp %s \n\", \$1, \$1}" |sh
time 計算程式執行時間
- [www]$ time tcsh -c "repeat 10 php test.php"
- real 0m2.785s
- user 0m0.659s
- sys 0m0.141s
合併常用的 Linux 指令
砍掉指定的 process,如果我想要砍掉 vim 跟 php 的所有 process ,那麼我可以用下面這個指令,先用 ps aux 加上 grep 找出 vim, php 的 process ,再用 awk 組出 kill 的指令,最後丟給 sh 處理。
- [www]$ ps aux |grep 'vim\|php'|grep -v grep | awk '{printf "sudo kill -9 %s\n",$2}' | sh
將 Apache access log 中的所有 IP, 轉成 hostname 。
- [www]$ tail -n 5 access | awk '{print $1}' | sort | uniq | awk '{printf "host %s\n", $1}' | sh
- 125.233.54.169.in-addr.arpa domain name pointer 7d.e9.36a9.ip4.static.sl-reverse.com.
- 78.244.54.169.in-addr.arpa domain name pointer 4e.f4.36a9.ip4.static.sl-reverse.com.
- 254.237.178.188.in-addr.arpa domain name pointer 188-178-237-254-static.dk.customer.tdc.net.
將目錄下的所有副檔名為 php 的檔案,副檔名改為 php5 。
- [www]$ ls *.php | sed 's/\.php//g' | xargs -t -n 1 -I% mv %.php %.php5
- mv aaa.php aaa.php5
如何將所有檔案裡的某一個 function 全部取代
假如我碰到一個問題 ,"LOG4CXX_DEBUG" 這個 function 會造成 RHEL4 環境 coredump ,所以我想要把這個 function 都註解掉,首先我用 grep -Rl LOG4CXX_DEBUG * |grep .cc$
找出所有使用 LOG4CXX_DEBUG 的 C/C++ 檔案。
找出所有的檔案後,再來 sed 來測試取代的語言, grep -Rl LOG4CXX_DEBUG * |grep .cc$ |xargs -t -n 1 cat | sed 's/LOG4CXX_DEBUG/\/\/LOG4CXX_DEBUG/'
,這個指令執行完成後,這時還不會真的修改檔案內容,而是將 replace 後的結果印出來,這樣我們可以先確認印出來的結果是否符何我們的預期。
確定沒問題後,使用 sed -i
,系統就會真的將檔案裡的內容取代。
- [www]$ grep -Rl LOG4CXX_DEBUG * |grep .cc$ |xargs -t -n 1 sed -i 's/LOG4CXX_DEBUG/\/\/LOG4CXX_DEBUG/'
- sed -i s/LOG4CXX_DEBUG/\/\/LOG4CXX_DEBUG/ client/gServer.cc
- sed -i s/LOG4CXX_DEBUG/\/\/LOG4CXX_DEBUG/ client/gServer2.cc
- sed -i s/LOG4CXX_DEBUG/\/\/LOG4CXX_DEBUG/ client/gClient.cc
- sed -i s/LOG4CXX_DEBUG/\/\/LOG4CXX_DEBUG/ client/gClient2.cc
最後再搜尋一次 LOG4CXX_DEBUG,確認所有的 LOG4CXX_DEBUG 都被註解了。
- [www]$ grep -R LOG4CXX_DEBUG *
- client/gServer.cc: //LOG4CXX_DEBUG(logger, " xx."<< endl);
- client/gServer.cc: //LOG4CXX_DEBUG(logger, "Cannot find "<< __FUNCTION__ << " Line " << __LINE__ << endl);
- client/gServer2.cc: //LOG4CXX_DEBUG(logger, "Call xxx "<< __FUNCTION__ << " Line " << __LINE__ << endl);
找出檔案裡的所有英文字
- [www]$ cat en |grep -o '[a-z]*' | sort | uniq
- said
- since
- single
- the
從 /usr/lib shared object 中掃出某個 function
- [www]$ nm -A -C /usr/lib/*.so |grep zero_nan
- /usr/lib/libm-2.17.so:00030090 r zero_nan
- /usr/lib/libm-2.17.so:00032800 r zero_nan
- /usr/lib/libm-2.17.so:00034e10 r zero_nan
作業
接下來有一些簡單的作業,看你是否可以完成它囉
- 移除副檔名 .log ,以及五天前建立的檔案。
- 計算檔案內的所有不重複英文單字。
- 計算檔案內的所有中文字數,重複的中文算兩個字。
- 計算所有 tar, gz, zip 等等的檔案 size 總合。
- 計算檔案的所有行數,但是不包含空白。
- 找出 CPU 最多的 process
- 將檔案內的 call(1, false, 'input') ,改成 apply([1, false, 'input']) 。
- 移除 PHP 檔案中有使用 error_log 的 function 。
- 使用 tar ,打包某個檔案,並將其檔案命名為 "年-月-日.tar.gz"
- 找出檔案內的所有 email 。
- 印出五天前(120 小時前)的 timestamp。
- 記算 httpd 這種 process 的記憶體使用量。