shell脚本

本文介绍了Shell编程的基础知识,包括脚本的用途、常见Shell解释器如bash的特性,以及脚本的基本结构和规范。详细讲解了bash的特性和环境变量的使用,如局部和全局变量、只读变量、位置参数和预定义变量。还涵盖了错误调试、重定向、管道符和算术运算等内容,是学习Linux自动化和系统管理的重要参考资料。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1Shell 编程基础与脚本规范

1.1编程基础

1.1.1程序组成

程序:算法+数据结构

  • 数据:是程序的核心
  • 算法:处理数据的方式
  • 数据结构:数据在计算机中的类型和组织方式

1.2 shell 脚本的用途和应用场景用途:

  • 自动化常用命令
  • 执行系统管理和故障排除
  • 创建简单的应用程序
  • 处理文本或文件

应用场景:

  • 重复性操作
  • 交互性任务
  • 批量事务处理
  • 服务运行状态监控
  • 定时任务执行

1.3常见的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特性:

  1. 支持快捷键:比如 ctrl+c 强制终止进程 、 ctrl+l 清屏 、Tab补齐 等等。
  2. 支持查看历史命令(history)
  3. 支持别名(alias)
  4. 标准输入和标准输出的重定向
  5. 管道符
  6. 文件名通配机制
  7. 支持命令hash
  8. 支持变量

这些功能都是bash特有的,其他shell环境没有这些功能,或者说没有这么全,所以bash取代sh成为了Linux的默认shell。

2    shell脚本基本结构

2.1 脚本的构成:

  1. 脚本申明(申明解释器) :第一行开头 “#!/bin/bash”,表示此行以下的代码语句是通过/bin/bash程序来执行。还有其他类型的解释器,比如 #/usr/bin/python、#!/usr/bin/expect 。
  2. 注释信息: 以“#”开头的语句表示为注释信息,被注释的语句在脚本运行时不会被执行。
  3. 可执行语句: 如echo命令,用于输出“ ”之间的字符串。

2.2 shell 脚本规范

脚本名称规范:文件名以.sh结尾,方便识别。

脚本代码开头约定:

  1. 第一行一般为调用使用的语言
  2. 程序名,避免更改文件名后无法找到正确的文件
  3. 版本号
  4. 更改后的时间
  5. 作者相关信息
  6. 该程序的作用,及注意事项
  7. 最后是各版本的更新简要说明

2.3  脚本的执行方式

1、指定路径去执行文件,文件需要有执行权限。

  • 绝对路径。如:/root/hello.sh
  • 相对路径。如:./hello.sh

2、指定解释器去执行(bash 脚本名),不需要执行权限。

  • bash 脚本名。如:bash hello.sh
  • “source 脚本名” 或 “ . 脚本名”。 //不会启动子shell环境

注意:

  1. 执行脚本时的shell环境:
  • source和 . 执行脚本时,会在当前shell环境中执行脚本。
  • bash、绝对路径、相对路径 执行脚本时,会创建一个子shell环境,并在这个子shell环境中执行脚本。
  1. 不建议使用source来执行脚本,可能会影响一些资源配置。
  2. 脚本中的空白行会被解释器忽略。
  3. 脚本中,除了shebang,余下所有以#开头的行,都回被视作注释行而被忽略。此即为注释行。

 脚本错误调试

脚本错误类型:

  1. 命令错误: 命令错误不会影响接下来的命令,之后的命令会继续执行。
  2. 语法错误: 会导致后续的命令不执行。造成脚本中一部分命令已执行,一部分未执行。
  3. 逻辑错误: 执行后的效果不是自己想要的。需要自己去排查。

 bash -n 脚本名称     //只检查语法错误,不真正执行脚本。定位的错误行可能不准确。  

​  bash -x 脚本名称     //显示每个命令的执行过程,方便发现逻辑错误

重定向

重定向的意思就是,不通过标准输出到默认屏幕上,而是输出到你指定的位置。

输入重定向

符号作用
命令 < 文件从指定的文件读取文件,而不是从键盘输入
命令 << 分界符从标准输入中读入,直到遇见分界符才停止
命令 < 文件1 > 文件2将文件1 作为命令的标准输入并将标准输出到文件

输出重定向

