1. 程式人生 > >生產力工具:shell 與 Bash 指令碼

生產力工具:shell 與 Bash 指令碼

生產力工具:shell 與 Bash 指令碼

作者:吳甜甜
個人部落格網站: wutiantian.github.io
注意:本文只是我個人總結的學習筆記,不適合0基礎人士觀看。


參考內容:

王頂老師 linux bash 視訊教程

http://billie66.github.io/TLCL/book

C語言程式設計網: http://c.biancheng.net/shell/

推薦書籍:《UNIX環境程式設計》,有內容,有遠離,課後習題也很棒。


目錄

  • 生產力工具:shell 與 Bash 指令碼
  • 我為什麼學 shell
    • 什麼是 shell 與 BASH
    • 學 shell 與 BASH 立竿見影的好處
  • 三步編寫執行一個 Shell 指令碼
  • 命令
    • 命令提示符與命令的概念簡述
    • 命令的詳細
  • linux系統基礎操作
    • linux思想:一切皆檔案
    • 探索作業系統狀態
    • linux檔案系統跳轉
    • 操作檔案和目錄
    • 文字處理
    • 停止
    • 許可權
    • 軟體安裝管理
    • 編譯程式make
  • shell眼中看世界——“展開”
    • 字元展開
    • 路徑名展開
    • 波浪線展開
    • 算術表示式展開
    • 花括號展開
    • 引數展開
    • 命令(展開)替換
    • 引用-控制展開
    • 引用-雙引號-限制部分展開
    • 引用-單引號-禁止展開
    • 轉義字元
  • IO 重定向
    • IO
    • 重定向
    • 管道操作符|提取資料
  • 正則表示式
    • 用“元字元”實現複雜匹配
    • 元字元和原義字元
    • grep
  • 專項專題(選看)
    • 顯示與查詢檔案
    • 歸檔 tar、解壓、批量
    • 記憶體與程序的效能
    • 儲存媒介-裝置掛載
    • 網路
  • 定製 shell
    • shell環境
    • 定製 shell 提示符$PS1
    • 別名alias-建立你自己的命令
  • 寫指令碼
    • 註釋第一行
    • 變數
    • 使用變數
    • 宣告陣列
    • 表示式
    • 數學運算
    • 流程控制-if
    • 流程控制-迴圈
    • 語句
    • 指令碼習題
  • 附錄:如何檢視 man 幫助手冊
  • 附錄:學習方法
  • 附錄:鳴謝

我為什麼學 shell

我首先接觸到 shell 是在深圳的一家fpga的方案公司參觀交流時,看到工程師對fpga進行程式設計時,敲幾個字元就插入了程式碼塊,感覺很快,是生產力的決勝武器。工程師告訴我,每個 fpga 公司都有自己的核心技術專利,編寫好的私有庫就是通過幾個字元的指令碼插入到程式中,每家都不同,模組不對外公開。

我意識到,成為具有核心價值的工程師必須掌握這項技能!

我本科時學的是電子資訊工程,對軟體的態度並沒有什麼都要會的意識,只是用到再學。但對於 shell ,它並不能迫在眉睫能解決什麼必須處理的問題,卻成為人與人差距的重要一環之一。

寫本內容時,是應用於影象機器學習中遇到實際問題寫的個人筆記。當我準備用手頭的《Linux程式設計》書時,很失望,看著塊頭挺大。內容可看的不多。網上的部落格大多數內容比較淺,實戰性不強。所以我自己寫給自己複習。

嵌入式的shell是精簡過的,語法略有不同,這點要注意。比如說陣列,部分命令的輸出和PC尚的存在一定差異。

什麼是 shell 與 BASH

  • shell:
    一說到命令列,我們真正指的是 shell。
    shell 就是一個程式,它接受從鍵盤輸入的命令, 然後把命令傳遞給作業系統去執行。

  • BASH
    “bash” 是 “Bourne Again SHell” 的首字母縮寫。
    bash 是由 Steve Bourne 的人寫成 shell 程式的增強版

因為基於“命令列”介面,而不是“圖形”介面,所以 shell 與 bash 的適應性更強,能應用在多種系統中,是“通殺”的技能。

學 shell 與 BASH 立竿見影的好處

常用功能例舉 功能簡述 優勢 功能
1 自動執行命令列 自動執行多組操作 新增一條命令列,每次輸入幾個字元(開啟bash)時都會自動執行
2 alias別名 簡化單組操作字元數

三步編寫執行一個 Shell 指令碼

步驟 內容 詳細
1 編寫一個指令碼。 shell 指令碼就是普通的文字檔案。所以我們需要一個文字編輯器來書寫它們。最好的文字 編輯器都會支援語法高亮,這樣我們就能夠看到一個指令碼關鍵字的彩色編碼檢視。語法高亮會幫助我們檢視某種常見 錯誤。為了編寫指令碼檔案,vim,gedit,kate,和許多其它編輯器都可以。
2 使指令碼檔案可執行。 系統會相當挑剔不允許任何舊的文字檔案被看作是一個程式,並且有充分的理由! 所以我們需要設定指令碼檔案的許可權來允許其可執行。
3 把指令碼放置到 shell 能夠找到當前目錄下。 當沒有指定可執行檔案明確的路徑名時,shell 會自動地搜尋某些目錄, 來查詢此可執行檔案。為了最大程度的方便,我們會把指令碼放到這些目錄當中。

命令

命令提示符與命令的概念簡述

  • 命令提示符:說明 shell已經準備好輸入了。

[當前使用者登入名@linux主機名 當前路徑]$

例如: [[email protected] ~]$
表示:當前使用者Teenie在主機名為wutiantian.github.io的當前路徑為家目錄

注意,後續的“定製 shell 環境”章節 有具體更改為自己心中環境的設定過程。

  • 命令列語法

command -options arguments
命令 一個或多個選項 一個或多個引數物件

以“空格”分隔,不管幾個空格都算一個空格。

例如: ls -l /usr

  • 如何選擇命令列發揮更大優勢
