Shell执行过程 | 青训营笔记

160 阅读1分钟

1. 执行命令

基本有约定:shell脚本一般以.sh结尾,也可以没有;脚本文件第一行用来指定用什么解释器来执行:

#! /bin/bash

启动方式:

  1. 文件名运行: ./filename.sh
  2. 解释器运行: bash filename.sh
  3. source运行: source filename.sh

2. 执行流程

image.png 从图中可知,shell脚本的执行过程包括字符解析、shell展开、重定向、执行命令(builtin)、子进程执行命令(非builtin)、状态返回等过程。可能涉及用户态到内核态到转换。

2.1 字符解析

  1. 识别换行符、分号,做行的分割;

  2. 识别命令连接符(||、&&、|),做命令的分割;

  3. 识别空格、tab符,做命令和参数的分割。

2.2 shell展开

  1. 大括号展开

一般由三部分(前缀、大括号、后缀)组成,大括号内可以是逗号分隔的字符串,也可以是序列表达式{x..y[..incr]};

# 字符串list
a{b,c,d}e => abe ace ade

#序列表达式
{1..5} => 1 2 3 4 5
{1..5..2} => 1 3 5
{a..e} => a b c d e
  1. 波浪号展开 波浪号展开为用户的主目录:
#当前用户
~ => $HOME

#指定用户
~king =>  king用户的$HOME

  1. 参数展开 ${}

(1) 间接参数扩展 间接参数扩展相当于将参数进一步展开:

parameter="var"
var="hello"
echo ${!parameter}

# 此时输出 hello, 也就是var的值

(2) 参数长度

${#parmeter} 使用#可以获取参数的长度

(3) 空参数处理 ${parameter:-word} : 如果parameter为空则替换为word

${parameter:=word} : 如果parameter为空则替换为word,且将parameter赋值为word

${parameter:?word} : 为空报错

${parameter:+word} : 如果parameter不为空,则将parameter替换为word

(4) 参数切片

${parameter:offset} : 从offset到最后

${parameter:offset:leghth} : 从offset开始取length个字符

  1. 命令展开

在子进程中执行命令,并用得到结果返回,使用$()或``的方式:

echo $(whoimi) #在子进程中执行whoimi命令

function(){
    echo "function"
}

result=`function` #在子进程中执行function函数
  1. 数学计算

使用$(())进行数学计算

echo $((1+2)) ---> 3

  1. 文件名展开

当有单词没有被引号包裹,且其中出现了'*'、'?'、或‘[’字符,则shell会去按照正则匹配的方式查找文件名进行替换,如果没找到则保持不变:

echo D*

输出当前目录下所有以D字母开头的目录、文件

2.3 重定向

将stdin、stdout、stderr的文件描述符进行指向变更:

  1. 输出重定向

> : 覆盖写入文件 >> : 追加写入文件 &> : 标准输出和错误输出统一写入文件 2> : 错误输出写入文件

  1. 输入重定向

< : 重点向标准输入 << : 沿用标准输入,当识别到指定标识符(如EOF)后停止,将收到的内容作为stdin

2.4 命令执行

  1. builtin命令直接执行

  2. 非内置命令查找$PATH后启动子进程执行