Shell
Shell(壳)是计算机操作系统中的一种用户界面,它为用户提供了与操作系统内核和系统资源进行交互的途径。Shell可以是一种命令行界面(CLI,Command-Line Interface)或图形用户界面(GUI,Graphical User Interface),用户可以通过Shell执行命令、运行程序、管理文件和系统等。
在Linux和类Unix系统中,Shell是一个解释器,它解释和执行用户输入的命令,然后将这些命令传递给操作系统内核执行。
程序组成
程序:算法+数据结构
- 数据:是程序的核心
- 算法:处理数据的方式
- 数据结构:数据在计算机中的类型和组织方式
编程风格
过程式:以指令为中心来组织代码,数据服务于指令。代表:C语言,bash。
过程式编程语言三种执行逻辑:
- 顺序执行:程序按从上到下顺序执行。
- 选择执行:程序执行过程中,根据条件的不同,进行选择不同分支继续执行。
- 循环执行:程序执行过程中需要重复执行多次某段语句。
对象式:以数据为中心来组织代码,指令服务于数据。代表:Java,C++,Python。
- 类(class):实例化对象,method
编程语言的分类
根据运行方式
- 编译运行:源代码 → 编译器(编译)→ 程序文件
- 解释运行:源代码 → 运行时启动解释器,由解释器边解释边运行
根据启编译过程中功能的实现是调用库还是调用外部的程序文件
- shell脚本编程:利用系统上的命令及编程组件进行编程
- 完整编程:利用库或编程组件进行编程
shell 脚本的用途和应用场景
用途:
- 自动化常用命令
- 执行系统管理和故障排除
- 创建简单的应用程序
- 处理文本或文件
应用场景:
- 重复性操作
- 交互性任务
- 批量事务处理
- 服务运行状态监控
- 定时任务执行
常见的shell解释器
Linux系统中的Shell 是一个特殊的应用程序,它介于操作系统内核与用户之间,充当一个"命令解释器"的角色,负责接收用户输入的操作指令(命令)并进行解释,将需要执行的操作传递给内核执行,并输出结果。 它是用户使用 Linux 的桥梁。
Shell 既是一种命令语言,又是一种程序设计语言。
常见的 Shell 解释器程序有很多种,使用不同的 Shell 时,其内部指令、命令行提示符等方面会存在一些区别。通过/etc/shell 文件可以了解当前系统所支持的 Shell 脚本种类。
linux 中常见的shell
- bash:基于GUN的框架下发展的shell
- csh:类似C语言的shell
- tcsh:整合了csh 提供了更多功能
- sh:已经被bash替换
- nologin:让用户无法登录
bash(/bin/bash)是目前大多数 Linux 版本采用的默认 shell。
bash特性
- 支持快捷键:比如 ctrl+c 强制终止进程 、 ctrl+l 清屏 、Tab补齐 等等。
- 支持查看历史命令(history)
- 支持别名(alias)
- 标准输入和标准输出的重定向
- 管道符
- 文件名通配机制
- 支持命令hash
- 支持变量
这些功能都是bash特有的,其他shell环境没有这些功能,或者说没有这么全,所以bash取代sh成为了Linux的默认shell。
shell脚本基本结构
shell脚本就是将各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。
将要执行的命令按顺序一一列出,保存到一个文本文件,最后自动执行。 执行脚本需要x权限,也可以使用绝对路径来执行。 可结合各种Shell控制语句以完成更复杂的操作。
脚本的构成:
脚本申明(申明解释器) :第一行开头 "#!/bin/bash",表示此行以下的代码语句是通过/bin/bash程序来执行。还有其他类型的解释器,比如 #/usr/bin/python、#!/usr/bin/expect 。
注释信息: 以"#"开头的语句表示为注释信息,被注释的语句在脚本运行时不会被执行。
可执行语句: 如echo命令,用于输出" "之间的字符串。
脚本的执行方式
指定路径去执行文件,文件需要有执行权限。
绝对路径。如:/root/hello.sh
相对路径。如:./hello.sh
指定解释器去执行(bash 脚本名),不需要执行权限。
- bash 脚本名。如:bash hello.sh
- "source 脚本名" 或 " . 脚本名"。 //不会启动子shell环境
执行脚本时的shell环境:
- source和 . 执行脚本时,会在当前shell环境中执行脚本。
- bash、绝对路径、相对路径 执行脚本时,会创建一个子shell环境,并在这个子shell环境中执行脚本。
- 不建议使用source来执行脚本,可能会影响一些资源配置。
- 脚本中的空白行会被解释器忽略。
- 脚本中,除了shebang,余下所有以#开头的行,都会被视作注释行而被忽略。此即为注释行。
脚本错误调试
脚本错误类型:
- 命令错误: 命令错误不会影响接下来的命令,之后的命令会继续执行。
- 语法错误: 会导致后续的命令不执行。造成脚本中一部分命令已执行,一部分未执行。
- 逻辑错误: 执行后的效果不是自己想要的。需要自己去排查。
bash -n 脚本名称 //只检查语法错误,不真正执行脚本。定位的错误行可能不准确。
bash -x 脚本名称 //显示每个命令的执行过程,方便发现逻辑错误
重定向与管道符
由于Shell脚本"批量处理"的特殊性,其大部分操作过程位于后台,不需要用户进行干预,因此要学会提取、过滤执行信息变得十分重要,所以我们需要重定向和管道。
标准输入与输出
交互式硬件设备:
- 标准输入:从该设备接收用户输入数据。
- 标准输出:通过该设备想用户输出数据。
- 标准错误:通过该设备报告执行出错信息。
重定向
重定向的意思就是,不通过标准输出到默认屏幕上,而是输出到你指定的位置。
输入重定向
符号 | 作用 |
---|---|
命令 < 文件 | 从指定的文件读取文件,而不是从键盘输入 |
命令 << 分界符 | 从标准输入中读入,直到遇见分界符才停止 |
命令 < 文件1 > 文件2 | 将文件1 作为命令的标准输入并将标准输出到文件2 |
输出重定向
符号 | 作用 |
---|---|
命令 > 文件 | 将标准输出结果保存到指定的文件中(覆盖原有内容) |
命令 >> 文件 | 将标准输出结果追加到指定的文件尾部 |
命令 2> 文件 | 将错误输出信息保存到指定文件中(覆盖原有内容) |
命令 2>> 文件 | 将错误输出信息追加到指定文件尾部 |
命令 > 文件 2>&1 | 混合输出,将标准输出与错误输出保存到文同一个文件中 |
命令 2> 文件 1>&2 | 混合输出,将标准输出与错误输出保存到文同一个文件中 |
命令 &> 文件 | 混合输出,将标准输出与错误输出保存到文同一个文件中 |
命令 >& 文件 | 混合输出,将标准输出与错误输出保存到文同一个文件中 |
- &表示混合,&> 和 >& 都表示将标准输出和错误输出重定向到同一个文件。
- 命令 > 文件 2>&1,表示把错误输出2重定向给前面的标准输出1 (前面的1被省略了),即将错误输出和标准输出保存到同一个文件中。
管道符
管道符的作用是连接两个命令,将第一个命令的标准输出作为第二个命令的标准输入。 同一行命令中可以使用多个管道符。
linux下的管道符使用"竖杠"表示:| 。
格式:命令A | 命令B
变量
- 变量即在程序运行过程中它的值是允许改变的量。
- 变量是用一串固定的字符串去表示不固定的内容。
- 变量表示命令的内存空间,将数据放在内存空间中,通过变量名引用,获取数据。
变量的作用:
- 用来存放系统和用户需要使用的特定参数(值)。
- 变量名:使用固定的名称,由系统预设或用户定义。
- 变量值:能够根据用户设置、系统环境的变化而变化。
变量类型
变量赋值: 变量名=变量值(name=value)
根据变量的生效范围
环境变量(全局变量):全局生效,在任何bash环境中都可以识别。
局部变量:生效范围为当前shell进程。对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效。
本地变量:生效范围为当前shell进程中某代码片断,通常指函数。 只能在定义它们的函数/脚本内部中使用。
根据是否由系统定义
内置变量:由系统维护,用于设置工作环境。如PS1,PATH,HISTSIZE, HOSTNAME,USER。 自定义变量:由用户自己定义、修改和使用。
特殊变量
环境变量(全局变量):全局生效,在任何bash环境中都可以识别。:
只读变量:read only, 只可以读取不可以更改 。
位置变量: 通过命令行给脚本传递参数 。n(n是正整数),n(n是正整数),n(n是正整数),{10} 要加花括号。
预定义变量用来保持脚本程序的执行信息。
- $0 :当前脚本名称(如果是软链接,显示当前软链接文件名)。
- $? :查看上一次命令的执行状态,返回0为正常,非0为错误。
- $* :返回所有参数,当整体返回。
- $@ :返回所有参数,当个体返回。
- $# :获取当前shell命令行中参数的总个数。
- $_ :在此之前执行的命令或脚本的最后一个参数。
- '$$' :获取当前进程的PID。
变量作用范围
默认情况下,新定义的变量只在当前的shell环境中有效,因此称为局部变量,当进入子程序或新的shell环境中,局部变量将无法再起作用。 可以通过内部命令export将指定的变量为全局变量(即环境变量),使用户定义的变量在所有子shell环境中可以继续使用。
设置全局变量:
- export name=value
- declare -x name=value
将局部变量转变为全局变量:
- export name
特殊符号
js
双引号" ":会把引号的内容当成整体来看待。强引用,识别变量,允许通过$符号引用其他变量值。
单引号' ':会把引号的内容当成整体来看待。弱引用,禁止引用其他变量值,单引号内的内容都会被认为是普通字符。
反撇号` ` 和 $() :调用命令执行后输出的结果。如果存在嵌套,不能使用反撇号。
花括号{ } :定义变量范围。 echo ${color}${price}
局部变量
定义变量: 变量名=变量值
引用变量 : <math xmlns="http://www.w3.org/1998/Math/MathML"> 变量名或 变量名 或 </math>变量名或{变量名}
查看变量:
- echo $变量名:查看单个变量
- set:查看所有变量,包括局部变量和环境变量
取消变量: unset 变量名
作用范围: 仅在当前shell环境中有效,无法在子shell环境中使用。
环境变量
系统内置环境变量
由系统提前创建,用来设置用户的工作环境。
使用env命令查看所有环境变量:
- $PATH 表示可执行文件的默认路径
- $USER 表示用户名称
- $HOME 表示用户的宿主目录
- $LANG 表示语言和字符集
- $PWD 表示当前所在工作目录
环境变量的特性:
- 可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量。
- 一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程。
- 一般只在系统配置文件中使用,在脚本中较少使用。
只读变量
在定义shell变量时,默认定义的变量是可以被修改的,但有一种变量是不能修改的,就是只读变量。
只读变量只能被赋值一次。只读变量在取得初始值之后,只能进行读取操作,不能重新赋值或删除。
位置变量
位置变量也称为位置参数。
使用$n表示,n为数字序列号,且必须为整数。
如: <math xmlns="http://www.w3.org/1998/Math/MathML"> 1 、 1、 </math>1、2、...、 <math xmlns="http://www.w3.org/1998/Math/MathML"> 9 、 9 、 </math>9、{10}、${11}。
两位数需要加花括号{},不然 <math xmlns="http://www.w3.org/1998/Math/MathML"> 10 会被识别为: 10会被识别为: </math>10会被识别为:1和0 。
预定义变量
预定义变量是系统定义好的变量,用来保持脚本程序的执行信息。
可以直接使用这些变量,不能直接为这些变量赋值。
变量 | 作用 |
---|---|
$? | 表示前一条命令执行后的返回状态。返回值为 0 表示执行正确,返回任何非 0值均表示执行出现异常 |
$* | 表示所有位置参数的内容。当整体返回。(将输入的参数作为一个单词) |
$@ | 表示所有位置参数的内容。当个体返回。可作为数组。(将参数内容分割成n份,每份作为独立个体) |
$# | 表示命令行中位置参数的总个数 |
$0 | 表示当前脚本名称(如果是软链接,显示当前软链接文件名) |
$_ | 表示在此之前执行的命令或脚本的最后一个参数 |
$$ | 获取当前进程的PID |
js
$* 和 $@的区别:
不加双引号的话,$* 和 $@ 都代表脚本后面跟的所有参数。
加上双引号的话,"$*"会把所有参数当作一个整体去看待(此时参数数量为1),"$@"会把脚本后面跟的每一个参数当作一个个体去看待。
$?
read
read可以从键盘输入变量值,即将键盘输入的内容变成变量值。
选项 | 作用 |
---|---|
-p | 后面跟提示信息,即在输入前打印提示信息 |
-s | 安静模式,在输入字符时不再屏幕上显示,例如密码 |
-t | 后面跟秒数,定义输入字符的等待时间 |
-n | 后跟一个数字,定义输入文本的长度 |
-a | 后跟一个变量,该变量会被认为是个数组 |