介面 優勢
圖形 簡單的任務更簡單
命令列 複雜的任務成為可能

命令的詳細

選項 options 分為 短選項和長選項,功能效果一樣。

options 舉例 優勢 描述
short -a 效率高 格式為'-'單橫槓。
短選項可合併。若'-'後不止一個字母則為合併選項。
例如:-a與-l合併為-al全部列出功能
long --all 更直觀 格式為'--'雙橫槓。
長選項沒有合併說法。
命令 四種形式
execute binary
可執行二進位制
就像我們所看到的位於目錄/usr/bin 中的檔案一樣 用諸如 C 和 C++語言寫成的程式編譯的二進位制檔案, 也可以是由諸如shell,perl,python,ruby等等指令碼語言寫成的程式
buildin bash
內嵌bash命令
bash 支援若干命令,內部叫做 shell 內部命令 (builtins) 例如,cd 命令,就是一個 shell 內部命令。
shell function 函式 這些是小規模的 shell 指令碼 它們混合到環境變數中。
alias 命令別名 定義自己的命令 建立在其它命令之上
命令 檢測命令的四種形式歸屬 舉例 舉例
type Indicate how a command name is interpreted
說明怎樣解釋一個命令名
type command
四種命令形式的哪一種
#type type
type is a shell builtin
#type ls
ls is aliased to `ls --color=auto'
#type cp
cp is /bin/cp
which To determine the exact location of a given executable, the which command is used:
顯示可執行程式的位置
which command
一個作業系統中,不只安裝了可執行程式的一個版本,為了確定所給定的執行程式的準確位置,使用 which 命令
這個命令只對可執行程式有效
#which cp
/bin/cp
#which cd
使用 shell 內建命令時,得不到迴應。
help 得到shell 內建命令的(簡要)幫助文件 command --help
help command
幫助檔案可能是中文也可能是英文
help cd
cd --help
man 詳細使用者幫助 man command man ls | less
apropos 基於某個關鍵字的搜尋匹配項,很粗糙但有時很有用 apropos command
等價於man -k
whatis The whatis program displays the name and a one line description of a man page matching a specified
顯示匹配特定關鍵字的手冊頁的名字和一行命令說明
whatis command whatis ls
ls(1)- list directory contents
info info 內容可通過 info 閱讀器 程式讀取。info 頁是超級連結形式的,和網頁很相似,退出就消失了痕跡。
info 檔案包含超級連結,它可以讓你從一個結點跳到另一個結點。一個超連結可通過 它開頭的星號來辨別出來,把游標放在它上面並按下 enter 鍵,就可以啟用它。
info command info ls

help cd

長說明

cd: cd [-L|[-P [-e]] [-@]] [dir]
    Change the shell working directory.
    
    Change the current directory to DIR.  The default DIR is the value of the
    HOME shell variable.
    
    The variable CDPATH defines the search path for the directory containing
    DIR.  Alternative directory names in CDPATH are separated by a colon (:).
    A null directory name is the same as the current directory.  If DIR begins
    with a slash (/), then CDPATH is not used.
    
    If the directory is not found, and the shell option `cdable_vars' is set,
    the word is assumed to be  a variable name.  If that variable has a value,
    its value is used for DIR.
    
    Options:
        -L  force symbolic links to be followed: resolve symbolic links in
        DIR after processing instances of `..'
        -P  use the physical directory structure without following symbolic
        links: resolve symbolic links in DIR before processing instances
        of `..'
        -e  if the -P option is supplied, and the current working directory
        cannot be determined successfully, exit with a non-zero status
        -@  on systems that support it, present a file with extended attributes
            as a directory containing the file attributes
    
    The default is to follow symbolic links, as if `-L' were specified.
    `..' is processed by removing the immediately previous pathname component
    back to a slash or the beginning of DIR.
    
    Exit Status:
    Returns 0 if the directory is changed, and if $PWD is set successfully when
    -P is used; non-zero otherwise.

cd --help

短說明

bash: cd: --: invalid option
cd: usage: cd [-L|[-P [-e]] [-@]] [dir]

apropos ls

匹配關鍵字
等價於man -k ls

SSL (3ssl)           - OpenSSL SSL/TLS library
_llseek (2)          - reposition read/write file offset
aconnect (1)         - ALSA sequencer connection manager
add-shell (8)        - add shells to the list of valid login shells
afInitChannels (3)   - initialize audio data format for a track in an audio f...
afOpenFile (3)       - open an audio file and create a file handle structure ...
afs_syscall (2)      - unimplemented system calls
afSetVirtualChannels (3) - set the virtual data format for a track in an audi...
afSetVirtualSampleFormat (3) - set the virtual data format for a track in an ...
alsabat (1)          - command-line sound tester for ALSA sound card driver
alsactl (1)          - advanced controls for ALSA soundcard driver
alsactl_init (7)     - alsa control management - initialization
alsaloop (1)         - command-line PCM loopback
alsamixer (1)        - soundcard mixer for ALSA soundcard driver, with ncurse...
amidi (1)            - read from and write to ALSA RawMIDI ports
amixer (1)           - command-line mixer for ALSA soundcard driver
aplay (1)            - command-line sound recorder and player for ALSA soundc...
...

linux系統基礎操作

linux思想:一切皆檔案

顏色屬性 淺藍 紅色閃爍
檔案型別 普通檔案 目錄 連結檔案 可執行檔案 壓縮檔案 連結有問題檔案 裝置檔案 其他檔案
解析例如:
檔案型別許可權 連節數 檔案擁有者  檔案所屬群組  檔案大小  檔案最後被修改時間  檔名
-rw-r--r--  1      Teenie       Teenie     3803     6月  24 21:43     .bashrc

檔案型別標記方法:
|首位|型別|舉例|檔案舉例|
|---|---|---|---|
|-|普通檔案|文字檔案、二進位制檔案|a.c , 1.txt , a.out , test1.sh ,bbbb.txt-hard看不出型別的文字硬連結|
|d|資料夾||cache/|
|l|符號連結檔案|後面會用->打印出它指向的檔案|ln -s src.c linker.c
linker.c就是src.c的一個符號連結檔案
lrwxrwxrwx 1 root root 3 .... linker.c -> src.c|
|s|socket檔案||
|p|管道檔案|||

