Shell 编程基础与变量

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 后跟一个变量,该变量会被认为是个数组
相关推荐
_OP_CHEN几秒前
【Linux网络编程】(一)初识计算机网络:从独立主机到协议世界的入门之旅
linux·服务器·网络·网络协议·计算机网络·socket·c/c++
原来是猿2 分钟前
Linux-【文件系统上】
linux·服务器·数据库
寂柒3 小时前
信号量——基于环形队列的生产消费模型
linux·ubuntu
vin_zheng6 小时前
破解企业安全软件网络拦截实战记录
运维
林姜泽樾7 小时前
Linux入门第十二章,创建用户、用户组、主组附加组等相关知识详解
linux·运维·服务器·centos
xiaokangzhe8 小时前
Linux系统安全
linux·运维·系统安全
feng一样的男子8 小时前
NFS 扩展属性 (xattr) 提示操作不支持解决方案
linux·go
xiaokangzhe8 小时前
Nginx核心功能
运维·nginx
松果1778 小时前
以本地时钟为源的时间服务器
运维·chrony·时间服务器
Highcharts.js8 小时前
Highcharts React v4.2.1 正式发布:更自然的React开发体验,更清晰的数据处理
linux·运维·javascript·ubuntu·react.js·数据可视化·highcharts