理解shell

shell是一个程序,程序加载后启动一个shell进程,以命令行提示符的形式跟用户交互, shell不单单是一种CLI。它是一个时刻都在运行的复杂交互式程序

shell的类型

系统启动什么样的shell程序取决于你个人的用户ID配置 , 在/etc/passwd文件中,在用户ID记 录的第7个字段中列出了默认的shell程序 ,例:

root:x:0:0:root:/root:/bin/bash

7 个字段的对应关系如下:

  • 登录名:登录系统时,用户所必须输入的唯一名称
  • 经过加密的密码:该字段包含的是经过加密处理的密码,长度为 13 个字符 ,这里显示字母“x”, 而经过加密处理的密码实际上却存储到 shadow 密码文件中
  • 用户 ID(UID) : 用户的数值型 ID
  • 组 ID(GID):用户属组中首选属组的数值型 ID。
  • 注释:该字段存放关于用户的描述性文字
  • 主目录:用户登录后所处的初始路径。
  • 登录 shell:一旦用户登录,便交由该程序控制。

在Linux系统上,通常有好几种Linux shell可用 ,不同的shell有不同的特性,有些更利于创建脚本,有些则更利于管理进程。如下:

  • ash 一种运行在内存受限环境中简单的轻量级shell,但与bash shell完全兼容
  • korn 一种与Bourne shell兼容的编程shell,但支持如关联数组和浮点运算等一些高级的编程特性
  • tcsh 一种将C语言中的一些元素引入到shell脚本中的shell
  • zsh 一种结合了bash、tcsh和korn的特性,同时提供高级编程特性、共享历史文件和主题化提示符的高级 shell

所有Linux发行版默认的shell都是bash shell , 你经常会看到某些发行版使用软链接将默认的系统shell设置成bash shell ,比如我电脑的CentOS发行版:

[root@help ~]#  ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Dec 14 23:41 /bin/sh -> bash

最左侧的l代表软连接

外部命令&内建命令

[root@help ~]# type cd

cd is a shell builtin

[root@help ~]# type ps

ps is hashed (/usr/bin/ps)

注:cd就是内建命令,而ps是外部命令,那有什么区别呢

外建命令:有时候也被称为文件系统命令,是存在于bash shell之外的程序 , 当外部命令执行时,会创建出一个子进程。这种操作被称为衍生(forking)。

内建命令:它们已经和shell编译成了一 体,作为shell工具的组成部分存在, 执行不会新建shell子进程。

shell的父子关系

用于登录某个虚拟控制器终端或在GUI中运行终端仿真器时所启动的默认的交互shell,是一 个父shell , 父shell提供CLI提示符,然后等待命令输入 。

在生成子shell进程时,只有部分父进程的环境被复制到子shell环境中。这会对包括变量在内的一些东西造成影响

[root@help /]# bash
[root@help /]# bash
[root@help /]# bash
[root@help /]# ps --forest
  PID TTY          TIME CMD
 14128 pts/6    00:00:00 bash
 3031 pts/6    00:00:00  \_ bash
 3046 pts/6    00:00:00      \_ bash
 3060 pts/6    00:00:00          \_ bash
 3108 pts/6    00:00:00              \_ ps

在上面的例子中,bash命令被输入了三次。这实际上创建了三个子shell。ps -forest命令 展示了这些子shell间的嵌套结构

进程列表

你可以在一行中指定要依次运行的一系列命令。这可以通过命令列表来实现,只需要在命令

之间加入分号(;)即可,要想知道是否生成了子shell,得借助一个使用了环境变量的命令echo $BASH_SUBSHELL。例:

[root@help /]# pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls ; echo $BASH_SUBSHELL
/
bin   dev  get-pip.py  lib    lost+found  mnt      opt   root  sbin  sys  usr
boot  etc  home        lib64  media       myredis  proc  run   srv   tmp  var
/etc
/root
:                 format_schemas               metadata_dropped                            status      yarn.lock
555.txt           FreebuyApplication           mysql-5.7.24-linux-glibc2.12-x86_64.tar.gz  store
data              iZwz9hegfy8iwwrwssss7kZ.pid  nacos                                       tmp
dictionaries_lib  logs                         node_modules                                user_files
flags             metadata                     preprocessed_configs                        work
0

在命令输出的最后,显示的是数字0。这就表明这些命令不是在子shell中运行的。

[root@help ~]#  (pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls ; echo $BASH_SUBSHELL)
/root
:                 format_schemas               metadata_dropped                            status      yarn.lock
555.txt           FreebuyApplication           mysql-5.7.24-linux-glibc2.12-x86_64.tar.gz  store
data              iZwz9hegfy8iwwrwssss7kZ.pid  nacos                                       tmp
dictionaries_lib  logs                         node_modules                                user_files
flags             metadata                     preprocessed_configs                        work
/etc
/root
:                 format_schemas               metadata_dropped                            status      yarn.lock
555.txt           FreebuyApplication           mysql-5.7.24-linux-glibc2.12-x86_64.tar.gz  store
data              iZwz9hegfy8iwwrwssss7kZ.pid  nacos                                       tmp
dictionaries_lib  logs                         node_modules                                user_files
flags             metadata                     preprocessed_configs                        work
1