檔案許可權 含義
r 可讀
w 可寫
x 可執行
- 空許可權,沒有許可權
不可執行Permission denied
檔案目錄結構 內容
bin 儲存二進位制可執行命令檔案(綠色)
root root超級使用者,即根使用者的主目錄
home 普通使用者的預設家目錄,每個普通使用者擁有一個以使用者名稱命名的資料夾
mnt 可移除裝置掛載點。例如:光碟機。共享資料夾目錄/mnt/ghfs/
media 可移除裝置
etc 配置檔案和目錄
/etc/crontab寫指令碼或定時執行一些任務,有定時設定。
/etc/fstab系統掛載的磁碟ID
/etc/passwd所有使用者的賬號密碼
proc 作業系統正在執行程序的檔案列表。可用“file 檔名”去檢視用途
lib 儲存各種程式所需要的共享庫檔案
opt optional可選的,第三方軟體可安裝至此
boot 存放ubuntu核心和系統啟動檔案
/boot/grub/grub.conf or menu.lst,被用來配置啟動載入程式。
/boot/vmlinuz,Linux 核心
var 用於存放很多不斷變化的檔案,例如日誌檔案等。
/var/log 目錄包含日誌檔案、各種系統活動的記錄。
這些檔案非常重要,並且 應該時時監測它們。
tmp 儲存系統和使用者的臨時資訊
user 包括與系統使用者直接有關的檔案和目錄
sbin 系統命令的儲存位置
  • linux檔案儲存

至少包括兩部分,(1)檔案資料本身(2)檔案原資料
原資料包括:檔案屬性(建立時間、修改時間、所有者、許可權、檔名)。
這些原資料鏈接到了資料塊本身,所以本身就是一個硬連結。
當硬連結數量比1少時,檔案就被刪除了。

型別 硬連結 軟連結
侷限性 不能指向到目錄
有 ln file link無ln directory link
檔案和連結檔案不能位於不同裝置
符號連結:連結、原檔案。刪除連結,原檔案不受影響。
刪除原檔案則連結檔案指向空,野指標,在作業系統有紅色顯示
外觀 硬連結在ls命令下是看不出區別的。 符號連結課看出符號指向
sbin->usr/sbin

探索作業系統狀態

date

顯示系統當前時間和日期
This command displays the current time and date.

2019年 06月 30日 星期日 18:21:15 CST

cal

顯示當前月份的日曆
A related command is cal which, by default, displays a calendar of the current month.

      六月 2019         
日 一 二 三 四 五 六  
                   1  
 2  3  4  5  6  7  8  
 9 10 11 12 13 14 15  
16 17 18 19 20 21 22  
23 24 25 26 27 28 29  
30              

exit

結束終端會話

We can end a terminal session by either closing the terminal emulator window, or by entering the exit command at the shell prompt:

file filename

確定檔案型別

file ~/.bashrc

/home/Teenie/.bashrc: ASCII text

linux檔案系統跳轉

命令 全英文 用法
pwd Print name of current working directory
打印出當前工作的絕對路徑
pwd 我是誰?我在哪?
ls List directory contents
列出目錄內容
ls
什麼都不跟,檢視當前目錄資料
ls /dev
檢視指定路徑下資料
cd Change directory
更改目錄
cd
什麼都不跟,回到家目錄
cd ~username
回到某使用者家目錄
cd -
切換到前一個操作目錄
cd Teenie/
切換到指定路徑下目錄

[[email protected] ~]$ pwd

/home/Teenie
普通使用者根目錄的工作目錄名:在home目錄下的該使用者名稱地址下。

ls

常用選項 長選項 作用 舉例
-a --all 列出目錄下的所有內容,包括隱藏的
-d --directory 該目錄本身的資訊(單)行 ls -ld /usr
drwxr-xr-x. 13 root root 155 6月 30 03:28 /usr
-F --classify 檔案或者目錄名字後加一個字元的分類標識 /目錄,例如opt/; @連結,例如 bin@
-h --human-readable 可讀模式 將容量4096轉為4.0k,
避免太大數字不能直觀看出多大
-l long長格式輸出
-r --reverse 反序,字母降序排列資料夾
-t --time 按修改日期排序

cd Teenie/

切換到當前路徑下的Teenie資料夾目錄路徑下
在幾乎所有的情況下,你可以省略”./”。它是隱含的。

To change your working directory (where we are standing in our tree-shaped maze) we use the cd command. To do this, type cd followed by the pathname of the desired working directory. A pathname is the route we take along the branches of the tree to get to the directory we want. Pathnames can be specified in one of two different ways; as absolute pathnames or as relative pathnames. Let’s deal with absolute pathnames first.
|路徑的兩種方式|特徵|
|---|---|
|相對路徑|用一對特殊符號來表示相對位置:符號 “.” 指的是工作目錄,”..” 指的是工作目錄的父目錄|
|絕對路徑|根目錄開頭的“/”開始,直到它的目的地|

cd ..

切換到上一級目錄

操作檔案和目錄

命令 含義 示例
mkdir make directory mkdir dir1
mkdir dir1 dir2 dir3
cp copy cp item1 item2 把單個檔案item1複製成item2
cp item... directory 複製多個item檔案/資料夾到directory資料夾
mv move 移動、重新命名檔案
rm remove -i互動諮詢;
-r遞迴;
-f,--force ;
-v,--verbose,explain what is being done。
rm file1
默默地刪除檔案
rm -i file1
除了在刪除檔案之前,提示使用者確認資訊之外,和上面的命令作用一樣。
rm -r file1 dir1
刪除檔案 file1, 目錄 dir1,及 dir1 中的內容。
rm -rf file1 dir1
除了如果檔案 file1,或目錄 dir1 不存在的話,rm 仍會繼續執行。
ln link ln file link建立硬連結;
ln bbb.txt bbb.txt-hard
ln -s item link建立符號連結
ln -s fun fun-sym

