分享一個(gè)可以通過(guò)命令簡(jiǎn)寫執(zhí)行對(duì)應(yīng)命令的Shell腳本
本篇文章介紹一個(gè)可以通過(guò)命令簡(jiǎn)寫執(zhí)行對(duì)應(yīng)命令的 shell 腳本。
假設(shè)這個(gè) shell 腳本的名稱為 tinyshell.sh。
在 Linux 下進(jìn)行項(xiàng)目開(kāi)發(fā),經(jīng)常會(huì)用到一些調(diào)試開(kāi)發(fā)命令。
這些命令可能比較長(zhǎng),需要輸入多個(gè)字符。
例如,Android 系統(tǒng)抓取全部 log 并包含 log 時(shí)間的命令是 adb logcat -b all -v threadtime。
抓取 log 是調(diào)試開(kāi)發(fā)非常常見(jiàn)的操作,這個(gè)命令又很長(zhǎng),輸入起來(lái)不方便。
為了簡(jiǎn)化輸入,可以配置一些命令簡(jiǎn)寫來(lái)對(duì)應(yīng)比較長(zhǎng)命令。
例如,配置 ala 對(duì)應(yīng) adb logcat -b all -v threadtime。
把 als 作為參數(shù)傳遞給當(dāng)前的 tinyshell.sh 腳本,會(huì)執(zhí)行該命令簡(jiǎn)寫對(duì)應(yīng)的命令。
這樣只需要輸入比較少的字符,就能執(zhí)行比較長(zhǎng)的命令。
實(shí)際上,這個(gè)功能類似于 bash 的 alias 別名,只是將這些別名統(tǒng)一放到該腳本來(lái)處理。
可以把 tinyshell.sh 腳本作為學(xué)習(xí) shell 腳本的參考例子,獨(dú)立維護(hù)更新,根據(jù)需要擴(kuò)充更多的功能。
配置命令簡(jiǎn)寫
如之前說(shuō)明,可以用 ala 表示 adb logcat -b all -v threadtime 這個(gè)命令。
這個(gè) ala 稱之為 “命令簡(jiǎn)寫”。
命令簡(jiǎn)寫使用一些簡(jiǎn)單的字符來(lái)表示特定的命令。
可以在命令簡(jiǎn)寫后面動(dòng)態(tài)提供命令的參數(shù)。
為了方便動(dòng)態(tài)添加、刪除、查詢命令簡(jiǎn)寫,可以把這些命令簡(jiǎn)寫保存在一個(gè)配置文件里面。
在執(zhí)行 tinyshell.sh 腳本時(shí),會(huì)讀取配置文件內(nèi)容,獲取到各個(gè)配置項(xiàng)的值。
配置項(xiàng)的基本格式是:命令簡(jiǎn)寫|命令內(nèi)容
每個(gè)配置項(xiàng)占據(jù)一行。每一行默認(rèn)以第一個(gè)豎線 ‘|' 隔開(kāi)命令簡(jiǎn)寫和命令內(nèi)容。
一個(gè)參考的配置文件內(nèi)容如下所示:
ll|ls --color=auto -l ala|adb logcat -b all -v threadtime gl|git log gp|git pull --stat --no-tags $(git remote) $(git rev-parse --abbrev-ref HEAD)
這里配置的命令內(nèi)容可以是系統(tǒng)支持的任意命令。
解析配置文件時(shí),需要用到之前文章介紹的 parsecfg.sh 腳本。
要獲取 parsecfg.sh 腳本的代碼,可以查看之前的文章。
后面會(huì)提供具體測(cè)試的例子,可供參考。
腳本代碼
列出 tinyshell.sh 腳本的具體代碼如下所示。
在這個(gè)代碼中,對(duì)大部分關(guān)鍵代碼都提供了詳細(xì)的注釋,方便閱讀。
這篇文章的后面也會(huì)對(duì)一些關(guān)鍵點(diǎn)進(jìn)行說(shuō)明,有助理解。
#!/bin/bash -i # 使用 bash 的 -i 選項(xiàng),讓該腳本在交互模式下運(yùn)行. # 實(shí)現(xiàn)一個(gè)小型的 shell. 支持內(nèi)置命令、命令簡(jiǎn)寫. 如果提供這兩種命令之外 # 的其他命令,會(huì)嘗試在 bash 中直接執(zhí)行所給命令,可以執(zhí)行系統(tǒng)支持的命令. # 命令簡(jiǎn)寫指的是一些簡(jiǎn)單的字符,會(huì)對(duì)應(yīng)一串實(shí)際要執(zhí)行的命令.只要輸入命令 # 簡(jiǎn)寫就可以執(zhí)行對(duì)應(yīng)的命令,減少需要輸入的字符.命令簡(jiǎn)寫在配置文件中配置. # 下面變量指定默認(rèn)解析的配置文件名.該文件配置了命令簡(jiǎn)寫、以及對(duì)應(yīng)的命令. # 這個(gè) tinyshellcmds.txt 文件需要預(yù)先配置好,放到指定路徑的目錄底下. # 直接修改這個(gè)配置文件,就可以動(dòng)態(tài)添加或刪除命令簡(jiǎn)寫.不需要修改腳本代碼. SHORT_COMMANDS="${HOME}/.liconfig/tinyshellcmds.txt" # PARSECFG_filepath 是 parsecfg.sh 腳本里面的變量. 如果這個(gè)變量為空, # 說(shuō)明還沒(méi)有打開(kāi)過(guò)配置文件,進(jìn)入下面的分支打開(kāi)默認(rèn)的配置文件. if [ -z "$PARSECFG_filepath" ]; then # 導(dǎo)入解析配置文件的腳本,以便調(diào)用該腳本的函數(shù)來(lái)解析配置文件. source parsecfg.sh # 調(diào)用 parsecfg.sh 里面的 open_config_file() 函數(shù)解析配置文件. # 如果配置文件不存在,會(huì)返回 1,經(jīng)過(guò)'!'操作符取反為 0,會(huì)退出執(zhí)行. if ! open_config_file "$SHORT_COMMANDS"; then exit 2 fi fi # 下面變量指定 tiny shell 的提示字符串. PROMPT="TinySh>>> " # 下面使用 basename 命令來(lái)提取出腳本的文件名,去掉目錄路徑部分. show_help() { printf "USAGE $(basename $0) [option] [shortcmd [argument1 ... [argumentn]]] OPTIONS option: 可選的選項(xiàng)參數(shù). 支持的選項(xiàng)參數(shù)描述如下: -h: 打印這個(gè)幫助信息. -l: 打印配置文件本身的內(nèi)容,會(huì)列出配置的命令簡(jiǎn)寫和對(duì)應(yīng)的命令. -v: 以鍵值對(duì)的方式列出命令簡(jiǎn)寫和對(duì)應(yīng)的命令. -i: 在配置文件中查找指定內(nèi)容.后面跟著一個(gè)參數(shù),指定要查找的內(nèi)容. -e: 使用 vim 打開(kāi)腳本的配置文件,以供編輯. -a: 新增或修改一個(gè)命令簡(jiǎn)寫和對(duì)應(yīng)的命令.后面跟著一個(gè)參數(shù),用 單引號(hào)括起來(lái),以指定命令簡(jiǎn)寫和命令. 格式為: 命令簡(jiǎn)寫|命令. 例如 -a 'p|git pull',如果p簡(jiǎn)寫不存在則新增它,否則修改它. -d: 從腳本配置文件中刪除一個(gè)命令簡(jiǎn)寫和對(duì)應(yīng)的命令.后面跟著一個(gè) 參數(shù),指定要?jiǎng)h除的命令簡(jiǎn)寫.例如 -d s,會(huì)刪除命令簡(jiǎn)寫為 s 的行. shortcmd: 可選選項(xiàng). 指定要直接執(zhí)行的命令簡(jiǎn)寫. 提供命令簡(jiǎn)寫參數(shù),不會(huì)進(jìn)入 tiny shell. argument1 ... argumentn: 可選選項(xiàng). 指定該命令簡(jiǎn)寫的參數(shù). 命令簡(jiǎn)寫對(duì)應(yīng)一個(gè)命令,支持動(dòng)態(tài)提供參數(shù). NOTE 如果沒(méi)有提供任何參數(shù),默認(rèn)會(huì)進(jìn)入 tiny shell 解釋器. 在 tiny shell 中 接收用戶輸入并執(zhí)行對(duì)應(yīng)的命令.直到讀取到EOF、或者執(zhí)行quit命令才會(huì)退出. " } # tiny shell 的內(nèi)置命令數(shù)組. 這是一個(gè)關(guān)聯(lián)數(shù)組. 數(shù)組元素的 # 鍵名是內(nèi)置命令名. 數(shù)組元素的鍵值是響應(yīng)內(nèi)置命令的函數(shù)名. declare -A BUILTIN_COMMAND=( \ [help]="builtin_command_help" \ [quit]="builtin_command_quit" \ [debug]="builtin_command_debug" \ ) # bash 的 help 命令默認(rèn)會(huì)打印內(nèi)置命令列表. 這里仿照這個(gè)行為, # 讓 help 內(nèi)置命令打印內(nèi)置命令列表、以及配置文件包含的命令簡(jiǎn)寫. builtin_command_help() { printf "下面列出 Tiny Shell 支持的內(nèi)置命令列表和配置的命令簡(jiǎn)寫列表. 輸入內(nèi)置命令名或命令簡(jiǎn)寫,會(huì)執(zhí)行對(duì)應(yīng)的命令. 也可以輸入系統(tǒng)自身支持的命令,會(huì)在 bash 中執(zhí)行所給命令. 內(nèi)置命令列表: debug: 所給第一個(gè)參數(shù)指定打開(kāi)、或關(guān)閉調(diào)試功能. 其參數(shù)說(shuō)明如下: on: 打開(kāi)調(diào)試功能,會(huì)執(zhí)行 bash 的 set -x 命令 off: 關(guān)閉調(diào)試功能,會(huì)執(zhí)行 bash 的 set +x 命令 help: 打印當(dāng)前幫助信息. quit: 退出當(dāng)前 Tiny Shell. 命令簡(jiǎn)寫列表: " # 調(diào)用 parsecfg.sh 的 handle_config_option -v 打印命令簡(jiǎn)寫列表 handle_config_option -v } # quit 內(nèi)置命令. 執(zhí)行該命令會(huì)退出整個(gè)腳本,從而退出當(dāng)前 tiny shell. builtin_command_quit() { exit } # debug 內(nèi)置命令. 所給第一個(gè)參數(shù)指定打開(kāi)、或關(guān)閉調(diào)試功能. # debug on: 打開(kāi)調(diào)試功能,會(huì)執(zhí)行 bash 的 set -x 命令 # debug off: 關(guān)閉調(diào)試功能,會(huì)執(zhí)行 bash 的 set +x 命令 builtin_command_debug() { if [ $# -ne 1 ]; then echo "Usage: debug on/off" return 1 fi if [ "$1" == "on" ]; then set -x elif [ "$1" == "off" ]; then set +x else echo -e "Unknown argument: $1\nUsage: debug on/off" fi return } # 處理 tiny shell 內(nèi)置命令.對(duì)于內(nèi)置命令,會(huì)調(diào)用對(duì)應(yīng)函數(shù)進(jìn)行處理. # 該函數(shù)的返回值表示所給命令名是否內(nèi)置命令. # 返回 0, 表示是內(nèi)置命令. 返回 1, 表示不是內(nèi)置命令. execute_builtin_command() { # 在傳遞過(guò)來(lái)的參數(shù)中,第一個(gè)參數(shù)是命令名,剩余的參數(shù)是該命令的參數(shù). local cmdname="$1" # 從 BUILTIN_COMMAND 數(shù)組中獲取所給命令對(duì)應(yīng)的處理函數(shù). # 如果所給命令不是內(nèi)置命令,會(huì)獲取為空. local cmdfunc="${BUILTIN_COMMAND["${cmdname}"]}" if [ -n "${cmdfunc}" ]; then # 將位置參數(shù)左移一位,移除命令名,剩下的就是該命令的參數(shù). shift 1 ${cmdfunc} "$@" # 無(wú)論執(zhí)行內(nèi)置命令是否報(bào)錯(cuò),都會(huì)返回 0,表示該命令是內(nèi)置命令. return 0 else return 1 fi } # 處理 tiny shell 的命令簡(jiǎn)寫.在所解析的配置文件中包含了支持的命令簡(jiǎn)寫. # 該函數(shù)的返回值表示所給命令名是否命令簡(jiǎn)寫. # 返回 0, 表示是命令簡(jiǎn)寫. 返回 1, 表示不是命令簡(jiǎn)寫. execute_short_command() { # 判斷所給的參數(shù)是否對(duì)應(yīng)配置文件中的某個(gè)鍵名.如果是,將取出鍵值. local key="$1" # 從配置文件中獲取所給命令簡(jiǎn)寫對(duì)應(yīng)要執(zhí)行的命令 local cmd_value=$(get_value_by_key "${key}") if test -n "${cmd_value}"; then # 將位置參數(shù)左移一位,移除命令簡(jiǎn)寫,剩下的就是命令的參數(shù). shift 1 # 下面要用 "$*" 來(lái)把所有參數(shù)組合成一個(gè)參數(shù),再跟命令內(nèi)容一起傳入 # bach -c,確保 bash -c 把命令內(nèi)容和所有參數(shù)都當(dāng)成要執(zhí)行的命令 bash -c "$cmd_value $*" # 打印命令簡(jiǎn)寫,以及該簡(jiǎn)寫對(duì)應(yīng)的命令,以便查看具體執(zhí)行了什么命令. # 先執(zhí)行命令,再打印命令內(nèi)容. 由于有些命令的輸出很多,先打印命令 # 內(nèi)容的話,需要拉動(dòng)終端滾動(dòng)條,才能找到打印的命令內(nèi)容,不便于查看. echo -e "\e[33m命令簡(jiǎn)寫: ${key}. 命令: ${cmd_value} $*\e[0m" return 0 else # 如果獲取到的鍵值為空,表示所給鍵名不是有效的命令簡(jiǎn)寫,返回 1 return 1 fi } # 處理所給的內(nèi)容.這個(gè)內(nèi)容可能是內(nèi)置命令,命令簡(jiǎn)寫,或者命令本身. handle_input_command() { # 所給參數(shù)是要執(zhí)行的命令名、以及命令參數(shù). 如果命令名是配置的 # 命令簡(jiǎn)寫,會(huì)把該命令簡(jiǎn)寫替換成對(duì)應(yīng)的命令,再進(jìn)行對(duì)應(yīng)的命令. local inputcmd="$@" # if 語(yǔ)句可以直接判斷命令返回值是否為 0,并不是只能搭配 [ 命令使用. # 注意: 由于有的 tiny shell 內(nèi)置命令接收參數(shù),下面的 ${cmd_line} # 不能用雙引號(hào)括起來(lái),否則多個(gè)參數(shù)會(huì)被當(dāng)成一個(gè)參數(shù). if execute_builtin_command ${inputcmd}; then # 先調(diào)用 execute_builtin_command 函數(shù)處理內(nèi)置命令.如果所給 # 命令是內(nèi)置命令,則調(diào)用對(duì)應(yīng)的函數(shù)進(jìn)行處理,且不再往下執(zhí)行. return 0 elif execute_short_command ${inputcmd}; then # 調(diào)用 execute_short_command 函數(shù)處理命令簡(jiǎn)寫. return 0 else # 對(duì)于 tiny shell 不能執(zhí)行的命令,嘗試用 bash -c 在 bash 中執(zhí)行. bash -c "${inputcmd}" # 當(dāng) return 命令不加具體狀態(tài)碼時(shí),它會(huì)返回上一條執(zhí)行命令的狀態(tài)碼. return fi } # SIGINT 信號(hào)的處理函數(shù).目前不做特殊處理,只是想在輸入CTRL-C后,不會(huì)終止 # 當(dāng)前 tiny shell. 輸入 CTRL-C 還是可以終止 tiny shell 啟動(dòng)的子 shell. sigint_handler() { # 當(dāng)輸入 CTRL-C 后,終端只顯示"^C",但是不會(huì)自動(dòng)換行,需要輸入回車才會(huì) # 換行,并重新輸出提示字符串. 而在交互式Bash中,輸入"^C"后,就會(huì)自動(dòng)回 # 車,并輸出提示字符串.這里模仿這個(gè)行為,先輸出一個(gè)回車,再輸出提示符. printf "\n${PROMPT}" } # 啟動(dòng) tiny shell 解釋器. 從標(biāo)準(zhǔn)輸入不停讀取、并執(zhí)行所給命令.直到 # 使用 CTRL-D 輸入 EOF 為止, 或者輸入 quit 命令退出當(dāng)前解釋器. start_tinyshell() { # 執(zhí)行 python 命令,默認(rèn)會(huì)打印 python 版本號(hào)和一句幫助提示. # 這里仿照這個(gè)行為,打印 tiny shel 版本號(hào)和一句幫助提示. echo -e "Tiny shell 1.0.0\nType 'help' for more information." # 捕獲SIGINT信號(hào),以便輸入 CTRL-C 后,不會(huì)退出當(dāng)前的 tiny shell. # 注意: 由于子shell會(huì)繼承父shell所忽略的信號(hào),所以不能將 SIGINT 信號(hào) # 設(shè)成忽略,而是要指定一個(gè)處理函數(shù). 當(dāng)前 shell 所捕獲的信號(hào)不會(huì)被 # 子 shell 繼承. 所以子 shell 還是可以被 CTRL-C 終止. 即,指定信號(hào)處理 # 函數(shù)后,當(dāng)前 tiny shell 不會(huì)被CTRL-C終止.但是當(dāng)前 tiny shell 執(zhí)行的 # 命令會(huì)運(yùn)行在子 shell 下,可以用 CTRL-C 終止運(yùn)行在子 shell 下的命令. # 查看 man bash 對(duì)子 shell 的信號(hào)繼承關(guān)系說(shuō)明如下: # traps caught by the shell are reset to the values inherited from # the shell's parent, and traps ignored by the shell are ignored trap "sigint_handler" SIGINT # 如果不使用 -e 選項(xiàng),輸入上光標(biāo)鍵, read 會(huì)讀取到 "^[[A";輸入下光標(biāo)鍵, # read 會(huì)讀取到 "^[[B".而使用 -e 選項(xiàng)后,輸入上下光標(biāo)鍵,不會(huì)讀取到亂碼, # 但是在子shell中,也不會(huì)返回歷史命令.因?yàn)閟hell腳本是在非交互模式下執(zhí)行. # 可以使用 bash 的 -i 選項(xiàng)讓腳本在交互模式下運(yùn)行,例如: "#/bin/bash -i" while read -ep "${PROMPT}" input; do # 傳遞參數(shù)給函數(shù)時(shí),參數(shù)要用雙引號(hào)括起來(lái),避免參數(shù)帶有空格時(shí),會(huì)拆分 # 成多個(gè)參數(shù). 當(dāng)輸入CTRL-C時(shí), tiny shell 捕獲了這個(gè)信號(hào),不會(huì)退出 # 當(dāng)前的 tiny shell.但是read命令會(huì)被中斷,此時(shí)讀取到的 input 為空. # 不需要對(duì)空行做處理,所以下面先判斷 input 變量值是否為空. if [ -n "${input}" ]; then handle_input_command "${input}" # 執(zhí)行 history -s 命令把所給的參數(shù)添加到當(dāng)前歷史記錄中.后續(xù) # 通過(guò)上下光標(biāo)鍵獲取歷史命令,就可以獲取到新添加的命令.這個(gè)只 # 影響當(dāng)前 tiny shell 的歷史記錄,不會(huì)寫入外部shell的歷史記錄. history -s "${input}" fi done # 輸出一個(gè)換行.當(dāng)用戶輸入CTRL-D結(jié)束執(zhí)行后,需要換行顯示原先的終端提示符. echo } # 循環(huán)調(diào)用 getopts 命令處理選項(xiàng)參數(shù). while getopts "hlvi:ea:d:" opt; do # 調(diào)用parsecfg.sh腳本處理選項(xiàng)的函數(shù)來(lái)處理 "lvi:ea:d:" 這幾個(gè)選項(xiàng). # 如果處理成功,就直接繼續(xù)讀取下一個(gè)選項(xiàng),不再往下處理. # handle_config_option()函數(shù)要求傳入的選項(xiàng)以'-'開(kāi)頭,而getopts命令 # 返回的選項(xiàng)不帶有'-',所以下面在 ${opt} 前面加上一個(gè) '-'. handle_config_option "-${opt}" "${OPTARG}" if [ $? -ne 127 ]; then continue fi case "$opt" in h) show_help ;; ?) echo "出錯(cuò): 異常選項(xiàng),請(qǐng)使用 -h 選項(xiàng)查看腳本的幫助說(shuō)明." ;; esac done # $# 大于0,說(shuō)明提供了命令參數(shù). $# 等于OPTIND減去1,說(shuō)明傳入的參數(shù)都 # 是以 '-' 開(kāi)頭的選項(xiàng)參數(shù). 此時(shí),直接結(jié)束執(zhí)行,不需要再往下處理. # 下面的 -a 表示兩個(gè)表達(dá)式都為真時(shí)才為真.表達(dá)式之間不要加小括號(hào). # Shell里面的小括號(hào)有特殊含義,跟C語(yǔ)言的小括號(hào)有些區(qū)別,加上會(huì)有問(wèn)題. if [ $# -gt 0 -a $# -eq $((OPTIND-1)) ]; then exit 0 fi if [ $# -eq 0 ]; then # 當(dāng)不帶任何參數(shù)時(shí),默認(rèn)啟用 tiny shell. start_tinyshell else # 左移所給的命令參數(shù),去掉已處理過(guò)的選項(xiàng)參數(shù),只剩下非選項(xiàng)參數(shù). shift $((OPTIND-1)) # 執(zhí)行腳本時(shí),如果提供了非選項(xiàng)參數(shù),那么第一個(gè)參數(shù)認(rèn)為是命令簡(jiǎn)寫, # 需要執(zhí)行該命令簡(jiǎn)寫對(duì)應(yīng)的命令. 第一個(gè)參數(shù)之后的所有參數(shù)認(rèn)為是 # 命令的參數(shù). 即,可以在命令簡(jiǎn)寫之后提供參數(shù)來(lái)動(dòng)態(tài)指定一些操作. execute_short_command "$@" fi exit
代碼關(guān)鍵點(diǎn)說(shuō)明
使用 trap 命令捕獲信號(hào)
在 bash 中,可以使用 trap 命令捕獲信號(hào),并指定信號(hào)處理函數(shù)。
捕獲信號(hào)后,可以避免收到某個(gè)信號(hào)終止腳本執(zhí)行。
當(dāng)前 tinyshell.sh 腳本使用 trap 命令捕獲 SIGINT 信號(hào)。
也就是 CTRL-C 鍵所發(fā)送的信號(hào),避免按 CTRL-C 鍵會(huì)退出當(dāng)前 tiny shell。
要注意的是,不能設(shè)置成忽略 SIGINT 信號(hào)。
在 bash 中,父 shell 所忽略的信號(hào),也會(huì)被子 shell 所忽略。
除了內(nèi)置命令之外,當(dāng)前 tiny shell 所執(zhí)行的命令運(yùn)行在子 shell 下。
如果設(shè)置成忽略 SIGINT 信號(hào),那么子 shell 也會(huì)忽略這個(gè)信號(hào)。
那么就不能用 CTRL-C 來(lái)終止子 shell 命令的執(zhí)行。
例如,Android 系統(tǒng)的 adb logcat 命令會(huì)不停打印 log,需要按 CTRL-C 來(lái)終止。
此時(shí),在 tiny shell 里面按 CTRL-C 就不能終止 adb logcat 的執(zhí)行。
父 shell 所捕獲的信號(hào),子 shell 不會(huì)繼承父 shell 所捕獲的信號(hào)。
子 shell 會(huì)繼承父 shell 的父進(jìn)程的信號(hào)狀態(tài)。
父 shell 的父進(jìn)程一般是外部 bash shell 進(jìn)程。
而 bash shell 進(jìn)程默認(rèn)捕獲SIGINT并終止前臺(tái)進(jìn)程。
即,雖然當(dāng)前 tiny shell 捕獲了 SIGINT 信號(hào),但是子 shell 并沒(méi)有捕獲該信號(hào)。
可以在 tiny shell 使用 CTRL-C 來(lái)終止子 shell 命令的執(zhí)行。
使用 history -s 命令添加歷史記錄
在 tiny shell 執(zhí)行命令后,默認(rèn)不能用上下光標(biāo)鍵查找到 tiny shell 自身執(zhí)行的歷史命令。
為了可以查找到 tiny shell 自身執(zhí)行的歷史命令,使用 history -s 命令添加命令到當(dāng)前 shell 的歷史記錄。
這個(gè)命令只會(huì)影響當(dāng)前 shell 的歷史記錄。
退出當(dāng)前 shell 后,在外部 shell 還是看不到 tiny shell 所執(zhí)行的命令。
由于這個(gè) tiny shell 主要是為了執(zhí)行命令簡(jiǎn)寫。
這些命令簡(jiǎn)寫只有 tiny shell 自身支持,不需要添加到 bash shell 的歷史記錄。
如果想要命令歷史信息添加到外部 shell 的歷史記錄,可以在退出 tinyshell.sh 腳本之前,執(zhí)行 history -w ~/.bash_history 命令把歷史記錄寫入到 bash 自身的歷史記錄文件。
測(cè)試?yán)?br />
把 tinyshell.sh 腳本放到 PATH 變量指定的可尋址目錄下。
查看 tinyshell.sh 腳本代碼,可知要解析的配置文件名是 tinyshellcmds.txt。
把前面貼出的命令簡(jiǎn)寫配置信息寫入 tinyshellcmds.txt 文件。
把這個(gè)文件放到 HOME 目錄的 .liconfig 目錄下。
之后,就可以開(kāi)始執(zhí)行 tinyshell.sh 腳本。
當(dāng)前的 tinyshell.sh 腳本可以執(zhí)行內(nèi)置命令、命令簡(jiǎn)寫對(duì)應(yīng)的命令、系統(tǒng)自身支持的命令。
當(dāng)不提供任何命令參數(shù)時(shí),會(huì)進(jìn)入 tiny shell。
在 tiny shell 中,會(huì)不停接收用戶輸入并執(zhí)行對(duì)應(yīng)命令。
直到讀取到 EOF 、或者執(zhí)行 quit 命令才會(huì)退出 tiny shell。
處理選項(xiàng)參數(shù)和直接處理命令簡(jiǎn)寫的例子
下面是不進(jìn)入 tiny shell,只處理選項(xiàng)參數(shù)和命令簡(jiǎn)寫的例子:
$ tinyshell.sh -v key='gl' value='git log' key='gp' value='git pull --stat --no-tags $(git remote) $(git rev-parse --abbrev-ref HEAD)' key='ll' value='ls --color=auto -l' key='ala' value='adb logcat -b all -v threadtime' $ tinyshell.sh ll -rwxrwxr-x 1 xxx xxx 964 11月 14 17:37 tinyshell.sh 命令簡(jiǎn)寫: ll. 命令: ls --color=auto -l
這里先執(zhí)行 tinyshell.sh -v 命令,用鍵值對(duì)的形式列出支持的命令簡(jiǎn)寫。
此時(shí),只處理所給的選項(xiàng)參數(shù),不會(huì)進(jìn)入 tiny shell 里面。
tinyshell.sh ll 命令,提供了一個(gè) ll 參數(shù)(兩個(gè)小寫字母 l)。
這個(gè)參數(shù)會(huì)被當(dāng)成命令簡(jiǎn)寫,然后執(zhí)行該命令簡(jiǎn)寫對(duì)應(yīng)的命令。
執(zhí)行結(jié)束后,不會(huì)進(jìn)入 tiny shell 里面。
基于剛才列出的命令簡(jiǎn)寫,可知 ll 對(duì)應(yīng) ls --color=auto -l 命令。
實(shí)際執(zhí)行的也是這個(gè)命令。
進(jìn)入 tiny shell 循環(huán)處理命令的例子
當(dāng)不提供任何命令參數(shù)時(shí),會(huì)進(jìn)入 tiny shell 里面,循環(huán)處理命令。
具體例子如下所示:
$ tinyshell.sh Tiny shell 1.0.0 Type 'help' for more information. TinySh>>> help 下面列出 Tiny Shell 支持的內(nèi)置命令列表和配置的命令簡(jiǎn)寫列表. 輸入內(nèi)置命令名或命令簡(jiǎn)寫,會(huì)執(zhí)行對(duì)應(yīng)的命令. 也可以輸入系統(tǒng)自身支持的命令,會(huì)在 bash 中執(zhí)行所給命令. 內(nèi)置命令列表: debug: 所給第一個(gè)參數(shù)指定打開(kāi)、或關(guān)閉調(diào)試功能. 其參數(shù)說(shuō)明如下: on: 打開(kāi)調(diào)試功能,會(huì)執(zhí)行 bash 的 set -x 命令 off: 關(guān)閉調(diào)試功能,會(huì)執(zhí)行 bash 的 set +x 命令 help: 打印當(dāng)前幫助信息. quit: 退出當(dāng)前 Tiny Shell. 命令簡(jiǎn)寫列表: key='gl' value='git log' key='gp' value='git pull --stat --no-tags $(git remote) $(git rev-parse --abbrev-ref HEAD)' key='ll' value='ls --color=auto -l' key='ala' value='adb logcat -b all -v threadtime' TinySh>>> date 2019年 12月 31日 星期二 17:46:41 CST TinySh>>> ll -C tinyshell.sh 命令簡(jiǎn)寫: ll. 命令: ls --color=auto -l -C
當(dāng)執(zhí)行 tinyshell.sh 命令會(huì)進(jìn)入 tiny shell 時(shí),會(huì)打印一個(gè) “TinySh>>>” 提示符。
在 tiny shell 中執(zhí)行 help 命令可以查看支持的內(nèi)置命令和命令簡(jiǎn)寫。
在 tiny shell 中執(zhí)行 date 命令打印當(dāng)前的日期和時(shí)間。
當(dāng)前的 tiny shell 自身不支持 date 命令。
這里執(zhí)行了系統(tǒng)自身的 date 命令。
最后執(zhí)行 ll -C 命令。
這里的 ll 是命令簡(jiǎn)寫。后面的 -C 是對(duì)應(yīng)命令的參數(shù)。
具體執(zhí)行的命令是 ls --color=auto -l -C。
ls 命令的 -C 選項(xiàng)會(huì)多列顯示文件名,覆蓋了 -l 選項(xiàng)的效果。
由于 -l 選項(xiàng)的效果被覆蓋,輸出結(jié)果沒(méi)有打印文件的詳細(xì)信息,只列出文件名。
可以看到,在命令簡(jiǎn)寫之后,可以再提供其他的命令參數(shù)。
即,可以只配置比較長(zhǎng)的命令前綴部分,一些簡(jiǎn)單的參數(shù)可以動(dòng)態(tài)提供。
不需要在配置文件中添加很多內(nèi)容相似、只有細(xì)微差異的配置項(xiàng)。
以上就是分享一個(gè)可以通過(guò)命令簡(jiǎn)寫執(zhí)行對(duì)應(yīng)命令的Shell腳本的詳細(xì)內(nèi)容,更多關(guān)于命令簡(jiǎn)寫執(zhí)行對(duì)應(yīng)命令的Shell腳本的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 監(jiān)控MySQL主從狀態(tài)的shell腳本
- shell腳本使用兩個(gè)橫杠接收外部參數(shù)的方法
- 使用Shell腳本如何啟動(dòng)/停止Java的jar程序
- Shell中使用grep、sed正則提取和替換字符串
- Shell eval通過(guò)變量獲取環(huán)境變量的方法實(shí)現(xiàn)
- shell腳本實(shí)戰(zhàn)-while循環(huán)語(yǔ)句
- shell腳本--sed的用法詳解
- linux shell中 if else以及大于、小于、等于邏輯表達(dá)式介紹
- Linux中執(zhí)行shell腳本的4種方法總結(jié)
- 一個(gè)不錯(cuò)的shell 腳本教程 入門級(jí)
- Shell字符串比較相等、不相等方法小結(jié)
- python中執(zhí)行shell命令的幾個(gè)方法小結(jié)
相關(guān)文章
統(tǒng)計(jì)網(wǎng)卡流量的兩段shell腳本(使用ifconfig)
一個(gè)很小巧的shell腳本,使用ifconfig的不間斷輸出來(lái)統(tǒng)計(jì)網(wǎng)卡的流量,有需要的朋友可以參考下2013-02-02如何實(shí)現(xiàn)ls命令在Win7下正常運(yùn)行
ls命令是Linux系統(tǒng)下最常用的命令之一,使用ls指令可列出目錄中的內(nèi)容,包括文件和子目錄的名稱,下面通過(guò)本文給大家分享如何實(shí)現(xiàn)ls命令在Win7下正常運(yùn)行,需要的朋友參考下吧2018-03-03linux 中more、less 和 most 的區(qū)別
more 是一個(gè)老式的、基礎(chǔ)的終端分頁(yè)閱讀器,它可以用于打開(kāi)指定的文件并進(jìn)行交互式閱讀。這篇文章主要給大家介紹linux 中more、less 和 most 的區(qū)別,感興趣的朋友跟隨小編一起看看吧2018-11-11linux whatis與whatis database 使用及查詢方法(man使用實(shí)例)
在學(xué)習(xí)man命令時(shí)候,估計(jì)很多朋友都發(fā)現(xiàn)有man –f ,man –k 參數(shù),可以查出很多數(shù)據(jù)。這些有的與man手冊(cè)頁(yè)相同,有些不是屬于手冊(cè)頁(yè)的。它們數(shù)據(jù)怎么收集來(lái)的,并且whatis是怎么樣工作的2015-10-10Shell實(shí)現(xiàn)多級(jí)菜單系統(tǒng)安裝維護(hù)腳本實(shí)例分享
這篇文章主要介紹了Shell實(shí)現(xiàn)多級(jí)菜單系統(tǒng)安裝維護(hù)腳本實(shí)例分享,本文腳本用多級(jí)菜單實(shí)現(xiàn)管理WEB服務(wù)器、Mysql服務(wù)器、Nginx服器等,需要的朋友可以參考下2014-12-12