符号作用
命令 > 文件将标准输出结果保存到指定的文件中(覆盖原有内容)
命令 >> 文件将标准输出结果追加到指定的文件尾部
命令 2> 文件将错误输出信息保存到指定文件中(覆盖原有内容)
命令 2>> 文件将错误输出信息追加到指定文件尾部
命令 > 文件 2>&1混合输出,将标准输出与错误输出保存到文同一个文件中
命令 2> 文件 1>&2同上
命令 &> 文件同上
命令 >& 文件同上

管道符

管道符的作用是连接两个命令,将第一个命令的标准输出作为第二个命令的标准输入。 同一行命令中可以使用多个管道符。

linux下的管道符使用"竖杠"表示:| 。

格式:命令A | 命令B

Shell 脚本中的变量

变量概述

变量即在程序运行过程中它的值是允许改变的量。

变量是用一串固定的字符串去表示不固定的内容。

变量表示命令的内存空间,将数据放在内存空间中,通过变量名引用,获取数据。

变量的作用:

用来存放系统和用户需要使用的特定参数(值)。

  • 变量名:使用固定的名称,由系统预设或用户定义。

  • 变量值:能够根据用户设置、系统环境的变化而变化。

 变量类型

变量赋值: 变量名=变量值(name=value)

bash变量类型:

1、根据变量的生效范围可分为:

  • 环境变量(全局变量):全局生效,在任何bash环境中都可以识别。

  • 局部变量:生效范围为当前shell进程。对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效。

  • 本地变量:生效范围为当前shell进程中某代码片断,通常指函数。 只能在定义它们的函数/脚本内部中使用。

2、根据是否由系统定义可分为:

  • 内置变量:由系统维护,用于设置工作环境。如PS1,PATH,HISTSIZE, HOSTNAME,USER。
  • 自定义变量:由用户自己定义、修改和使用。

3、特殊变量:

  • 环境变量(全局变量):全局生效,在任何bash环境中都可以识别。:

  • 只读变量:read only, 只可以读取不可以更改 。

  • 位置变量: 通过命令行给脚本传递参数 。n(n是正整数),n(n是正整数),n(n是正整数),{10} 要加花括号。

  • 预定义变量:用来保持脚本程序的执行信息。

    • $0 :当前脚本名称(如果是软链接,显示当前软链接文件名)。
    • $? :查看上一次命令的执行状态,返回0为正常,非0为错误。
    • $* :返回所有参数,当整体返回。
    • $@ :返回所有参数,当个体返回。
    • $# :获取当前shell命令行中参数的总个数。
    • $_ :在此之前执行的命令或脚本的最后一个参数。
    • $$ :获取当前进程的PID。

 变量的命名要求

  • 区分大小写
  • 不能使程序中的保留字和内置变量名称:如:if, for,hostname。
  • 只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线 “ - ”,和主机名相反。
  • 使用英文时,尽量使用词义通俗易懂,如PATH。
  • 大驼峰 StudentFirstName
  • 小驼峰 studentFirstName
  • 下划线 student_name

变量作用范围

默认情况下,新定义的变量只在当前的shell环境中有效,因此称为局部变量,当进入子程序或新的shell环境中,局部变量将无法再起作用。

可以通过内部命令export将指定的变量为全局变量(即环境变量),使用户定义的变量在所有子shell环境中可以继续使用。

方法:

  1. 法一,设置全局变量:

    • export name=value
    • 或 declare -x name=value
  2. 法二,将局部变量转变为全局变量:export name

环境变量

系统内置环境变量

1、由系统提前创建,用来设置用户的工作环境。

2、使用env命令查看所有环境变量:

需要记住的常用环境变量:

  • $PATH 表示可执行文件的默认路径
  • $USER 表示用户名称
  • $HOME 表示用户的宿主目录
  • $LANG 表示语言和字符集
  • $PWD 表示当前所在工作目录

环境变量的特性:

  • 可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量。
  • 一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程。
  • 一般只在系统配置文件中使用,在脚本中较少使用。

环境变量的配置文件

自定义的环境变量只是临时生效,退出系统后就会失效。需要将自定义的环境变量放入配置文件中,才会永久生效。配置文件可以用来长期变更或设置环境变量。

全局配置文件:

  • /etc/profile,修改此文件会作用于所有用户。

用户独立的配置文件:

  • ~/.bash_profile,修改这个文件只作用于当前用户。