附:item 表示檔案或目錄

cp /etc/passwd .

將使用者賬戶密碼拷貝至當前目錄

cp -v /etc/passwd .

"/etc/passwd"->"./passwd"
顯示操作過程

cp -i /etc/passwd .

cp:是否覆蓋"./passwd"?

cp a passwd dir1

將a與passwd檔案,複製到dir1資料夾中

cp短選項 長選項 意義
-a --archive 複製檔案和目錄,以及它們的屬性,包括所有權和許可權。 通常,副本具有使用者所操作檔案的預設屬性。
-i --interactive 在重寫已存在檔案之前,提示使用者確認。如果這個選項不指定, cp 命令會預設重寫檔案。
-r --recursive 遞迴地複製目錄及目錄中的內容。當複製目錄時, 需要這個選項(或者-a 選項)。
-u --update 當把檔案從一個目錄複製到另一個目錄時,僅複製目標目錄中不存在的檔案,或者是檔案內容新於目標目錄中已經存在的檔案。
-v --verbose 顯示翔實的命令操作資訊
mv短選項 長選項 意義
-i --interactive 在重寫一個已經存在的檔案之前,提示使用者確認資訊。 如果不指定這個選項,mv 命令會預設重寫檔案內容。
-u --update 當把檔案從一個目錄移動另一個目錄時,只是移動不存在的檔案, 或者檔案內容新於目標目錄相對應檔案的內容。
-v --verbose 當操作 mv 命令時,顯示翔實的操作資訊。

文字處理

文字處理用處:文件、網頁、電子郵件、列印輸出、程式原始碼

  • 排序
排序命令 功能
cat 連線檔案並且列印到標準輸出
sort 給文字行排序,結果傳送到標準輸出
uniq 報告或者省略重複行
cat選項 功能
-A 列印文字文件中的非列印字元
-n number增加行號在文字中
-s 合併多餘空行。3個連續空行變為1個
非列印字元 名稱 顯示效果
enter 回車鍵 $
tab 製表鍵 ^I
space 空格

cat -A hello.c

列印 hello.c 文字文件中的非列印字元,讓人更明瞭程式排版

#include<stdio.h>$
int main(void)$
{$
    printf("hello world");$
    return 0;$
 } $

sort 程式對標準輸入的內容,或命令列中指定的一個或多個檔案進行排序,然後把排序 結果傳送到標準輸出。

使用與 cat 命令相同的技巧,我們能夠演示如何用 sort 程式來處理標準輸入

sort >foo.txt 
c
a
b

Ctrl-d 組合鍵來表示檔案的結尾

cat foo.txt 
a
b
c
看到文字行有序地顯示

sort 程式能接受命令列中的多個檔案作為引數,所以有可能把多個檔案合併成一個有序的檔案。

例如, 如果我們有三個文字檔案,想要把它們合併為一個有序的檔案。

sort file1.txt file2.txt file3.txt > final_sorted_list.txt

sort 程式選項 長選項 功能
-b --ignore-leading-blanks 預設情況下,對整行進行排序,從每行的第一個字元開始。這個選項導致 sort 程式忽略 每行開頭的空格,從第一個非空白字元開始排序。
-f --ignore-case 讓排序不區分大小寫。
-n --numeric-sort 基於字串的數值來排序。使用此選項允許根據數字值執行排序,而不是字母值。
-r --reverse 按相反順序排序。結果按照降序排列,而不是升序。
-k --key=field1[,field2]
偏量
根據欄位排序
-m --merge 把每個引數看作是一個預先排好序的檔案。把多個檔案合併成一個排好序的檔案,而沒有執行額外的排序。
-o --output=file 把排好序的輸出結果傳送到檔案,而不是標準輸出。
-t --field-separator=char 定義域分隔字元。預設情況下,域由空格或製表符分隔。

