前面两节学习了一些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 bash
或bash --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
命令,就是一个外部命令,可自行试验一下
内建命令
和外键命令最大的区别就是内建命令不需要子进程来执行,这就很容易理解内建命令比外键命令的优势
例如:cd
、exit
都是内建命令
可以用type
命令判断是否是内建命令
例如:type cd
输出的结果是
cd is a shell builtin
这是一个bash内建命令和保留字的列表bash内建命令和保留字
有一些命令既是内建命令也是外键命令,例如pwd
、echo
,可以用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中使用