这次在命令输入的最后显示出了数字1。这表明的确创建了子shell,并用于执行这些命令

别出心裁的子 shell 用法

在交互式的shell CLI中,还有很多更富有成效的子shell用法。进程列表、协程和管道都利用了子shell。

在交互式shell中,一个高效的子shell用法就是使用后台模式,

探索后台模式

什么是后台模式?

在后台模式中运行命令可以在处理命令的同时让出CLI,以供他用,演示后台模式的一个经

典命令就是sleep。

而要想将命令置入后台模式,可以在命令末尾加上字符&,把sleep命令置入后台模式可以让我

们利用ps命令来小窥一番。

[root@help ~]# sleep 20&
[1] 12995
[root@help ~]# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root     12920 12915  0 22:39 pts/9    00:00:00 -bash
root     12995 12920  0 22:39 pts/9    00:00:00 sleep 20
root     12998 12920  0 22:39 pts/9    00:00:00 ps -f

sleep命令会在后台(&)睡眠20秒,当它被置入后台,在shell CLI提示符返回

之前,会出现两条信息。第一条信息是显示在方括号中的后台作业(background job)号(1)。

第二条是后台作业的进程ID(12995)。除了ps命令,你也可以使用jobs命令来显示后台作业信息。

[root@help ~]# sleep 20&
[1] 13432
[root@help ~]# jobs -l
[1]+ 13432 Running                 sleep 20 &

一旦后台作业完成,就会显示出结束状态

[root@help ~]# jobs -l
[1]+ 13432 Done                    sleep 20

将进程列表置入后台

[root@help ~]# (sleep 2 ; echo $BASH_SUBSHELL ; sleep 2)

1

[root@help ~]#

在上面的例子中,有一个2秒钟的暂停,显示出的数字1表明只有一个子shell,在返回提示符

之前又经历了另一个2秒钟的暂停

将相同的进程列表置入后台模式会在命令输出上表现出些许不同

[root@help ~]#  (sleep 2 ; echo $BASH_SUBSHELL ; sleep 2)&
[1] 14349
[root@help ~]# 1

[1]+  Done                    ( sleep 2; echo $BASH_SUBSHELL; sleep 2 )
[root@help ~]#

把进程列表置入后台会产生一个作业号和进程ID,然后返回到提示符。不过奇怪的是表明单

一级子shell的数字1显示在了提示符的旁边!不要不知所措,只需要按一下回车键,就会得到另

一个提示符

在CLI中运用子shell的创造性方法之一就是将进程列表置入后台模式。你既可以在子shell中

进行繁重的处理工作,同时也不会让子shell的I/O受制于终端

当然了,sleep和echo命令的进程列表只是作为一个示例而已。使用tar(参见第4章)创

建备份文件是有效利用后台进程列表的一个更实用的例子。

[root@help ~]#  (tar -cf Rich.tar /home/rich ; tar -cf My.tar /home/christine)& 
[3] 2423 

将进程列表置入后台模式并不是子shell在CLI中仅有的创造性用法。协程就是另一种方法。

协程

协程可以同时做两件事。它在后台生成一个子shell,并在这个子shell中执行命令。

要进行协程处理,得使用coproc命令,还有要在子shell中执行的命令

[root@help ~]#  coproc sleep 10
[1] 15041

除了会创建子shell之外,协程基本上就是将命令置入后台模式。当输入coproc命令及其参

数之后,你会发现启用了一个后台作业。屏幕上会显示出后台作业号(1)以及进程ID(15041)。

jobs命令能够显示出协程的处理状态

[root@help ~]# jobs
[1]+  Done                    coproc COPROC sleep 10

在上面的例子中可以看到在子shell中执行的后台命令是coproc COPROC sleep 10

[root@help ~]#  coproc My_Job { sleep 10; }
[1] 15387
[root@help ~]# jobs
[1]+  Running                 coproc My_Job { sleep 10; } &

通过使用扩展语法,协程的名字被设置成My_Job。这里要注意的是,扩展语法写起来有点

麻烦。必须确保在第一个花括号({)和命令名之间有一个空格。还必须保证命令以分号(

;)结 尾。另外,分号和闭花括号(})之间也得有一个空格

你可以发挥才智,将协程与进程列表结合起来产生嵌套的子shel

[root@help ~]# coproc ( sleep 20; sleep 20 )
[1] 16547
[root@help ~]# jobs
[1]+  Running                 coproc COPROC ( sleep 20; sleep 20 ) &
[root@help ~]# ps --forest
  PID TTY          TIME CMD
12920 pts/9    00:00:00 bash
16547 pts/9    00:00:00  \_ bash
16599 pts/9    00:00:00  |   \_ sleep
16627 pts/9    00:00:00  \_ ps

生成子shell的成本不低,而且速度还慢。创建嵌套子shell更是火上浇油!

在命令行中使用子shell能够获得灵活性和便利。要想获得这些优势,重要的是理解子shell的

行为方式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值