du -s /usr/share/* |sort -nr |head

檢視磁碟中目錄,哪個資料夾佔用磁碟空間大,數字逆序排列前十個

245984  /usr/share/fonts
122532  /usr/share/icons
114424  /usr/share/doc
89328   /usr/share/help
82640   /usr/share/libreoffice
60556   /usr/share/pyzy
55588   /usr/share/app-install
42228   /usr/share/mythes
41496   /usr/share/fcitx-sogoupinyin
39692   /usr/share/man
uniq 選項 功能
-c 輸出所有的重複行,並且每行開頭顯示重複的次數。
-d 只輸出重複行,而不是特有的文字行。
-f n 忽略每行開頭的 n 個欄位,欄位之間由空格分隔,正如 sort 程式中的空格分隔符;然而, 不同於 sort 程式,uniq 沒有選項來設定備用的欄位分隔符。
-i 在比較文字行的時候忽略大小寫。
-s n 跳過(忽略)每行開頭的 n 個字元。
-u 只輸出獨有的文字行。這是預設的。
  • 切片
命令 功能 例子
cut 裁剪,從檔案裡取東西 cut -f 2,2 linux-by-date.txt >linux-vernums.txt
paste 合併檔案文字行
通過讀取多個檔案,然後把每個檔案中的欄位整合成單個文字流,輸入到標準輸出。
paste linux-dates.txt linux-names.txt >linux-key-names.txt
join 往檔案里加東西 join linux-key-names.txt linux-key-vernums.txt
  • 比較
檢視差異命令 功能 例子
comm 逐行比較兩個有序的檔案
compare
diff 逐行比較檔案或目錄
different
如何把檔案1程式設計檔案2
patch 把更改應用到原始文件中去 diff -Naur old_file new_file >patchfile.txt
patch < patchfile.txt


diff三種模式 模式內容 示例
normal 描述要求更改的位置和型別
context 上下文模式。資訊有冗餘 -刪除行
+增加行
!更改行
unin 統一模式 空格:兩個檔案都包含這一行
-:在第一個檔案中刪除這一行
+:新增這一行到第一個檔案中
cat file1.txt
a
b
c
d

cat file2.txt
b
c
d
e

comm file1.txt file2.txt
a
            b
            c
            d
    e
1特  2特  共有

comm -12 file1.txt file2.txt
b
c
d
隱藏12列

diff file1.txt file2.txt           
1d0     如何把file1改成file2.txt?
< a     刪除d第一行的a
4a4     把第2個檔案的第4行
> e     加上e

diff -c file1.txt file2.txt
context模式
*** file1.txt
--- file2.txt
*************
*** 1,4 *****
-a
 b
 c
 d
--- 1,4 -----
 b
 c
 d
+e

diff -u file1.txt file2.txt
unin 統一模式
---file1.txt
+++file2.txt
@@-1,4,+1,4@@
-a
 b
 c
 d
+e
  • 執行時編輯

The tr program is used to transliterate characters.

tr 程式被用來更改字元。我們可以把它看作是一種基於字元的查詢和替換操作。

命令 功能 例子
tr search/replace查詢與替換 tr char_set1 char_set2
在第一個字符集裡查詢,替換成第2個字符集內容
charset三種模式 內容
list列舉 abcdefghijklmnop
field域 a-z or A-Z or 0-9
POSIX [:lower:][:upper:]

停止

停止的快捷鍵 功能 例子
ctrl+z 將任務中止(暫停的意思),但是此任務並沒有結束。
他仍然在程序中他只是維持掛起的狀態,
使用者可以使用fg/bg操作繼續前臺或後臺的任務,
fg命令重新啟動前臺被中斷的任務,
bg命令把被中斷的任務放在後臺執行.
當你vi一個檔案是,如果需要用shell執行別的操作,
但是你又不打算關閉vi,
因為你得存檔退出,
你可以簡單的按下ctrl+z,
shell會將vi程序掛起,
當你結束了那個shell操作之後,
你可以用fg命令繼續vi你的檔案。
ctrl+c 強制中斷程式的執行,程序已經終止。
ctrl+d 不是傳送訊號,而是表示一個特殊的二進位制值,表示 EOF。
在shell中,ctrl-d表示退出當前shell

許可權

Linux 系統有多使用者效能。

為了使多使用者特性付諸實踐,那麼必須發明一種方法來阻止使用者彼此之間受到影響。

畢竟,一個使用者的行為不能導致計算機崩潰,也不能亂動屬於另一個使用者的檔案。

命令 詳解 示例
id Display user identity
顯示當前使用者身份號
#id
chmod Change a file’s mode
更改已經存在的檔案模式
支援兩種不同的方法來改變檔案模式:八進位制數字表示法或 符號表示法。
umask Set the default file permissions
設定預設的新建立檔案許可權
umask 0002
預設許可權減2
chown Change a file’s owner
更改檔案所有者
chgrp Change a file’s group ownership
更改檔案組所有權
su Run a shell as another user
以另一個使用者的身份來執行 shell
sudo Execute a command as another user
以另一個使用者的身份來執行命令
passwd Change a user’s password
更改使用者密碼
passwd [user]

在 Unix 術語中,每個人 是指整個世界。可以用 id 命令,來找到關於你自己身份的資訊

id
uid=1000(teenie) gid=1000(teenie) groups=1000(teenie),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)

id組的字元 含義
u g o a
owner
user
group other all=user+group+other

uid 從1000開始變號

屬性 檔案(直觀) 目錄(不直觀,需記憶)
r 允許開啟並讀取檔案內容 允許列出目錄中的內容,
前提是目錄必須設定了可執行屬性(x)
w 允許寫入檔案內容或截斷檔案。
但不允許對檔案進行重新命名或刪除,
重新命名或刪除是由目錄的屬性決定的
允許在目錄下新建、刪除或重新命名檔案,
前提是目錄必須設定了可執行屬性(x)
x 允許將檔案作為程式來執行,使用指令碼語言編寫的程式必須設定為可讀才能被執行 允許進入目錄,例如:cd directory

許可權的基礎組合值
|Octal|Binary|File Mode|
|---|---|---|---|
|1|001|--x|execute|
|2|010|-w-|write|
|4|100|r--|read|
八進位制有8種組合,對以上三種進行組合相加賦值即可。

  • 對於指令碼檔案,有兩個常見的許可權設定
指令碼許可權值 功能
755 每個人都能執行
700 只有檔案所有者能夠執行

注意:為了能夠執行指令碼檔案,指令碼必須是可讀的。

chmod

chmod gu=rw foo.txt
組許可權賦值

chmod o-x foo.txt
減去other組的x可執行功能

chmod 755 foo.txt
把檔案的許可權設為755

軟體安裝管理

軟體包管理工具:系統中,一種安裝和維護軟體的方法

如果我們花些時間在 Linux 社群裡,我們會看到很多像Linux發行版中哪一個是“最佳”之類的觀點。 這些討論通常非常可笑,集中在一些像桌面背景的漂亮程度(一些人不使用 Ubuntu, 只是因為 Ubuntu 預設主題顏色是棕色的!)和其它的瑣碎東西上。

Linux 發行版本質量最重要的決定因素是軟體包管理系統和其支援社群的永續性。隨著我們 花更多的時間在 Linux 上,我們會發現它的變化是非常快的。大多數一線 Linux 發行版每隔六個月釋出一個新版本,並且許多獨立的程式每天都會更新。為了能和這些 如暴風雪一般多的軟體保持聯絡,我們需要一些好工具來進行軟體包管理。

選擇 linux 發行版的重要指標:軟體包管理

該發行版是否有
1.好用的軟體包管理系統
2.豐富的軟體包使用
3.持久的社群維護更新

對於早期 linux 使用者,人們需下載和編譯原始碼來安裝軟體。
如果有預先編譯好的軟體包,使用起來相對容易和快速一些

擁有對軟體原始碼的訪問許可權是linux的偉大之處,它賦予每個人定製和優化系統權利。

包管理兩大陣營 發行版(部分列表) 包管理底層工具 包管理上層工具
.deb Debian , Ubuntu dpkg apt-get, aptitude
.rpm Fedora , CentOS , Red Hat , OpenSUSE rpm rpm

以 ubuntu16為例:

  • 查詢安裝

命令 子命令 包名
apt install git

apt 命令首先分析 git 依賴關係,這就是包管理的好處.
如果程式發現缺少了一個依賴,則會報錯並退出。

Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages were automatically installed and are no longer required:
  libllvm5.0 snapd-login-service
Use 'apt autoremove' to remove them.
Suggested packages:
  git-daemon-run | git-daemon-sysvinit git-doc git-el git-email
  git-gui gitk gitweb git-arch git-cvs git-mediawiki git-svn
The following NEW packages will be installed:
  git
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 3,176 kB of archives.
After this operation, 24.1 MB of additional disk space will be used.
Get:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu xenial-updates/main amd64 git amd64 1:2.7.4-0ubuntu1.6 [3,176 kB]
Fetched 3,176 kB in 3s (878 kB/s)
Selecting previously unselected package git.
(Reading database ... 241828 files and directories currently installed.)
Preparing to unpack .../git_1%3a2.7.4-0ubuntu1.6_amd64.deb ...
Unpacking git (1:2.7.4-0ubuntu1.6) ...
Setting up git (1:2.7.4-0ubuntu1.6) ...
  • 解除安裝

命令 子命令 包名
apt remove git
y

Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages were automatically installed and are no longer required:
  liberror-perl libllvm5.0 snapd-login-service
Use 'apt autoremove' to remove them.
The following packages will be REMOVED:
  git git-core
0 upgraded, 0 newly installed, 2 to remove and 0 not upgraded.
After this operation, 24.1 MB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database ... 242467 files and directories currently installed.)
Removing git-core (1:2.7.4-0ubuntu1.6) ...
Removing git (1:2.7.4-0ubuntu1.6) ...
  • 更新

apt update 更新源

更新已安裝的包
命令 子命令 包名
apt upgrade git

Reading package lists... Done
Building dependency tree       
Reading state information... Done
git is already the newest version (1:2.7.4-0ubuntu1.6).
Calculating upgrade... Done
The following packages were automatically installed and are no longer required:
  libllvm5.0 snapd-login-service
Use 'apt autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
  • 顯示包資訊

知道包名後,要顯示軟體包的詳細資訊,例如:版本號、大小、校驗值和軟體描述等資訊時。

apt-cache show firefox

Package: firefox
Architecture: amd64
Version: 67.0.4+build1-0ubuntu0.16.04.1
Priority: optional
Section: web
Origin: Ubuntu
...

列出所有已經安裝的軟體包
apt list --installed

Listing... Done
a11y-profile-manager-indicator/xenial,xenial,xenial,now 0.1.10-0ubuntu3 amd64 [installed]
account-plugin-facebook/xenial,xenial,xenial,xenial,xenial,xenial,now 0.12+16.04.20160126-0ubuntu1 all [installed]
...
firefox/xenial-updates,xenial-security,xenial-updates,xenial-security,xenial-security,xenial-updates,now 67.0.4+build1-0ubuntu0.16.04.1 amd64 [installed]
...

PS:aptitude與 apt-get 一樣,是 Debian 及其衍生系統中功能極其強大的包管理工具。

與 apt-get 不同的是,aptitude在處理依賴問題上更佳一些。

編譯程式make

編譯就是把原始碼(一個由程式設計師編寫的人類可讀的程式的說明)翻譯成計算機處理器的語言的過程。

ubuntu16 下,編譯一個叫做 diction 的程式,來自 GNU 專案。步驟:

(1)安裝編譯器

sudo apt install ftp gcc

安裝 ftp 與 gcc 兩個檔案。

(2)獲取原始碼

ftp ftp.gnu.org

Connected to ftp.gnu.org.
220 GNU FTP server ready.

Name (ftp.gnu.org:root): anonymous


230-NOTICE (Updated October 13 2017):
...
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.


ftp> ls

200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
...
-rw-r--r--    1 0        0            2925 Apr 04 20:15 README
-rw-r--r--    1 0        0          405121 Oct 23  2003 before-2003-08-01.md5sums.asc
-rw-rw-r--    1 0        3003       262986 Jul 05 09:50 find.txt.gz
drwxrwxr-x  320 0        3003        12288 Jun 17 21:54 gnu
drwxrwxr-x    3 0        3003         4096 Mar 10  2011 gnu+linux-distros
-rw-rw-r--    1 0        3003       483088 Jul 05 09:50 ls-lrRt.txt.gz
drwxr-xr-x    3 0        0            4096 Apr 20  2005 mirrors
lrwxrwxrwx    1 0        0              11 Apr 15  2004 non-gnu -> gnu/non-gnu
...
226 Directory send OK.


ftp> cd gnu/dicition

550 Failed to change directory.



ftp> cd gnu/diction

250 Directory successfully changed.


ftp> ls

200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r--    1 3003     65534       68940 Aug 28  1998 diction-0.7.tar.gz
-rw-r--r--    1 3003     65534       90957 Mar 04  2002 diction-1.02.tar.gz
-rw-r--r--    1 3003     65534      141062 Sep 17  2007 diction-1.11.tar.gz
-rw-r--r--    1 3003     65534         189 Sep 17  2007 diction-1.11.tar.gz.sig
226 Directory send OK.


ftp> get diction-1.11.tar.gz

local: diction-1.11.tar.gz remote: diction-1.11.tar.gz
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for diction-1.11.tar.gz (141062 bytes).
226 Transfer complete.
141062 bytes received in 1.99 secs (69.1985 kB/s)


ftp> bye

221 Goodbye.
此時根目錄下多了個壓縮包
diction-1.11.tar.gz

解壓縮檔案

tar xzf diction-1.11.tar.gz

(3)檢視程式碼

.c與.h檔案

(4)編譯預處理

執行 configure 預處理檔案=>產生 makefile指令碼檔案

./configure

(5)編譯程式

make

執行命令 make 會直接找 makefile=>建立很多 .o 檔案

(6)安裝程式

sudo make install

(7)檢視程式是否安裝好

which diction
/usr/local/bin/diction

編譯原因 內容
可用性 有些發行版不包含所有程式
即時性 獲得最新版本程式

shell眼中看世界——“展開”

當按下 enter 鍵後,發生在命令列中的一些“魔法”,這種魔法就是展開的過程。

字元展開

echo *

打印出當前目錄下的所有資料夾名,不會顯示隱藏檔案。

當回車鍵被按下時,shell 在命令被執行前在命令列上自動展開任何符合條件的字元, 所以 echo 命令的實際引數並不是”*“,而是它展開後的結果。

路徑名展開

echo /usr/*/share

