在 mac OSX 系统下测试也不生效 。
这几种情况都是在 login shell 下运行,查看 readline 库的配置文件也没有看到异常,目前原因不明 。
可以改成用 source 命令执行脚本来避免这个异常 。具体如后面说明所示 。
通过 source 命令执行 shell 脚本通过 bash 的 source 内置命令执行 shell 脚本时,这个脚本运行在当前 bash shell 下,而不是启动一个子 shell 来执行脚本 。
由于当前 bash shell 是交互式,运行在该 bash shell 下的脚本也是交互式 。
此时,脚本开头的解释器不需要加 -i 选项,但 read 命令还是要加 -e 选项来指定用 readline 库读取输入 。
修改 tinyshell.sh 脚本内容如下:
#!/bin/bashwhile read -ep "tinyshell> " input; doif [ "$input" == "l" ]; thenlselif [ "$input" == "quit" ]; thenbreakelsebash -c "${input}"fidone这个脚本的改动点是:
- 脚本开头的解释器写为 #!/bin/bash,不需要加 -i 选项 。
- read 命令加了 -e 选项 。
- 对于不识别的输入,使用 bash -c 来执行所输入的内容,这样就可以执行外部的命令 。
$ source tinyshell.shtinyshell> ltinyshell.shtinyshell> echo "This is a tinyshell."This is a tinyshell.tinyshell> source tinyshell.shtinyshell> quittinyshell> quit$在执行的时候,先是手动输入 l 字符,该脚本会相应执行 ls 命令 。然后手动输入 echo "This is a tinyshell.",该脚本使用 bash -c 来执行这个命令,打印出 This is a tinyshell. 。
接着输入上光标键,出现上一个历史命令,显示当前正在执行的 source tinyshell.sh 命令 。
回车之后会再次执行这个脚本 。
可以看到,需要手动输入两次 quit,才退出这两次执行 。
上面提到,在 Windows 下通过 ssh 远程登录到 Ubuntu 系统,在远程 Ununtu 系统下,使用 bash 的 -i 选项来执行脚本,read -e 也不能通过上下光标键来获取历史命令 。
此时,通过 source 命令执行脚本,read -e 命令能通过上下光标键来获取历史命令 。
即,通过 bash 的 -i 选项来执行脚本,可能会受到子 shell 环境配置的影响,导致 read -e 命令不能通过上下光标键来获取历史 。
而通过 source 命令来执行脚本,直接运行在当前 bash shell 下,可以避免子 shell 环境配置的影响,兼容性较强 。
注意:通过 source 命令执行脚本时,脚本内不能执行 exit 命令,否则不但会退出脚本执行,还会退出所在的 bash shell 。
把脚本自身执行的命令添加到当前历史记录在前面的脚本代码中,无论是通过 bash 的 -i 选项来执行脚本,还是通过 source 命令来执行脚本,这两种方式有一个共同的问题:虽然可以使用上下光标键查找历史命令,但找不到脚本自身所执行的命令 。
例如输入 l 字符,tinyshell.sh 脚本执行了 ls 命令 。
通过上光标键还是只能查找到执行脚本之前的历史命令,查找不到输入的 l 字符,也找不到脚本所执行的 ls 命令,就像是这个脚本的命令没有加入到历史记录 。
如果想在执行脚本时,可以使用上下光标键查找到脚本自身执行的命令,可以使用 history -s 命令 。
在上面 while 循环的末尾添加下面的语句,新增的代码前面用 + 来标识:
elsebash -c "${input}"fi+history -s "${input}"done添加 history -s "${input}" 语句后,就能通过上下光标键找到 input 变量指定的命令 。例如输入 l 字符,tinyshell.sh 脚本执行了 ls 命令 。
而 input 变量保存的是 l 字符,能够通过上下光标键找到 l 命令,找不到 ls 命令 。
查看 man bash 对 history 内置命令的 -s 选项说明如下:
history -s arg [arg ...]即,history -s 命令把所给的参数添加到当前历史记录中 。
-s: Store the args in the history list as a single entry.
后续通过上下光标键获取历史命令,就可以获取到新添加的命令 。
从文件中逐行读取命令并执行既然是模拟一个简易的 shell 效果,当然要具有执行脚本文件的能力 。
我们可以通过重定向用 read 命令逐行读取文件内容,然后执行每一行的命令 。一段示例代码如下:
while read line; doecho $linedone < filename这段代码会逐行读取 fliename 这个文件的内容,读取到最后一行 (EOF) 就会退出 while 循环 。参考这段代码,对 tinyshell.sh 脚本修改如下:
#!/bin/bash -iif [ $# -ne 0 ]; thenfilename="$1"elsefilename="/dev/stdin"fiwhile read -ep "tinyshell> " input; doif [ "$input" == "l" ]; thenlselif [ "$input" == "quit" ]; thenbreakelsebash -c "$input"fidone < "$filename"
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 完整版 Linux技巧:使用 bash function 命令自定义函数
- 如何在 Mac 上使用 pyenv 运行多个版本的 Python | Linux 中国
- 公司来位腾讯大牛,看完我构建的Spring MVC框架,甩给我一份文档
- Linux这5款微型发行版,体积小+精简,比win7运行还快,值得安装
- Linux磁盘管理超详细
- 手把手教你安装Windows 10之完整篇
- 吃完东西就犯困?科学家解释其中原因
- 看完胎压标示图后不知道如何充气了
- 5 种拆分 Linux 终端的方法
- Linux下查看进程线程数的方法