只读变量

我们在定义shell变量时,默认定义的变量是可以被修改的,但有一种变量是不能修改的,就是只读变量。

只读变量只能被赋值一次。只读变量在取得初始值之后,只能进行读取操作,不能重新赋值或删除。

定义变量:

  • 第一步:name=value # 定义一个变量
  • 第二步:readonly name # 使用 readonly 来修饰该变量 ,表明只读

位置变量

位置变量也称为位置参数。

使用$n表示,n为数字序列号,且必须为整数。

如:$1$2、…、$9 、${10}${11}

两位数需要加花括号{},不然$10会被识别为:$1和0 。

预定义变量

预定义变量是系统定义好的变量,用来保持脚本程序的执行信息。

可以直接使用这些变量,不能直接为这些变量赋值

变量作用
$?表示前一条命令执行后的返回状态。返回值为 0 表示执行正确,返回任何非 0值均表示执行出现异常。
$*表示所有位置参数的内容。当整体返回。(将输入的参数作为一个单词)
$@表示所有位置参数的内容。当个体返回。可作为数组。(将参数内容分割成n份,每份作为独立个体)
$#表示命令行中位置参数的总个数。
$0表示当前脚本名称(如果是软链接,显示当前软链接文件名)。
$_表示在此之前执行的命令或脚本的最后一个参数。
$$获取当前进程的PID。

$*$@的区别:

  • 不加双引号的话,$*$@ 都代表脚本后面跟的所有参数。
  • 加上双引号的话,"$*"会把所有参数当作一个整体去看待(此时参数数量为1),"$@"会把脚本后面跟的每一个参数当作一个个体去看待

read 从键盘输入内容为变量赋值

read可以从键盘输入变量值,即将键盘输入的内容变成变量值。

格式: read 变量名

常用选项:

  • -p:后面跟提示信息,即在输入前打印提示信息。
  • -s:安静模式,在输入字符时不再屏幕上显示,例如密码。
  • -t:后面跟秒数,定义输入字符的等待时间。
  • -n:后跟一个数字,定义输入文本的长度。
  • -a:后跟一个变量,该变量会被认为是个数组。

四个配置文件的作用

1、/etc/profile 文件

系统级的配置文件,开机时系统自动加载该文件中的配置。

系统每次启动都会自动执行/etc/profile 文件里的命令,这个文件是对全局有效的(所有的shell环境和用户)。

2、~/.bash_ profile 文件

不同用户登录系统时,会自动执行自己家目录中的~/ .bash_ profile 文件中的命令,之后自动执行~/ . bashrc。(因为~/ .bash_ profile文件中规定了,如果~/ . bashrc是个文件,则执行该文件)。

3、~/.bashrc 文件

当前用户每切换一个shell环境都会自动加载~/ . bashrc 文件中的配置 ,之后自动执行/etc/bashrc文件。(因为~/ . bashrc文件中规定了,如果/etc/bashrc是个文件,则执行该文件)。

4、/etc/bashrc 文件

/etc/bashrc针对所有用户,用户每切换一个shell环境都会自动执行。

5、/etc/skel/ 目录

/etc/skel/是用来存放新用户配置文件的目录,当我们添加新用户的时候,这个目录下的所有文件会自动被复制到新添加的用户的家目录下。这个目录下的所有文件都是隐藏文件(以.开头的文件)。

该目录中包括 .bash_logout.bash_profile.bashrc 这三个配置文件。

 重点总结

1、全局变量和局部变量:

  • 环境变量(全局变量):在当前shell环境和子shell环境(包括孙子shell环境)中都生效。
  • 局部变量:只在当前shell环境中生效,子shell环境中无效。

2、设置、查看和删除变量的命令:

  • 变量赋值:

    • 方法1:变量名=变量值(name=value)
    • 方法2:read 变量名, 之后从键盘输入中获取变量名的值
  • 设置环境变量:export name=value 或 export name

  • 设置只读变量:readonly name 。只读变量不可删除或重新赋值。

  • 查看变量和变量值:

    • env:查看所有环境变量。
    • set:查看所有变量,包括局部变量和环境变量。
  • 删除变量:unset name