/usr/kerberos/share  /usr/local/share

萬用字元所依賴的工作機制叫做路徑名展開。

波浪線展開

波浪線字元(“~”)有特殊的含義。

[[email protected] ~]$ echo ~teenie
/home/teenie

當它用在 一個單詞的開頭時,它會展開成指定使用者的家目錄名,如果沒有指定使用者名稱,則展開成當前使用者的家目錄

算術表示式展開

shell 在展開中執行算數表示式。當作計算器來使用。

算術表示式展開使用這種格式:

$((expression))

表示式是指算術表示式,它由數值和算術操作符組成。
注意:美元符號不能丟掉!
例如

echo $((2+2))
4

算術表示式只支援整數(全部是數字,不帶小數點),但是能執行很多不同的操作。

操作符 說明
+
-
*
/ 除(但是記住,因為展開只是支援整數除法,所以結果是整數。)
% 取餘,只是簡單的意味著,“餘數”
** 取冪

在算術表示式中空格並不重要,並且表示式可以巢狀。例如,5的平方乘以3:
注意:巢狀的$與括號切不可少!否則報錯!!!

echo $(($((5**2))*3))
75

echo with $((5%2)) left over.
with 1 left over.

花括號展開

這種模式不能 嵌入空白字元。
花括號展開可以巢狀。

