Language
Memo
Home > Memo > Linux常用指令

Home

Projects

Memo

Links

Contact







Linux常用指令:

擷取指定文字:grep


  這個指令可以從指定來源中幫你找出指定的文字,例如想在紀錄檔中找尋特定訊息時就可以派上用場:
[me@HPC ~]$ grep -i "error" ./install.log
# 這會在 install.log 裡面尋找 "error",並把整行列出來
install.log:5:3: error: ‘output’ undeclared (first use in this function)'
# 這裡的 -i 會讓他在執行時忽略大小寫的不同
# 另外,若想看看在找到的文字後 (After) 可以加上 -A 再配合一個數字即可
# 找前 (Before) 幾行的內容,則是使用 -B
# 如果想要同時搜尋搜尋不同的關鍵字,可以用 -e:
[me@HPC ~]$ grep -e "error" -e "warning" ./install.log
# 這會在 install.log 裡面尋找包含 "error" 或 "warning" 的行
配合 "|" 以及 xargs 後可說是相當好用!

管線命令(pipe)與參數代換(xargs)


  這兩個東西在想要進行比較複雜的操作時常常會用到(尤其是寫script的時候)。簡單來說呢,如果想要將原本會輸出到螢幕上的東西(stdout)全部當成輸入值(stdin)送入接在後面的指令中,那麼就是要用"|"這個所謂的管線命令來作,這邊用簡單的echo與cut指令來示範:
[me@HPC ~]$ echo "Hello World" # 什麼都不加,單純印出Hello World
Hello World
# 下面就是將本來會直接印出來的Hello World pipe給cut指令,並切出第三到第九個字元
[me@HPC ~]$ echo "Hello World" | cut --character=3-9
llo Wor
  而xargs的用法就更有趣了,可以先看一下這個例子:
[me@HPC ~]$ ls *.f90 # 假設這裡有以下這些檔案
main.f90 parameter.f90 sub-convert.f90 sub-sort.f90
[me@HPC ~]$ ls *.f90 | grep "sub" # 這樣用的話,他會從上面這些檔名中再撈出帶有sub字樣的結果
sub-convert.f90 sub-sort.f90
[me@HPC ~]$ echo "Hello World" | cut --character=3-9
llo Wor 可以將原本以空白或換行作為分隔的資料重新編排成以空白分隔的資料:

搜尋Linux下的無效symbolic link或空白檔案


  先用find -type l指定搜尋連結類型的檔案,再進一步用exec執行test -r指令,檢查那些連結的檔案是否存在並具有可讀之屬性,由於有加了!,所以會把出問題的連結print出來,如果沒加的話就會印出正常的連結。不過要注意因為test -r除了會檢查檔案是否存在之外,還會檢查他有沒有可以讀取的屬性,所以當權限不足時可能會出問題
  如果要搜尋空白檔案的話,只要將find指令的參數改為指定搜尋檔案類型的-type f,並把test的參數改成-s即可:
find 搜尋路徑 -type l ! -exec test -r {} \; -print
find 搜尋路徑 ! -exec test -s {} \; -print
# 搜尋無效連結
# 搜尋空白檔案

參考資料:鳥哥的Linux私房菜:利用 test 指令的測試功能


搜尋特定檔案中的特定字串


  一樣是先用find找出想找的檔案,然後用管線命令「|」將搜尋結果丟入xargs指令中轉換成輸入值餵給grep,讓它在這些檔案裡搜尋指定字串:
find 搜尋路徑 -type f -name "檔案名稱" | xargs grep "字串"
# 假設我要在src資料夾裡從一大堆的.f Fortran程式碼中找出叫做sst的變數,那麼就是:
find ./src -type f -name "*.f" | xargs grep "sst"
這樣就會列出"搜尋路徑"下所有符合"檔案名稱"的檔案,裡面包含"字串"的該行結果
如果沒有要特別搜尋哪種檔案的話,另一個更簡單的用法是:
grep -r "字串" *

參考資料:鳥哥的Linux私房菜:參數代換: xargs
     鳥哥的Linux私房菜:grep 的一些進階選項


背景執行程式 [nohup / GNU Screen]


  一般來說,在指令後面加上&之後即可去執行別的指令,若不想被輸出訊息打擾,可以把它輸出到一個紀錄檔裡面,這種用法一旦登出或是不小心斷線,之前的工作將會被結束掉,要避免這種情況可以用nohup這個指令:
