第九课 Shell基础
目錄
1. 命令歷史(history)
Linux 可以記錄每個用戶所使用的命令, 并記錄到 ~/.bash_history 文件中
當用戶以 bash 登入 Linux 主機后, 系統會主動地由 ~/.bash_history 讀取命令歷史
當用戶注銷時, 會將最近的 HISTFILESIZE 個記錄寫入 ~/.bash_history 文件中
1.1 相關文件及變量
- 文件: ~/.bash_history
- 變量: HISTFILE=/home/<user>/.bash_history or /root/.bash_history # 指定 history 文件
- 變量: HISTFILESIZE=1000 # history 文件最大的命令記錄條數
- 變量: HISTSIZE=1000 # 當前環境最大的命令記錄條數
1.2 history 命令用法
- history #: 列出最近的 # 條命令
- history -c: 清除當前內存內的全部命令記憶
- history -r: 將 history 文件中的命令記憶讀出到當前內存中 #一般登錄時會自動進行
- history -w: 將目前的內存中的命令記憶寫入 history 文件中 # 一般登出時會自動進行
1.3 命令歷史相關的使用技巧
- !<#> 執行 history 命令顯示的 第 # 條命令
- !! 執行上一條命令
- !<keywords> 執行最近的一條以< keywords> 開頭的命令
2. 命令補全(『Tab』)
非常提高工作效率的東西
這東西沒法上代碼,自己嘗試吧,誰用誰知道。
按一下:能進行 『命令』 以及 『文件名』 的補全
按兩下:能夠羅列出所有符合補全的可能選項
3. 命令別名(alias、unalias)
命令太長?常用命令的選項太多?有些命令后果嚴重,想在執行前進行提醒?
—— 用命令別名啊
3.1 查看當前已經存在的命令別名:alias
[root@localhost ~]# alias alias cp='cp -I' alias egrep='egrep --color=auto' alias fgrep='fgrep --color=auto' alias grep='grep --color=auto' alias l.='ls -d .* --color=auto' alias ll='ls -l --color=auto' alias ls='ls --color=auto' alias mv='mv -I' alias rm='rm -I' alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'3.2 設置命令別名
alias xx=xxx -x x -x x
[root@localhost ~]# alias lm='ll -a | more' [root@localhost ~]# alias | grep lm alias lm='ll -a | more'3.3 命令別名的相關文件
如果在 bash 中設置命令別名,則重啟后別名失效
其實只要是用戶登錄后所有會調用的環境配置文檔中寫入自定義命令別名的設置語句,都能實現 命令別名的固定
看一下 ~/.bashrc # 下列是 root 用戶的 ~./bashrc 文件, 為安全起見已進行了部分別名設置, 但普通用戶一般不會有這樣的別名設置
[root@localhost ~]# cat .bashrc # .bashrc# User specific aliases and functionsalias rm='rm -I' alias cp='cp -I' alias mv='mv -I'# Source global definitions if [ -f /etc/bashrc ]; then. /etc/bashrc fi3.4 取消命令別名:unalias <別名>
[root@localhost ~]# alias alias cp='cp -I' alias egrep='egrep --color=auto' alias fgrep='fgrep --color=auto' alias grep='grep --color=auto' alias l.='ls -d .* --color=auto' alias ll='ls -l --color=auto' alias lm='ll -a | more' # 當前 alias 中存在 lm alias ls='ls --color=auto' alias mv='mv -I' alias rm='rm -I' alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'[root@localhost ~]# unalias lm ; alias # 取消 lm 的別名后,發現別名中已沒有 lm alias cp='cp -I' alias egrep='egrep --color=auto' alias fgrep='fgrep --color=auto' alias grep='grep --color=auto' alias l.='ls -d .* --color=auto' alias ll='ls -l --color=auto' alias ls='ls --color=auto' alias mv='mv -I' alias rm='rm -I'alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'4. 通配符與特殊符號
- 通配符
| * | 代表0-無窮個 任意字符 |
| ? | 代表有且只有一個字符 |
| [ ] | 代表有且僅有一個字符,且為[…]中所枚舉的其中一個, 如 [13579] |
| [-] | 同上,只不過是一個范圍,如[ 0-9 ],[a-z]等 |
| [^] | 有且僅有一個,且不是所枚舉的任何字符,如:[^a-zA-Z] 代表該位不是字母 |
- 特殊符號
| # | 批注號 |
| \ | 轉義符號,將特殊字符或通配符還原成一般字符 |
| | | 管道符 |
| ; | 命令銜接符,連續執行兩條命令 |
| ~ | 當前用戶家目錄 |
| $ | 取用變量符號 |
| & | 工作控制,將指令變成后臺工作 |
| ! | 邏輯非 |
| > 、 >> | 數據流重定向,output |
| <、<< | 數據流重定向,input |
| ’ ‘ | 單引號,無法引用變量 |
| ” “ | 雙引號,可以引用變量 |
| ` ` | 指令引用,功能同 $(command) |
5. 輸入輸出重定向
先看看正常情況下,執行命令時,數據流的走向
5.1 standard output & standard error output
標準輸出,即命令成功執行時,將執行結果輸出至文件 or 設備
符號:> (覆蓋導出) 或 >> (追加導出)
5.1.1 標準輸出(覆蓋): >
如果多次命令的結果導出至同一個文件, 并采用覆蓋方式,那該文件將僅保留最后一次輸出的結果
[root@choco-01 ~]# cat /etc/motd /\ /\ |/ \ / \ |/ \ / \ ||----- .[root@choco-01 ~]# cat /etc/motd > aaa #屏幕上不再顯示笑臉,原本該輸出至屏幕的內容,現在輸出至 aaa 文件了 [root@choco-01 ~]# cat aaa/\ /\ |/ \ / \ |/ \ / \ ||----- .既然是覆蓋導出,我們再導出一個數據流到 aaa 文件,然后看看 aaa 文件變成啥樣了
[root@choco-01 ~]# ls / > aaa [root@choco-01 ~]# cat aaa # 原本的內容不見了 777 bin boot dev disk-test etc home lib lib64 media mnt opt proc root run sbin srv sys test tmp usr var YUM5.1.2 標準輸出(追加): >>
如果多次命令結果導出至同一個文件,若采用追加方式,那每次命令的結果都會追加至該文件的末尾
[root@choco-01 ~]# echo "asdfasdf" >> aaa [root@choco-01 ~]# cat aaa 777 bin boot dev disk-test etc home lib lib64 media mnt opt proc root run sbin srv sys test tmp usr var YUM aaa anaconda-ks.cfg col.man expect-test passwd passwd.linux tee.txt asdfasdf # 看,最后一次導出的結果,被追加至該文件的末尾了5.1.3 標準錯誤輸出(覆蓋): 2>
[root@choco-01 ~]# ls asdfasdf 2> bbb [root@choco-01 ~]# cat bbb ls: 無法訪問asdfasdf: 沒有那個文件或目錄 [root@choco-01 ~]# ls haha 2> bbb [root@choco-01 ~]# cat bbb ls: 無法訪問haha: 沒有那個文件或目錄5.1.4 標準錯誤輸出(追加): 2>>
[root@choco-01 ~]# cat bbb ls: 無法訪問haha: 沒有那個文件或目錄 [root@choco-01 ~]# ls 1234567 2>> bbb [root@choco-01 ~]# cat bbb ls: 無法訪問haha: 沒有那個文件或目錄 ls: 無法訪問1234567: 沒有那個文件或目錄5.1.5 同時進行標準輸出與標準錯誤輸出
如果同時想將正常輸出與錯誤輸出都導入到同一個文件,且按照順序,使用 2>&1 或 &>
<command> ><file> 2>&1 如: ls a b > report.txt 2>&1
[root@choco-01 ~]# ls aaa anaconda-ks.cfg bbb expect-test [root@choco-01 ~]# ls aaa asdfasdf > aaa ls: 無法訪問asdfasdf: 沒有那個文件或目錄 # 屏幕上顯示了標準錯誤輸出的信息 [root@choco-01 ~]# cat aaa aaa # 文件中僅能看到標準輸出的信息 [root@choco-01 ~]# ls aaa asdfasdf 2> bbb aaa # 屏幕上顯示了標準輸出的信息 [root@choco-01 ~]# cat bbb ls: 無法訪問asdfasdf: 沒有那個文件或目錄 # 文件中僅能看到標準錯誤輸出的信息 [root@choco-01 ~]# ls aaa asdfasdf > aaa 2>&1 [root@choco-01 ~]# cat aaa # 這樣就都能看到了 ls: 無法訪問asdfasdf: 沒有那個文件或目錄 aaa5.2 standard input
原本需要由鍵盤輸入的數據,改由文件內容來取代
5.2.1 標準輸入(以 Ctrl + d 結束)
[root@choco-01 ~]# cat > aaa 123 456 [Ctrl + d] [root@choco-01 ~]# cat aaa 123 456[root@choco-01 ~]# cat aaa 123 456 [root@choco-01 ~]# cat > aaa < .bashrc # .bashrc 的內容替換了屏幕輸入,并被放到 aaa 文件中 [root@choco-01 ~]# cat aaa # .bashrc# User specific aliases and functionsalias rm='rm -I' alias cp='cp -I' alias mv='mv -I'# Source global definitions if [ -f /etc/bashrc ]; then. /etc/bashrc fi5.2.2 標準輸入(以 指定字符 結束)
[root@choco-01 ~]# cat > bbb << "fuckoff" > 123123 > 456456 > fuckoff [root@choco-01 ~]#5.3 巧用垃圾桶
Linux 下有一個特殊的設備 /dev/null ,所有被寫入該設備的東西都會消失,所以如果有部分信息不想輸出至文件,也不想輸出至屏幕,那就輸出至 /dev/null 吧
6. 管道符
管道的概念與數據流重定向不同,管道只是在輸出至屏幕前多加一道工序,而配合管道的這些工序,往往是字符處理軟件
例子:
ls /etc/ | more # 原本要直接輸出至屏幕的信息, 用 more 進行了加工
ls /etc/ | grep "bash" # 原本直接輸出至屏幕的信息, 用 grep "bash" 進行了加工, 篩選出了關鍵字
7. 作業控制
當你希望同時執行多項耗時較長的任務時, 雖然 tty 有多個, 但是來回切換也是很麻煩的
這時可以用到 linux 下的 “工作管理”
7.1 基本概念
- foreground: 前臺, 平常執行命令的界面
- background: 后臺, 看不到的地方
- 什么樣的工作適合放到后臺: 不需要與用戶交互的命令
- 放入后臺的工作是無法用 Ctrl + c 來終止的
- 后臺的工作有兩種狀態: 暫停(stop) 和 運行中( running)
7.2 直接將命令放到后臺運行(&)
直接在待執行的命令的最后加上空格和 &
[root@localhost tmp]# vim aaa & [1] 2561加上&后, 命令直接被甩到后臺進行執行, 在執行完成后會在前臺彈出提示
但是, 如果執行的命令帶有 stdout 或 stderr 時(如 tar -v), 則大量信息仍然會扔到前臺來, 所以此時最好用上數據流重定向(推薦 2>&1
7.3 將正在運行的命令扔到后臺,且置為暫停(ctrl+z)
[root@localhost tmp]# vim bbb # 此時按下 ctrl+z, 將正在執行的 vim 扔到后臺且置為暫停 [1]- 已停止 vim aaa[2]+ 已停止 vim bbb[root@localhost tmp]# vim ccc# 扔后臺 [3]+ 已停止 vim ccc任何正在執行的任務, 在按下 ctrl+z 后, 都會被扔到后臺, 且置為”暫停”狀態
代碼中看到每暫停一個工作, 提示信息里就顯示一個數字和一個加號, 數字表示改任務目前在后臺的編號, 而加號則代表該任務是最新的一個被扔后臺的任務
7.4 查看后臺中的任務(jobs)
[root@localhost tmp]# jobs [1] 已停止 vim aaa [2]- 已停止 vim bbb [3]+ 已停止 vim ccc加號: 最新被扔進來的
減號: 次新被扔進來的
更早被扔進來的就不帶符號了
jobs 的選項:
* -l:同時列出任務的 PID
* -r: 僅列出后臺中處于 “running” 的任務
* -s: 僅列出后臺中處于 “stop” 的任務
7.5 將后臺工作拿回到前臺來(fg)
fg <job_num>
或
fg #不加任務號則將帶加號的拿回來
再次扔回后臺的命令將帶有加號, 因為 加號/減號 分別代表 最新/次新, 是個相對的概念, 所以在前后臺切換的過程中會不斷變化
但是 任務號 不會發生變化
7.6 將后臺暫停的任務激活
bg <job_num>
或
bg #不加任務號則將在后臺激活帶加號的任務
7.7 kill 命令(簡)
如果想要直接移除后臺的任務怎么做?
—用 kill
7.7.1 kill 的用法
kill -<signal> %<job_num>
或
kill -<signal> <PID>
7.7.2 常用 signal
* -1: 重新讀取參數的配置文件(類似 reload)
* -9: 立即強制刪除一個任務
* -15: 已正常方式結束一個任務
7.7.3 例子
[root@localhost tmp]# jobs [4]+ 已停止 tar -zcf root.tar.gz / [root@localhost tmp]# kill -9 %4 ; jobs # kill 掉4號任務 [4]+ 已停止 tar -zcf root.tar.gz / [root@localhost tmp]# jobs # 有一定延時才能殺死 [4]+ 已殺死 tar -zcf root.tar.gz / [root@localhost tmp]# jobs # 殺干凈后沒有任務了 [root@localhost tmp]#ps-1.: kill 默認是以 PID 來進行進程殺死的, 若要殺死某個任務號, 則任務號前必須加 %
ps-1.: -9是暴力殺死, -15是溫柔殺死, 兩者的區別在殺死 vim 時較為明顯: 若用 -9 殺死, 則會留有 .filename.swp 文件, 下次再進行 vim 時會有修復提示; 而若用 -15 殺死, 則能較好地料理后事, 不會有這種緩存文件存在.
8. Shell 變量
8.1 變量的種類
環境變量
往往以純大寫來命名, bash 的子進程中仍可使用自定義變量
推薦使用純小寫來命名, 不經過聲明, 則在 bash 的子進程中無法使用
8.2 變量的命名
由字母、數字、下劃線組成,且只能以非數字開頭
8.3 變量的設定
語法:變量名=變量值
注意-1:如果變量值中存在空格,需要用單引號或雙引號將變量值括起來
注意-2:如果變量值中有引用其他變量,需要用雙引號將變量值括起來
例一:
[root@choco-01 ~]# myname=Choco [root@choco-01 ~]# echo $myname Choco [root@choco-01 ~]# myname=Choco Lee -bash: Lee: 未找到命令 [root@choco-01 ~]# echo $myname Choco [root@choco-01 ~]# myname='Choco Lee' [root@choco-01 ~]# echo $myname Choco Lee例二:
[root@choco-01 ~]# myadd=China [root@choco-01 ~]# full='$myname @ $myadd' [root@choco-01 ~]# echo $full $myname @ $myadd #單引號不具有引用變量的能力 [root@choco-01 ~]# full="$myname @ $myadd" [root@choco-01 ~]# echo $full Choco Lee @ China [root@choco-01 ~]#8.4 變量的相關命令
8.4.1echo
功能:打印變量的內容
8.4.2 export
功能:將變量轉換為環境變量
8.4.3 env
功能:查看環境變量
8.4.4 declare
用法:
declare [-aixr] <var_name>
選項:
* -a:定義變量為數組
* -i:定義變量為純數字
* -x:定義變量為環境變量
* -r:定義變量為 readonly
8.5 常用環境變量
- HOME: 當前用戶的家目錄
- HOSTNAME: 該主機的主機名
- USER: 當前用戶的用戶名
- SHELL: 當前使用的 shell 類型
- HISTSIZE: 可存儲的歷史命令條數
- MAIL: 當前用戶的郵箱
- PATH: 可執行命令的所在目錄
- LANG: 當前語系
- PS1: 命令提示符的格式, 可玩性較高, 但工作中不常用, 可自行 man bash 查看 PS1 的設置方法
- PS2: 輸入命令時強制換行后的提示符
- OSTYPE: 當前操作系統類型
- MACHTYPE: 安裝的機器類型
- HOSTTYPE: 主機的位數, x86 還是 x86_64
9. 環境變量配置文件
9.1 login 與 non-login
login shell:取得 bash 時需要完整的登錄流程。如由 tty1-tty6登錄時,需要輸入用戶的賬號和密碼
讀取的文件:- /etc/profile :系統整體的設定,對所有用戶皆生效
- ~/.bash_profile 或 ~/.bash_login 或 ~/.profile:用戶的個人設定
但是各個文件中可能又會調用其他的文件,所以一般來說,login shell 讀取的文件如下圖所示:
non-login shell:取得 bash 接口的方法不需要重復登錄的舉動,如在 bash 環境下,再次執行bash命令進入子 shell 時,不需要輸入賬號和密碼
9.2 /etc/profile (login shell)
該文件會根據用戶的 UID 設定好許多環境變量以及參數
9.2.1 設定環境變量
* PATH:根據 UID 決定PATH 變量是否要包含 sbin 目錄
* USER:根據 id 命令的結果,顯示用戶名
* LOGNAME:等于 USER
* MAIL:配置好用戶的郵箱
* HOSTNAME:根據 hostname 指令,決定該變量值
* HISTSIZE:直接設定歷史命令記錄的條數為 1000
9.2.2 調用 /etc/profile.d/*.sh
for i in /etc/profile.d/*.sh ; doif [ -r "$i" ]; thenif [ "${-#*i}" != "$-" ]; then. "$I"else. "$i" >/dev/nullfifi done/etc/profile.d/ 下的腳本,主要是進行 bash 顏色、語系、vi 的別名、which 的別名等設置
9.3 ~/.bash_profile (login shell)
根據之前流程圖的描述,bash shell 讀取完通用配置后,才開始進行用戶個性化配置的讀取。
其實用戶個性化配置的文件不止 ~/.bash_profile 一個,還可能有 ~/.bahs_login 和 ~/.profile
為什么有這么多個性化配置文件呢?主要是為了給從其他種類的 shell 轉來使用 bash 的用戶提供便利,滿足其習慣罷了。
所以我們往往只能見到 ~/.bash_profile 而已
9.3.1 三種文件的讀取順序及規律
其實 bash 的 login shell 只會讀取上述文件中的其中一個, 讀取順序依照上面的排序, 一旦讀取到其中一個文件, 就不再繼續讀取其余文件
9.3.2 ~/.bash_profile 內容
[root@localhost ~]# cat .bash_profile # .bash_profile# Get the aliases and functions if [ -f ~/.bashrc ]; then. ~/.bashrc fi# User specific environment and startup programsPATH=$PATH:$HOME/binexport PATH~/.bash_profile 調取了 ~/.bashrc 文件, 并將 ~/bin 目錄加入到 PATH 變量中
9.4 ~/.bashrc (non-login shell)
當通過 non-login shell 取得 bash 后, 僅會讀取 ~/.bashrc 文件
先來看看 ~/.bashrc 的內容吧
[root@localhost ~]# cat .bashrc # .bashrc# User specific aliases and functionsalias rm='rm -I' alias cp='cp -I' alias mv='mv -I'# Source global definitions if [ -f /etc/bashrc ]; then. /etc/bashrc fi定義了幾個別名, 然后又調用了 /etc/bashrc
/etc/bashrc 會完成以下任務
* 根據不同的 UID 設置 umask 值
* 根據不同的 UID 設置 PS1 變量
* 調用 /etc/profile.d/*.sh
ps. 如果家目錄下沒有 .bashrc 文件, 那么你的 bash 提示符可能會變成如下樣子
-bash-4.2#但是沒關系, 還記得 /etc 下有個模板目錄嗎? 就是 /etc/shel/. 把該目錄下的 .bashrc 文件復制到家目錄即可.
總結
以上是生活随笔為你收集整理的第九课 Shell基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows8 flash修复怎么操作
- 下一篇: 分享15个超棒的透明风格名片设计