花括號的模式中 建立多個文字字串。  
echo Front-{A,B,C}-Back
Front-A-Back Front-B-Back Front-C-Back

echo Number_{1..5}
Number_1 Number_2 Number_3 Number_4 Number_5
使用了一個整數區間

echo {Z..A}
Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
倒序排列的字母區間

echo a{A{1,2},B{3,4}}b
aA1b aA2b aB3b aB4b
花括號展開可以巢狀

引數展開

引數展開特性在 shell 指令碼中比直接在命令列中更有用。

儲存小塊資料,並給每塊資料命名的能力有關係。許多像這樣的小塊資料, 更恰當的稱呼應該是變數,可供你方便地檢查它們。

"USER"的變數包含你的使用者名稱。可以這樣做來呼叫引數,並檢視 USER 中的內容

echo $USER
teenie

檢視有效的變數列表
printenv |less

其它展開型別中,如果你誤輸入一個字元,展開就不會發生。

這時 echo 命令只簡單地顯示誤鍵入的模式。

但在引數展開中,如果你拼寫錯了一個變數名, 展開仍然會進行,只是展開的結果是一個空字串。

命令(展開)替換

命令替換允許我們把一個命令的輸出作為一個展開模式來使用

ls -l $(which cp)
-rwxr-xr-x 1 root root 151024 3月   3  2017 /bin/cp
把 which cp 的執行結果作為一個引數傳遞給 ls 命令,因此可以在不知道 cp 命令 完整路徑名的情況下得到它的檔案屬性列表。