nohup 欲執行之指令 &
# 範例
[root@HPC mm5] ./mm5.deck > LOG &
[root@HPC mm5] ./mm5.deck >& LOG &
# 以上這兩種方法一旦登出或斷線程式就會被終止
[root@HPC mm5] nohup ./mm5.deck &
# 如此斷線也沒關係,所有訊息將被寫入nohup.out
# 末尾的&是讓你能繼續下其他指令

# 輸出訊息紀錄於LOG,但錯誤訊息會顯示在螢幕上
# 所有的輸出訊息都會紀錄在LOG中



  若nohup失效,可以用「GNU Screen」來做背景執行的工作,範例如下:
[root@HPC mm5] screen
# 切換至GNU Screen
切換過去後,應該會看到PieTTY左上角的狀態改變了:GNU Screen
[root@HPC mm5] ./mm5.deck
(cd Run; make -i -r mmlif);
make[1]: Entering directory .....(略)
# 工作開始跑後,按下Ctrl+a接著按下d

[detached]
# 執行你的工作


# 註:按下Ctrl+a後畫面不會有任何改變


如此即可暫時離開GNU Screen,即使斷線工作還是會繼續,我們接著下後續的指令:
[root@HPC mm5]
[root@HPC mm5] screen
# 一樣Ctrl+a 按d暫時離開
[root@HPC mm5] screen -r
You may wish for a screen, what do you want?
21121.pts-4.HPC (Detached)
20943.pts-4.HPC (Detached)
[root@HPC mm5] screen -r 20943.pts-4.HPC

[root@HPC mm5] ./mm5.deck
(cd Run; make -i -r mmlif);
make[1]: Entering directory .....(略)

# 假設Screen裡的工作結束了
[root@HPC mm5] exit
[screen is terminating]
# 注意:現在不在Screen裡
# 若這不加任何參數,將會打開一個新的Screen

# 加-r可回到剛剛打開的screen裡
# 但是因為剛剛共開了兩個,所以他會問你要去哪個


# 指定要叫出來的screen

# 回到Screen裡會顯示當初離開前的畫面




# 這樣才有結束掉Screen

  在detach後,如果沒有用screen -r返回剛剛畫面而是直接執行screen的話,將會再開一個GNU Screen出來,所以要記得打[exit]來關閉GNU Screen,或者是在top裡面把他砍掉。不然很容易被忘記然後越開越多。

註:另外你也可以安裝byobu這個套件,這工具可以讓你在操作screen上更為順手

參考資料:GNU Screen User's Manual


壓縮/解壓縮檔案


  壓縮檔格式太多真的很令人頭痛...
格式壓縮指令解壓縮指令
*.bz2
*.gz / *.z
*.tar
*.tar.bz2
*.tar.gz
*.tgz
*.zip
bzip2 欲壓縮檔案之名稱
gzip 欲壓縮檔案之名稱
tar -cv 欲壓縮檔案之名稱 -f 欲建立之壓縮檔名.tar
tar -jcv 欲壓縮檔案之名稱 -f 欲建立之壓縮檔名.bz2
tar -zcv 欲壓縮檔案之名稱 -f 欲建立之壓縮檔名.gz
tar -zcv 欲壓縮檔案之名稱 -f 欲建立之壓縮檔名.tgz
zip 欲建立之壓縮檔名.zip 欲壓縮檔案之名稱
bzip2 -d 壓縮檔名
gzip -d 壓縮檔名
tar -xvf 壓縮檔名
tar -jxvf 壓縮檔名
tar -zxvf 壓縮檔名
tar -zxvf 壓縮檔名
unzip 壓縮檔名

註:使用bzip2以及gzip來壓縮(解壓縮)檔案時,原始檔案(.bz2/.gz壓縮檔)會消失,要避免這種情況:
bzip2 -k 欲壓縮/解壓縮之檔名
gzip -c 欲壓縮檔案之名稱 > 欲建立之壓縮檔名.gz
# k為keep之意

# gzip解壓縮時也可以用-c,但是要指定輸出到哪個檔案比較麻煩一點

參考資料:鳥哥的Linux私房菜:Linux 系統常見的壓縮指令


踢掉某個使用者

  有時候想找某人碴(好孩子請勿模仿),或者是離開機房後發現忘了把近端登入的帳號登出,這時候這個指令就可以派上用場了:
pkill -kill -t 該使用者的Terminal

# 例
[root@HPC ~] who
UserA pts/1 Sep 17 08:03 (192.168.55.66)
root pts/3 Sep 17 09:07 (127.0.0.1)
# 這裡的pts/1就是UserA的Terminal
[root@HPC ~] pkill -kill -t pts/1
註:遠端登入為pts/#,近端的則是tty#


廣播訊息