3、几个符号的作用:

 双引号" ":强引用,识别变量,允许通过$符号引用其他变量值。会把引号的内容当成整体来看待。
 ​
 单引号' ':弱引用,不会识别变量,禁止引用其他变量值,单引号内的内容都会被认为是普通字符。
 ​
 反撇号` ` 和 $() :调用命令执行后输出的结果。如果存在嵌套,不能使用反撇号。
 ​
 花括号{  } :定义变量范围。 

Shell中的算术运算

Shell允许在某些情况下对算术表达式进行求值,比如:let和declare 内置命令,(( ))复合命令和算术扩展。求值以固定宽度的整数进行,不检查溢出。

注意:默认情况下bash只支持整数运算,不支持小数运算。

运算表达式:

(1) expr 变量1 运算符 变量2 [运算符 变量3]...

 (2) let var=算术表达式  

(3) ((var=算术表达式)),和上一个等价

 (4) var=$[算术表达式]

 (5) var=$((算术表达式))

 (6) var=$(expr arg1 arg2 arg3 ...)

 (7) var= `expr arg1 arg2 arg3 ...`

 (8) echo '算术表达式' | bc

运算符:

  • 加法 +
  • 减法 -
  • 乘法 \ *
  • 除法 /
  • 取余 (取模)%

运算法则:

  • 加法: num1 + num2
  • 减法:num1 - num2
  • 乘法:num1 \ * num2
  • 整除:num1 / num2
  • 取余(求模):num1 % num2 (求 num1 除以 num2 的余数)

 运算演示

expr

expr命令是一个手工命令行计数器,用于在UNIX/LINUX下求表达式变量的值,一般用于整数值,也可用于字符串。

  • 变量和运算符之间,要用空格隔开。
  • 用反斜杠 \ 放在 shell 特定的字符前面;
  • 对包含空格和其他特殊字符的字符串要用引号括起来

let 和 (( ))

let var=算术表达式 和 ((var=算术表达式)) 效果等同。

两者都不返回结果,需要借助echo命令。

$[ ]$(( ))

$[ ] 和 $(( ))效果相同,且都支持对变量进行运算

小数运算(浮点数运算)

使用bc计算器

Bash内置了对整数运算的支持,但是并不支持浮点运算,而 bc 计算器可以很方便的进行浮点运算。

  • 支持交互式和非交互式两种方式。
  • 使用scale=n可以指定精度,即小数点后的位数。要写在算术表达式之前。
  • 非交互式运算,使用 echo "算术表达式" | bc。 多个算术表达式之间用分号隔开,例如:echo '1+1;2+2" | bc。

 使用awk命令

使用awk进行浮点数的运算,运算结果最多显示6个有效数字。

格式:awk "BEGIN{print 算术表达式}"

变量的自增和自减

简写表达式等同于
let i++i=$[$i+1]
let i--i=$[$i-1]
let i+=2i=$[$i+2]
let i-=2i=$[$i-2]
let i*=2i=$[$i*2]
let i/=2i=$[$i/2]
let i%=2i=$[$i%2

使用分号,可以在一行执行多个命令。

Linux命令并行执行,顺序执行

1、Linux并行执行命令

在命令之间采用&进行连接

示例:

run1.sh&run2.sh&run3.sh&run4.sh&run5.sh

如果不是脚本而是一个程序块,那么可以采用如下形式来进行:

{程序块内容1}&{程序块内容2}&{程序块内容3}&{程序块内容4}&{程序块内容5}

注:&放在启动参数后面表示设置此进程为后台进程

2、Linux多命令顺序执行

当我们需要一次执行多个命令的时候,命令之间需要用连接符连接,不同的连接符有不同的效果。

(1) ; 分号,没有任何逻辑关系的连接符。当多个命令用分号连接时,各命令之间的执行成功与否彼此没有任何影响,都会一条一条执行下去。

(2) || 逻辑或,当用此连接符连接多个命令时,前面的命令执行成功,则后面的命令不会执行。前面的命令执行失败,后面的命令才会执行。

(3) && 逻辑与,当用此连接符连接多个命令时,前面的命令执行成功,才会执行后面的命令,前面的命令执行失败,后面的命令不会执行,与 || 正好相反。
 

(4) | 管道符,当用此连接符连接多个命令时,前面命令执行的正确输出,会交给后面的命令继续处理。若前面的命令执行失败,则会报错,若后面的命令无法处理前面命令的输出,也会报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值