file $(ls /usr/bin/* | grep zip)
/usr/bin/funzip:     ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=06412c648a6927c4a14c751fe2412db3425ecd0f, stripped
/usr/bin/gpg-zip:    POSIX shell script, ASCII text executable
...
管道線的輸出結果成為 file 命令的引數列表

引用-控制展開

shell 提供了一種叫做引用的機制,來有選擇地禁止不需要的展開。

echo this is a    test
this is a test
shell 利用單詞分割刪除掉 echo 命令的引數列表中多餘的空格

echo The total is $100.00
The total is nu00.00

echo The total is $00.00
The total is bash0.00

echo The total is$100.00
The total isnu00.00

因為 1 是沒有定義的變數,引數展開把 $1 的值替換為 nu

echo the winner is $smith
the winner is

引用-雙引號-限制部分展開

把文字放在雙引號中, shell 使用的特殊字元,都失去它們的特殊含義,被當作普通字元來看待。

有幾個例外: $, (反斜槓),和 `(倒引號)。

這意味著單詞分割、路徑名展開、 波浪線展開和花括號展開都將失效,然而引數展開、算術展開和命令替換 仍然執行。

使用雙引號,我們可以處理包含空格的檔名。

比方說我們是不幸的 名為 two words.txt 檔案的受害者。
如果我們試圖在命令列中使用這個 檔案,單詞分割機制會導致這個檔名被看作兩個獨自的引數,而不是所期望 的單個引數:
ls -l two words.txt
ls: cannot access two: No such file or directory
ls: cannot access words.txt: No such file or directory

使用雙引號,我們可以阻止單詞分割,得到期望的結果;
進一步,我們甚至可以修復 破損的檔名。

ls -l "two words.txt"
-rw-rw-r-- 1 me   me   18 2008-02-20 13:03 two words.txt
 mv "two words.txt" two_words.txt

記住,在雙引號中,引數展開、算術表示式展開和命令替換仍然有效:

echo "$USER$((2+2))"
teenie4

單詞分割機制會在單詞中尋找空格,製表符,和換行符,並把它們看作 單詞之間的界定符。

這意味著無引用的空格,製表符和換行符都不是文字的一部分, 它們只作為分隔符使用。

echo "this is a    test"
this is a    test

單詞分割被禁止,內嵌的空格也不會被當作界定符,它們成為引數的一部分。

一旦加上雙引號,我們的命令列就包含一個帶有一個引數的命令。

單詞分割機制把換行符看作界定符,對命令替換產生了一個雖然微妙但有趣的影響
echo $(cal)
六月 2019 日 一 二 三 四 五 六 1 2  3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

echo "$(cal)"
      六月 2019         
日  一 二 三 四  五 六  
                   1      
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29           
30                    
命令列只有一個引數,引數中包括嵌入的空格和換行符。

引用-單引號-禁止展開

如果需要禁止所有的展開,我們要使用單引號。以下例子是無引用,雙引號,和單引號的比較結果

echo text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
text /home/teenie/*.txt a b foo 4 teenie

echo "text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER"
text ~/*.txt {a,b} foo 4 teenie

echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER'
text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER

轉義字元

如果沒有準確地理解展開模式,shell 總是神祕和混亂的源泉,並且 shell 潛在的能力也 浪費掉了。

只想引用單個字元。
在字元之前加上一個反斜槓,叫做轉義字元。
經常在雙引號中使用轉義字元,來有選擇地阻止展開。

使用轉義字元來消除檔名中一個字元的特殊含義,是很普遍的。
這些字元包括”$”, “!”, “ “等字元。

echo "The balance for user $USER is: \$5.00"
The balance for user teenie is: $5.00
防止美元符號展開

IO 重定向

IO

”I/O”代表輸入/輸出。標準的輸入為鍵盤,標準的輸出為螢幕,而不是儲存到磁碟檔案。

檔案描述符 標準 檔名
0 標準輸入 stdin
1 標準輸出的特殊檔案 stdout
2 標準錯誤的檔案 stderr
型別輸出
程式執行結果,程式要完成的功能
得到狀態和錯誤資訊, 這些告訴我們程式進展

通過工具,你可以重定向命令的輸入輸出,命令的輸入來自檔案,而輸出也存到檔案。

重定向

重定向符號 含義 示例
> 覆蓋內容 清空一個已存在檔案的內容或是建立一個新的空檔案。
>> 追加內容 不會沖掉以前內容

標準錯誤重定向沒有專用的重定向操作符。為了重定向標準錯誤,我們必須參考其檔案描述符。
|將錯誤資訊輸出到檔案操作|說明|
|---|---|
|ls -l /bin/usr 2> ls-error.txt|因為標準錯誤和檔案描述符2一樣,我們用這種 表示法來重定向標準錯誤
檔案描述符”2”,緊挨著放在重定向操作符之前,來執行重定向標準錯誤到檔案 ls-error.txt 任務。|
|cat ls-error.txt|ls: cannot access '/bin/usr': No such file or directory錯誤資訊已經在所指定檔案中|

重定向標準輸出和錯誤到同一個檔案
|命令|說明|
|---|---|
|ls -l /bin/usr > ls-output.txt 2>&1|首先重定向標準輸出到檔案 ls-output.txt,
然後 重定向檔案描述符2(標準錯誤)到檔案描述符1(標準輸出)使用表示法2>&1。
注意重定向的順序安排非常重要。標準錯誤的重定向必須總是出現在標準輸出 重定向之後,要不然它不起作用。|

處理不需要的輸出/dev/null位儲存桶

ls -l /bin/usr 2> /dev/null

管道操作符|提取資料

  • 把多個命令連線起來組成一個強大的命令管道。
    管道操作符”|”(豎槓),一個命令的標準輸出可以通過管道送至另一個命令的標準輸入

command1 | command2

  • 過濾器

管道線經常用來對資料完成複雜的操作。有可能會把幾個命令放在一起組成一個管道線。 通常,以這種方式使用的命令被稱為過濾器。過濾器接受輸入,以某種方式改變它,然後輸出它。

命令 含義 示例 例子
cat Concatenate files
連線檔案
cat [file]不分頁顯示 cat < abc.txt 將檔案重定向輸入到cat中
sort Sort lines of text
排序文字行
ls /bin /usr/bin | sort | less
因為我們指定了兩個目錄(/bin 和/usr/bin),ls 命令的輸出結果由有序列表組成, 各自針對一個目錄。通過在管道線中包含 sort,我們改變輸出資料,從而產生一個 有序列表。
uniq Report or omit repeated lines
報道或省略重複行
ls /bin /usr/bin | sort | uniq | less
uniq 從 sort 命令的輸出結果中,來刪除任何重複行
grep Print lines matching a pattern
列印匹配行
grep pattern [file...] ls /bin /usr/bin | sort | uniq | grep zip
找到檔名中包含單詞”zip”的所有檔案
方便的選項:”-i”使得 grep 在執行搜尋時忽略大小寫(通常,搜尋是大小寫 敏感的),”-v”選項會告訴 grep 只打印不匹配的行。
wc Print newline, word, and byte counts for each file
列印檔案中換行符,字,和位元組個數
字計數 #wc xy.c
1 1 6 xy.c
xy.c檔案中有hello內容,輸出換行符1個,字1個,位元組數6個
ls /bin /usr/bin | sort | uniq | wc -l
-l 選項限制命令輸出只能 報道行數
head Output the first part of a file
輸出檔案第一部分
預設情況下,列印十行文字 head -n 5 ls-output.txt
只打印檔案前5行
ls /usr/bin | tail -n 5
tail Output the last part of a file
輸出檔案最後一部分
預設情況下,列印十行文字 tail -f /var/log/messages
tail的f選項允許實時地瀏覽檔案。當新的內容新增到檔案後,它們會立即 出現在螢幕上。這會一直繼續下去直到你輸入 Ctrl-c
tee Read from standard input and write to standard output and files
從標準輸入讀取資料,並同時寫到標準輸出和檔案
ls /usr/bin | tee ls.txt | grep zip
在 grep 過濾管道線的內容之前,來捕捉整個目錄列表到檔案 ls.txt

比方說我們下載了一個 大型檔案,這個檔案被分離成多個部分(USENET 中的多媒體檔案經常以這種方式分離), 我們想把它們連起來。

cat movie.mpeg.0* > movie.mpeg

movie.mpeg.001 movie.mpeg.002 … movie.mpeg.099,we could join them back together with this command

正則表示式

用“元字元”實現複