前文:VIM的用法
bash的基礎特性:
一、
命令歷史:shell進程會其會話中保存此前用戶提交執行過的命令;
~]# history
定製history的功能,可通過環境變量實現:
HISTSIZE:shell進程可保留的命令歷史的條數;
HISTFILE:持久保存命令歷史的文件;
.bash_history
HISTFILESIZE:命令歷史文件的大小;
命令用法:
history [-c] [-d 偏移量] [n]
或 history -anrw [文件名]
或 history -ps 參數 [參數...]
-c: 清空命令歷史;
-d offset:刪除指定命令歷史
-r: 從文件讀取命令歷史至歷史列表中;
-w:把歷史列表中的命令追加至歷史文件中;
history #:顯示最近的#條命令;
調用命令歷史列表中的命令:
!#:再一次執行歷史列表中的第#條命令;
!!:再一次執行上一條命令;
!STRING:再一次執行命令歷史列表中最近一個以STRING開頭的命令;
注意:命令的重複執行有時候需要依賴於冪等性;
調用上一條命令的最後一個參數:
快捷鍵:ESC, .
字符串:!$
控制命令歷史記錄的方式:
環境變量:HISTCONTROL
ignoredups:忽略重複的命令;
ignorespace:忽略以空白字符開頭的命令;
ignoreboth:以上兩者同時生效;
修改變量的值:
NAME='VALUE'
二、命令補全:
shell程序在接收到用戶執行命令的請求,分析完成之後,最左側的字符串會被當作命令;
命令查找機制:
查找內部命令;
根據PATH環境變量中設定的目錄,自左而右逐個搜索目錄下的文件名;
給定的打頭字符串如果能惟一標識某命令程序文件,則直接補全;
不能惟一標識某命令程序文件,再擊tab鍵一次,會給出列表;
三、路徑補全:
在給定的起始路徑下,以對應路徑下的打頭字串來逐一匹配起始路徑下的每個文件:
tab:
如果能惟一標識,則直接補全;
否則,再一次tab,給出列表;
四、命令行展開
~:自動展開爲用戶的家目錄,或指定的用戶的家目錄;
{}:可承載一個以逗號分隔的路徑列表,並能夠將其展開爲多個路徑;
例如:/tmp/{a,b} 相當於 /tmp/a /tmp/b
五、命令的執行狀態結果
命令執行的狀態結果:
bash通過狀態返回值來輸出此結果:
成功:0
失敗:1-255
命令執行完成之後,其狀態返回值保存於bash的特殊變量$?中;
命令正常執行時,有的還回有命令返回值:
根據命令及其功能不同,結果各不相同;
引用命令的執行結果:
$(COMMAND)
或`COMMAND`
六、引用
強引用:''
弱引用:""
命令引用:``
七、快捷鍵
Ctrl+a:跳轉至命令行行首
Ctrl+e:跳轉至命令行行尾
Ctrl+u:刪除行首至光標所在處之間的所有字符;
Ctrl+k:刪除光標所在處至行尾的所有字符;
Ctrl+l:清屏,相當於clear
八、globbing:文件名通配(整體文件名匹配,而非部分)
匹配模式:元字符
*:匹配任意長度的任意字符
pa*, *pa*, *pa, *p*a*
pa, paa, passwd
?:匹配任意單個字符
pa?, ??pa, p?a, p?a?
pa, paa, passwd
[]:匹配指定範圍內的任意單個字符
有幾種特殊格式:
[a-z], [A-Z], [0-9], [a-z0-9]
[[:upper:]]:所有大寫字母
[[:lower:]]:所有小寫字母
[[:alpha:]]:所有字母
[[:digit:]]:所有數字
[[:alnum:]]:所有的字母和數字
[[:space:]]:所有空白字符
[[:punct:]]:所有標點符號
pa[0-9][0-9], 2[0-9][0-9]
[^]:匹配指定範圍外的任意單個字符
[^[:upper:]]
[^0-9]
[^[:alnum:]]
九、IO重定向及管道
程序:指令+數據
程序:IO
可用於輸入的設備:文件
鍵盤設備、文件系統上的常規文件、網卡等;
可用於輸出的設備:文件
顯示器、文件系統上的常規文件、網卡等;
程序的數據流有三種:
輸入的數據流;<-- 標準輸入(stdin),鍵盤;
輸出的數據流:--> 標準輸出(stdout),顯示器;
錯誤輸出流: --> 錯誤輸出(stderr),顯示器;
fd: file descriptor,文件描述符
標準輸入:0
標準輸出:1
錯誤輸出:2
IO重定向:
輸出重定向:>
特性:覆蓋輸出
輸出重定向:>>
特性:追加輸出
# set -C
禁止覆蓋輸出重定向至已存在的文件;
此時可使用強制覆蓋輸出:>|
# set +C
關閉上述特性
錯誤輸出流重定向:2>, 2>>
合併正常輸出流和錯誤輸出流:
(1) &>, &>>
(2) COMMAND > /path/to/somefile 2>&1
COMMAND >> /path/to/somefile 2>&1
特殊設備:/dev/null
輸入重定向:<
tr命令:
tr [OPTION]... SET1 [SET2]
把輸入的數據當中的字符,凡是在SET1定義範圍內出現的,通通對位轉換爲SET2出現的字符
用法1:
tr SET1 SET2 < /PATH/FROM/SOMEFILE
用法2:
tr -d SET1 < /PATH/FROM/SOMEFILE
注意:不修改原文件
Here Document:<<
cat << EOF
cat > /PATH/TO/SOMEFILE << EOF
管道:連接程序,實現將前一個命令的輸出直接定向後一個程序當作輸入數據流
COMMAND1 | COMMAND2 | COMMAND3 | ...
tee命令:
COMMAND | tee /PATH/TO/SOMEFILE
bash特性及bash腳本編程初步
終端,附着在終端的接口程序:
GUI:KDE, GNome, Xfce
CLI:/etc/shells
bash
zsh
fish
bash的特性:
命令行展開:~, {}
命令別名:alias, unalias
命令歷史:history
文件名通配:glob
快捷鍵:Ctrl+a, e, u, k, l
命令補全:$PATH
路徑補全:
bash特性之:命令hash
緩存此前命令的查找結果:key-value
key:搜索鍵
value:值
hash命令:
hash:列出
hash -d COMMAND:刪除
hash -r:清空
bash的特性之:變量
程序:指令+數據
指令:由程序文件提供;
數據:IO設備、文件、管道、變量
程序:算法+數據結構
變量名+指向的內存空間
變量賦值:name=value
變量類型:存儲格式、表示數據範圍、參與的運算
編程語言:
強類型變量
弱類型變量:
bash把所有變量統統視作字符型;
bash中的變量無需事先聲明;相當於,把聲明和賦值過程同時實現;
聲明:類型,變量名
變量替換:把變量名出現的位置替換爲其所指向的內存空間中數據;
變量引用:${var_name}, $var_name
變量名:變量名只能包含數字、字母和下劃線,而且不能以數字開頭;
變量名:見名知義,命名機制遵循某種法則;不能夠使用程序的保留字,例如if, else, then, while等等;
bash變量類型:
本地變量:作用域僅爲當前shell進程;
環境變量:作用域爲當前shell進程及其子進程;
局部變量:作用域僅爲某代碼片斷(函數上下文);
位置參數變量:當執行腳本的shell進程傳遞的參數;
特殊變量:shell內置的有特殊功用的變量;
$?:
0:成功
1-255:失敗
本地變量:
變量賦值:name=value
變量引用:${name}, $name
"":變量名會替換爲其值;
'':變量名不會替換爲其值;
查看變量:set
撤銷變量:unset name
注意:此處非變量引用;
環境變量:
變量賦值:
(1) export name=value
(2) name=value
export name
(3) declare -x name=value
(4) name=value
declare -x name
變量引用:${name}, $name
注意:bash內嵌了許多環境變量(通常爲全大寫字符),用於定義bash的工作環境
PATH, HISTFILE, HISTSIZE, HISTFILESIZE, HISTCONTROL, SHELL, HOME, UID, PWD, OLDPWD
查看環境變量:export, declare -x, printenv, env
撤銷環境變量:unset name
只讀變量:
(1) declare -r name
(2) readonly name
只讀變量無法重新賦值,並且不支持撤銷;存活時間爲當前shell進程的生命週期,隨shell進程終止而終止;
bash特性之多命令執行:
~]# COMMAND1; COMMAND2; COMMAND3; ...
邏輯運算:
運算數:真(true, yes, on, 1)
假(false, no, off, 0)
與:
1 && 1 = 1
1 && 0 = 0
0 && 1 = 0
0 && 0 = 0
或:
1 || 1 = 1
1 || 0 = 1
0 || 1 = 1
0 || 0 = 0
非:
! 1 = 0
! 0 = 1
短路法則:
~]# COMMAND1 && COMMAND2
COMMAND1爲“假”,則COMMAND2不會再執行;
否則,COMMAND1爲“真”,則COMMAND2必須執行;
~]# COMMAND1 || COMMAND2
COMMAND1爲“真”,則COMMAND2不會再執行;
否則,COMMAND1爲“假”,則COMMAND2必須執行;
示例:~]# id $username || useradd $username
shell腳本編程:
編程語言的分類:根據運行方式
編譯運行:源代碼 --> 編譯器 (編譯)--> 程序文件;
解釋運行:源代碼 --> 運行時啓動解釋器,由解釋器邊解釋邊運行;
根據其編程過程中功能的實現是調用庫還是調用外部的程序文件:
shell腳本編程:
利用系統上的命令及編程組件進行編程;
完整編程:
利用庫或編程組件進行編程;
編程模型:過程式編程語言,面向對象的編程語言
程序=指令+數據
過程式:以指令爲中心來組織代碼,數據是服務於代碼;
順序執行
選擇執行
循環執行
代表:C,bash
對象式:以數據爲中心來組織代碼,圍繞數據來組織指令;
類(class):實例化對象,method;
代表:Java, C++, Python
shell腳本編程:過程式編程,解釋運行,依賴於外部程序文件運行;
如何寫shell腳本:
腳本文件的第一行,頂格:給出shebang,解釋器路徑,用於指明解釋執行當前腳本的解釋器程序文件
常見的解釋器:
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
文本編程器:nano
行編輯器:sed
全屏幕編程器:nano, vi, vim
shell腳本是什麼?
命令的堆積;
但很多命令不具有冪等性,需要用程序邏輯來判斷運行條件是否滿足,以避免其運行中發生錯誤;
運行腳本:
(1) 賦予執行權限,並直接運行此程序文件;
chmod +x /PATH/TO/SCRIPT_FILE
/PATH/TO/SCRIPT_FILE
(2) 直接運行解釋器,將腳本以命令行參數傳遞給解釋器程序;
bash /PATH/TO/SCRIPT_FILE
注意:腳本中的空白行會被解釋器忽略;
腳本中,除了shebang,餘下所有以#開頭的行,都會被視作註釋行而被忽略;此即爲註釋行;
shell腳本的運行是通過運行一個子shell進程實現的;
練習1:寫一個腳本,實現如下功能;
(1) 顯示/etc目錄下所有以大寫p或小寫p開頭的文件或目錄本身;
(2) 顯示/var目錄下的所有文件或目錄本身,並將顯示結果中的小寫字母轉換爲大寫後顯示;
(3) 創建臨時文件/tmp/myfile.XXXX;
bash的配置文件:
兩類:
profile類:爲交互式登錄的shell進程提供配置
bashrc類:爲非交互式登錄的shell進程提供配置
登錄類型:
交互式登錄shell進程:
直接通過某終端輸入賬號和密碼後登錄打開的shell進程;
使用su命令:su - USERNAME, 或者使用 su -l USERNAME執行的登錄切換;
非交互式登錄shell進程:
su USERNAME執行的登錄切換;
圖形界面下打開的終端;
運行腳本
profile類:
全局:對所有用戶都生效;
/etc/profile
/etc/profile.d/*.sh
用戶個人:僅對當前用戶有效;
~/.bash_profile
功用:
1、用於定義環境變量;
2、運行命令或腳本;
bashrc類:
全局:
/etc/bashrc
用戶個人:
~/.bashrc
功用:
1、定義本地變量;
2、定義命令別名;
注意:僅管理員可修改全局配置文件;
交互式登錄shell進程:
/etc/profile --> /etc/profile.d/* --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
非交互式登錄shell進程:
~/.bashrc --> /etc/bashrc --> /etc/profile.d/*
命令行中定義的特性,例如變量和別名作用域爲當前shell進程的生命週期;
配置文件定義的特性,只對隨後新啓動的shell進程有效;
讓通過配置文件定義的特性立即生效:
(1) 通過命令行重複定義一次;
(2) 讓shell進程重讀配置文件;
~]# source /PATH/FROM/CONF_FILE
~]# . /PATH/FROM/CONF_FILE
問題1:定義對所有用戶都生效的命令別名,例如 lftps='lftp 172.16.0.1/pub'?
問題2:讓centos用戶登錄時,提供其已經登錄,並顯示當前系統時間?
回顧:
bash的特性:hash, 變量
命令hash:hash命令
變量:
本地變量、環境變量、局部變量
位置參數變量、特殊變量
變量賦值:name=value, export name=value, declare -x name=value
變量引用:$name, ${name}
撤銷:unset name
bash腳本編程,運行腳本
#!/bin/bash
#
bash的配置文件
profile類:登錄式shell
bashrc類:非登錄式shell
登錄式shell: /etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
非登錄式shell:~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh
練習:定義一個對所有用戶都生效的命令別名,例如:lftps='lftp 172.168.0.1/pub'
二、編寫腳本,實現自動添加三個用戶,並計算這三個用戶的uid之和。