wall "想要廣播給所有使用者的訊息"
# 在 Ubuntu 上得用re-direction:
echo "想要廣播給所有使用者的訊息" | wall
# 也可以把訊息寫在一個檔案裡,然後:
wall < Mesg.txt


規格查詢

cat /proc/cpuinfo:CPU資訊
cat /proc/meminfo:目前的記憶體使用狀況
free -m:同樣也是查詢記憶體使用狀況
cat /proc/partitions:磁碟分割資訊
cat /proc/version:Linux Kernel完整資訊
uname -r:Linux Kernel版本
cat /etc/*-release:Linux版本
lsb_release -a:Linux版本

另外透過 dmidecode 這套件可以讓你查詢很多關於 BIOS 的資訊,例如下列指令可用來查詢 BIOS 版本:
sudo dmidecode -s "bios-version"
直接打 dmidecode -s 它會跟你說可用的選項有哪些,從這裡也可以看到這個工具最大的缺點就是需要root權限,有一個更好的替代方案就是直接讀取位在 /sys/devices/virtual/dmi/id/ 底下的檔案,這樣就有可能可以不需要root權限:
cat /sys/devices/virtual/dmi/id/bios_version

部份參考資料:
http://www.hkcode.com/linux-bsd-notes/466
StackOverflow - How can I find the hardware model in Linux?


利用rsync指令進行資料備份

  這個指令有幾個很強大的地方,首先,他可以保有原始檔案的擁有人(-o)、群組(-g)等特性,處理連結檔案時可以只複製連結(-l),還可以只更新最近的檔案(-u)大幅減少所需時間。這指令可以在本機上使用,也可以用來做異地備份,我都是靠這個指令來備份BBS資料的。
# 本地備份
rsync -av 欲備份之本地端資料夾 欲放置資料之位置

# 異地備份
rsync -av -e ssh 欲備份之本地端資料夾 帳號@欲存放備份資料之主機位置:欲存放備份資料之位置

參考資料:鳥哥的Linux私房菜:以 rsync 進行同步鏡像備份


輸入/輸出重新導向(I/O Redirection)

  其實這個東西很常用,搞不好你只是像我一樣不知道它的名字而已XD。有時要指定把顯示在螢幕上的輸出訊息寫入某個檔案時就會用上,沒錯,這個所謂的輸出輸入重新導向指的就是">"(輸出)或是"<"(輸入)符號:

# 把用cat秀出/etc/passwd的內容(stdout)輸出到LOG.txt裡
[root@HPC ~] cat /etc/passwd > LOG.txt

# 也可以讀入資料,下例利用"<"讀入Mesg.txt的內容並發送給所有使用者
[root@HPC ~] wall < Mesg.txt

# 輸入輸出可以同時使用
[root@HPC ~] 某指令 < 輸入 > 輸出

# 還可以指定錯誤訊息的輸出(stderr),如果不指定錯誤訊息的輸出的話,錯誤訊息將會顯示在螢幕上
# 同理,不將標準輸出(stdout)重新導向至某檔案的話那些訊息也會顯示在螢幕上
# 在下面這個簡單的例子中,date的輸出會被導入LOG中,而NoSuchCMD的錯誤訊息會被導入ERR中

[root@HPC ~] { date ; NoSuchCMD; }
一 9月 17 18:29:30 CST 2012
-bash: NoSuchCMD: command not found
[root@HPC ~] { date ; NoSuchCMD; } 1> LOG 2> ERR
# 1代表的是標準輸出,2為錯誤輸出,上例中的1可以不寫沒關係

# 此外也可以將stderr與stdout都輸入同一個檔案,只要將stderr指向到stdout即可
[root@HPC ~] { date ; NoSuchCMD; } > LOG 2>&1
# 這裡的2>&1就是將stderr指向stdout,加"&"符號是為了告知電腦是要導向至stdout,而不是1這個檔案
# 更簡化的寫法可以寫成下面這種

[root@HPC ~] { date ; NoSuchCMD; } &> LOG

# 重新導向時會覆蓋掉原有的檔案,若不希望這種情況發生可以用"">>"把資料附加在原本的檔案之後
[root@HPC ~] cat /etc/passwd >> LOG.txt

備註:在使用輸入輸出的重新導向時,如果目標檔案不存在將會自動產生。

參考資料:I/O Redirection
     Dorm 7 Softwarel:到底怎麼樣可以同時把std error, std out 記錄到檔案中呢?


讓程式輸出可以輸出到檔案同時印在螢幕上

  上面有解說了輸出輸入的重新導向,可是我希望輸出資料在寫入檔案時也能顯示在螢幕上呢?這時可以用tail這個指令把輸出檔的內容印出來:
[root@HPC ~] ./a.out > LOG &
[root@HPC ~] tail -f LOG

檢查某個指令是否有效

  需要判斷某個指令是否存在時可以用which來找,當有找到該指令時,which將會秀出其位置,反之則會告知使用者找不到。但是在有些電腦上可能沒有設定找不到時的回應,這樣在判斷式的判斷上可能會出問題,故建議用:

command -v 指令 >/dev/null 2>&1 && { 成功時的動作; } || { 失敗時的動作; }
type 指令 >/dev/null 2>&1 && { 成功時的動作; } || { 失敗時的動作; }
hash 指令 2>/dev/null && { 成功時的動作; } || { 失敗時的動作; }
# 將執行結果輸出到/dev/null裡面是為了讓他不要顯示在螢幕上
# 後面的2>&1這個I/O Redirection目的也是要把錯誤訊息丟進/dev/null裡面
# 而hash只要指定把stderr輸出到/dev/null是因為這個指令執行成功時不會有任何訊息
# 接著會例用&&與||的判斷式檢查執行結果,若為true則執行&&後面的東西,若否則執行||後面的東西

# 例:
[root@HPC ~] command -v pwd &> /dev/null && { echo "OK"; } || { echo "Not Exist"; }
OK
[root@HPC ~] command -v ker &> /dev/null && { echo "OK"; } || { echo "Not Exist"; }
Not Exist
# 這裡一定要注意大括號{}與指令一定要有空格,指令後面記得要加分號

  基本上這三種都可以用,但根據stackoverflow網站裡的Ihunath指出最保險的是command的這個用法,這主要是跟POSIX標準有關。

參考資料:stackoverflow: Check if a program exists from a bash script


查詢磁碟空間使用使用量

  查詢各磁區使用量:df -h,h這個參數是將計量單位以我們比較熟悉的MB/GB來表示
查詢某資料夾所占空間:du -sh 資料夾名稱

檢查 Ubuntu 系統是使用 systemd 還是 upstart 初始化系統

  Ubuntu 自15.04 (Vivid Vervet) 後由 upstart換用systemd了,但還是保留了upstart讓使用者能自由切換,如果想偵測系統目前到底是用哪種初始化系統,在Vivid上可以藉由檢查第一個執行緒來判斷檢查這台電腦到底是用哪一種:
$ ps 1
PIDTTYSTATTIMECOMMAND
1?Ss0:01/sbin/init splash # systemd on Vivid

以下是在Vivid上切換至upstart的結果:

$ ps 1
PIDTTYSTATTIMECOMMAND
1?Ss0:01/sbin/upstart # upstart on Vivid

而在Vivid之前的版本,預設是upstart:

$ ps 1
PIDTTYSTATTIMECOMMAND
1?Ss0:01/sbin/init # upstart on Precise

從這邊可以看出,如果單純只是想在 Vivid 上做判斷其實蠻簡單的,只要用 pidof upstart 這個指令就可以了,如果有回傳值的話那就是正在使用 upstart。但是如果要考慮不同的版本就要小心了,想依樣畫葫蘆用 pidof init 來判斷或是用 ps 1 檢查第一個執行緒時都會出問題!仔細看一下在 Vivid 下的 /sbin/init,會發現他其實被是指向 systemd:

# /sbin/init on Vivid (systemd)
$ ls -l /sbin/init
lrwxrwxrwx 1 root root 20 Apr 28 10:12 /sbin/init -> /lib/systemd/systemd*

但是在之前的版本中並不是這樣:

# /sbin/init on Precise (upstart)
$ ls -l /sbin/init
-rwxr-xr-x 1 root root 167192 1月 19 2013 /sbin/init*
但若由另一個方向出發,用 pidof systemd 指令來判斷是不是正在使用 systemd 倒是還蠻可靠的。

參考資料:Ubuntu Wiki: SystemdForUpstartUsers


查詢 Ubuntu 開機用 LiveUSB 版本

  如果手邊做了很多支 Ubuntu 的 LiveUSB,想知道裡面裝的到底是哪個版本的 image 除了實際用它來開機之外,另一個選項是把它掛載到任一台電腦上,然後檢查它的 .disk 隱藏資料夾,裡面會有一個叫做 info 的文字檔,版本資訊就在那裡面:

$ cat /media/myusb/.disk/info
Ubuntu 14.04.1 LTS "Trusty Tahr" - Release amd64 (20140722.2)


<-Memo

inserted by FC2 system