三、理解shell

作者: Miridescent | 来源:发表于2017-08-11 16:58 被阅读634次

    前面两节学习了一些shell的基本命令,但是我们并不知道shell进程的具体,本节学习一下

    命令 作用
    echo 显示
    bash 启用一个子bash shell
    exit 退出当前进程
    sleep 进程睡眠
    jobs 显示当前运行在后台模式的所有用户的进程
    type 判断是否是内建命令
    history 输出你输入过的命令
    alias 给已有的内建命令重新命名

    1.shell类型

    先来说下shell是什么,shell是Linux/Unix的一个外壳,Linux/Unix通过shell与内核交互,shell接收用户或程序的命令进而转化成内核明白的命令,内核完成任务后再返回有用的信息给用户或者程序
    为什么shell会有多种类型,因为有的程序员用着别人的shell不爽,就自己写了一个shell
    输入cat /etc/shells命令就可以查看你电脑上安装了那些shell,我的电脑有这些

    # List of acceptable shells for chpass(1).
    # Ftpd will not allow users to connect who are not using
    # one of these shells.
    
    /bin/bash
    /bin/csh
    /bin/ksh
    /bin/sh
    /bin/tcsh
    /bin/zsh
    

    输入echo $SHELL可以查看你电脑默认启动的是那种shell,我的是zsh

    /bin/zsh
    

    至于默认shell的配置,自己百度

    这里极力为大家推荐zsh,GitHub地址github.com/robbyrussell/oh-my-zsh,zsh兼容bash,并提供更多更牛X的功能,大家自行下载安装

    除了打开终端和我们交互的默认shell,系统还有一个默认的shell是/bin/sh,用于那些需要在启动时使用的系统shell脚本

    *注意 当我们自己写bash shell脚本的时候,对于有两个默认的shell(默认交互shell和默认系统shell)会有问题,后面会介绍脚本首行的语法要求,避免这个问题
    *注意 这一些列的学习都是基于bash而不是zsh

    2.shell的父子关系

    shell关系
    通过实际例子了解
    打开一个终端,输入命令ps -f,会得到如下的输出

    ➜  ~ ps -f
      UID   PID  PPID   C STIME   TTY           TIME CMD
      501   392   292   0 一10上午 ttys000    0:00.07 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server /usr/bin/login -fpl musong /Applications/iTerm.app/Contents/MacOS/iTerm2 --launch_shell
      501   394   393   0 一10上午 ttys000    0:02.32 -zsh
    

    看到有两个进程,一个是命令行ps -f启用的进程,一个是默认进程zsh
    这里再解释一下,楼主默认启动的是zsh,还有楼主用的是iTerm工具,可能会和系统命令行不一样

    再输入命令bash,会得到如下输出

    bash-3.2$
    

    此时启用了一个子bash shell

    再输入命令ps -f,会得到如下输出

    UID   PID  PPID   C STIME   TTY           TIME CMD
      501   392   292   0 一10上午 ttys000    0:00.07 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server /usr/bin/login -fpl musong /Applications/iTerm.app/Contents/MacOS/iTerm2 --launch_shell
      501   394   393   0 一10上午 ttys000    0:02.32 -zsh
      501 34915   394   0 11:49上午 ttys000    0:00.01 bash
    

    注意观察最后两行的PID(进程编号)、PPID(父进程编号),可能到这里大家已经理解子shell和父shell的关系了
    在上面的例子中,父shell是zsh,PID是394,子shell是bash,PID是34915,PPID是394

    *注意 各种shell之间可互相创建子shell
    *注意 这样的层级关系可以有多层,子shell还可以有子shell
    *注意 退出当前进程,用命令exit

    另外可以通过参数修改shell的启动方式,这里只简单的介绍一下,暂时不会涉及具体问题

    参数 描述
    -c string 从string中读取命令进行处理
    -i 启动一个能够接受用户输入的交互shell
    -l 以登录shell的形式启动
    -r 启动一个受限shell,用户会被限制在默认目录中
    -s 从标准输入中读取命令

    *注意 可以通过命令man bashbash --help了解更多帮助信息

    进程列表

    在一行指令之中一次运行一系列的命令
    例: pwd ; ls ; cd /etc

    将命令列表变成进程列表(实际上就是生成一个子shell去执行这些命令)
    例:(pwd ; ls ; cd /etc)
    *注意 查看一个shell是否有子shell用命令echo $BASH_SUBSHELL
    *注意 echo $BASH_SUBSHELL是bash的命令,在zsh下是echo $ZSH_SUBSHELL
    *注意 进程列表实际上是一种命令分组
    *注意 另一种分组方法是{},上面的例子等价于{pwd ; ls ; cd /etc},但是不同的是{}没有生成子shell
    *注意 命令分组可以嵌套使用例如:(pwd ;( ls ; cd /etc)),这样会生成两个子shell
    *注意 即使生成子shell也并不一定真正的是多进程处理

    子shell的经典用法

    了解后台模式
    即将任务放到后台处理,不影响其他的操作

    例:输入命令sleep 10 命令的作用是希望进程睡眠10秒
    回车后发现,进程进入睡眠,同时光标也没有了,无法进行任何操作

    例:输入命令sleep 10& &作用是将命令置入后台模式
    回车后发现,控制台提示

    [1] 36482
    

    [1]是后台作业编号,36482是进程ID(PID)
    光标还在,也可以进行其他操作
    10秒后,控制台突然弹出提示

    [1]  + 36482 done       sleep 10
    

    *注意 ps命令也可查看后台进程
    *注意 jobs命令可以显示当前运行在后台模式的所有用户的进程
    *注意 jobs -l命令可以显示更多关于进程的相关信息
    例:当有后台进程的时候输入jobs -l命令,会看到下面的输出

    [1]  + 36725 running    ( sleep 20; )
    

    [1]是后台作业编号,36725是进程ID(PID),running表示状态,( sleep 20; )子shell执行的命令

    *注意 后台进程结束后会突然出现在控制台上,而不是在合适的时候显示

    如何将进程列表置入后台模式,很简单,只要在()外加上&即可
    例:(pwd ; ls ; cd /etc)&

    协程 coproc
    可以同时做两件事,在后台生成一个子shell,并在这个子shell中执行命令
    例:coproc sleep 5 生成子shell并在子shell中执行sleep 5

    *注意 不知道为什么在bash-3.2环境下不支持 coproc命令,在zsh下就没有问题,还请指教

    3.理解shell的内建命令

    先来区分下内建命令和外建(外部)命令

    外部命令
    先来做一个操作ls /bin,控制台的输出结果是

    [          cat        cp         date       df         echo       expr       kill       launchctl  ln         mkdir      pax        pwd        rmdir      sleep      sync       test       wait4path
    bash       chmod      csh        dd         domainname ed         hostname   ksh        link       ls         mv         ps         rm         sh         stty       tcsh       unlink     zsh
    

    这些都是外部命令
    *注意 这些命令通常位于/bin、/usr/bin、/sbin或/usr/sbin中

    外部命令执行时,通常会创建子进程,称为“衍生”,例如ps命令,就是一个外部命令,可自行试验一下

    内建命令

    和外键命令最大的区别就是内建命令不需要子进程来执行,这就很容易理解内建命令比外键命令的优势

    例如:cdexit都是内建命令
    可以用type命令判断是否是内建命令
    例如:type cd 输出的结果是

    cd is a shell builtin
    

    这是一个bash内建命令和保留字的列表bash内建命令和保留字

    有一些命令既是内建命令也是外键命令,例如pwdecho,可以用type -a查看
    例:type -a echo 控制台输出结果

    echo is a shell builtin
    echo is /bin/echo
    

    *注意 witch命令可以显示外键命令
    *注意 通常使用的基本都是内建命令,如果想特意使用外键命令只要直接指明对应的文件即可,例如:/bin/pwd 使用外键pwd命令

    介绍一个命令history
    history命令会在控制台输出你输入过的命令
    !!命令可以呼出你上一条输入的命令
    *注意 !!基本用不到,现在的控制台基本都支持上下键呼出输入过的命令,方便快捷
    !10 命令会呼出编号为10的历史记录
    *注意 命令历史记录会保存在隐藏文件.bash_history中,每次shell退出时,使用过的命令会写入.bash_history中
    *注意 如果在没退出shell的时候想强制写入,可以用命令history -a

    命令别名 alias

    给已有的内建命令从新起个名字,有许多我们常用的命令已经是别名,zsh中可以用alias查看

    alias用法 alias li='ls -li' 即将ls -li命令命名为li
    *注意 不建议自己更改过多的名字
    *注意 更改过的名字在他被定义的shell中才有用
    *注意 更改过的名字在shell脚本中也可用

    下一篇会介绍如果让更改过的名字在子shell中使用

    相关文章

      网友评论

      本文标题:三、理解shell

      本文链接:https://www.haomeiwen.com/subject/zzjlrxtx.html