linux-shell编程基础

"linux"

Posted by yangsir on March 4, 2024

“Yeah It’s on. ”

shell编程基础

一、 shell 基本语法

1、什么是shell

Shell是一个命令解释器,它在操作系统的最外层,负责直接与用户进行对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出到屏幕反馈给用户。这种对话方式可是交互也可以是非交互式的

常见的shell解释器程序有很多种,使用不同的shell解释器时,其内部命令、命令行提示符等方面会存在一些区别。通过/etc/shells文件可以知道当前系统所支持的shell种类。其中/bin/bash是目前大多数linux版本采用的默认shell。

2、什么是shell脚本

Shell脚本(shell script)就是将要执行的命令按顺序保存到一个文本文件,并给该文件可执行权限,方便一次性执行的一个程序文件。主要是方便管理员进行设置或管理,可结合各种shell控制语句以完成更复杂的操作。常用于重复性操作、批量事物处理、自动化运维、服务运行状态监控、定时任务执行等。

例:

image-20240303105326557

image-20240303105448994

拓展:

date命令:

命令功能:date 可以用来显示或设定系统的日期与时间。

显示时间:

date命令可以按照指定格式显示日期,只键入date则以默认格式显示当前时间。如下:

# date

Sat Jun 15 16:51:13 CST 2019

如果需要以指定的格式显示日期,可以使用+开头的字符串指定其格式,详细格式如下:

%H : 小时(00-23)

%M : 分钟(00-59)

%S : 秒(00-60)

%X : 相当于 %H:%M:%S

%s : 从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数

%d : 日 (01-31)

%m : 月份 (01-12)

%y : 年份的最后两位数字 (00.99)

%Y : 完整年份 (0000-9999)

%x : 直接显示日期 (mm/dd/yy)

实例见下:

# date “+now time is: %Y-%m-%d %H:%M:%S”

now time is: 2019-06-15 17:05:41

# date “+%Y-%m-%d %H:%M:%S”

2019-06-15 17:05:57

# date -I //大写i

2019-06-15

设定时间:

date -s 01:01:01 #设置具体时间,不会对日期做更改

date -s “01:01:01 2019-06-15” #这样可以设置全部时间

date -s “01:01:01 20190615” #这样可以设置全部时间

date -s “2019-06-15 01:01:01” #这样可以设置全部时间

date -s “20190615 01:01:01” #这样可以设置全部时间

注意,生产环境中,要确保服务器的系统时间是一致的,可以通过NTP(网络时间协议,基于udp端口使123)服务同步时间,确保所有服务器的时间一致。可以自己搭建NTP时间服务器,也可以使用internet提供的NTP服务器。

例如结合cron计划任务定期与internet提供的ntp服务器同步保持时间一致。

# crontab -l

3、shell脚本

SHELL脚本的第一行以 #! ,后面的路径名称是命令解释器。#!/bin/bash 作用:告诉脚本使用的是哪种命令解释器,此行以后的语句通过/bin/bash程序来解释执行。如不指shell,以当前shell作为执行的shell。大多数情况下,脚本的开头使用“#!/bin/bash”和“#!/bin/sh”, sh为bash的软链接。

在shell中以#开始头表示整个行就被当作一个注释。执行时被忽略。

shell程序一般以.sh结尾,当然主要是看是否为执行,然后看里面有没有#!

4、脚本执行方式

(1)通过命令解释器执行脚本:bash test.sh 或 sh test.sh (可以对脚本文件不添加执行权限

(2)路径下执行脚本:./test.sh (当前路径下执行脚本,文件要有执行权限的)

(3)source script-name或 . script-name(脚本文件可以没有执行权限)

source或者“.”命令的功能是:读入脚本并执行脚本,即在当前Shell中执行source或“.”加载并执行的相关脚本文件的命令及语句,而不是产生一个子Shell来执行文件中的命令。

这种方式执行脚本,脚本中的变量和函数都会在当前 Shell 中生效,而不是在新的子 Shell 中

5、管道

管道操作为不同命令之间的协同工作提供了一种机制,位于管道符号“ ”左侧的命令输出的结果,将作为右侧命令的输入(处理对象)。

6、重定向

Linux系统使用文件来描述各种硬件、设备资源,如以前学过的硬盘和分区、光盘等设备文件。用户通过操作系统处理信息的过程中,包括以下几类交互设备文件。

标准输入(STDIN):默认的设备是键盘,文件编号为0,命令将从标准输入中读取在执行过程中需要的输入数据。例如通过passwd设置用户密码操作

标准输出(STDOUT):默认的设备是显示器,文件编号为1,命令将执行后的输出结果发送到显示器。

标准错误(STDERR):默认的设备是显示器,文件编号为2,命令将执行期间的各种错误信息发送到显示器。

在实际的Linux系统维护中,可以改变输入、输出内容的方向,而不是用默认的标准输入、输出设备(键盘和显示器),这种操作称为“重定向”。

(1)重定向输入

重定向输入指的是将命令中接收输入的途径由默认的键盘改为指定的文件,而不是等待从键盘输入。重定向输入使用“<”操作符。

例如:使用passwd命令为用户设置密码时,每次都根据提示输入两次密码字串,非常繁琐,若改用重定向输入将可以省略交互式的过程,而自动完成密码设置(结合passwd命令的—stdin选项来识别标准输入)。

image-20240303111323263

注意:关闭selinux

没有交互式的操作,语句更方便在shell脚本程序中使用,可以大大减少程序被打断的过程,提供脚本执行的效率。

(2)重定向输出

重定向输出指的是将命令的正常输出结果保存到指定的文件中,而不是直接显示在显示器的屏幕上,重定向输出使用“>”或“»”操作符号,分别用于将前面的命令的输出结果保存到该文件中;若目标文件已存在,则将输出结果覆盖或追加到文件中。

例如:将当前主机的CPU信息(uname -p)保存到kernel.txt文件中,而不是直接显示在屏幕上,可以执行以下操作。

image-20240303111334669

当需要保留目标文件原有的内容时,应该为“»”操作符,以便追加内容而不是覆盖。例如以下操作可以将内核版本信息追加到kernel.txt文件中。

image-20240303111401508

(3)错误重定向

错误重定向指的是将执行命令过程中出现的错误信息保存到指定的文件,而不是直接显示在屏幕上。错误重定向使用“2>”或“2»”操作符,其中2是指错误文件的编号(在使用标准输出、输入重定向时,实际上是省略了1、0编号)。

在实际应用中,错误重定向可用来收集程序执行的错误信息,为排错提供依据,对于shell脚本,还可以将无关紧要的错误信息重定向到空文件/dev/null中,以保持脚本输出的简洁。

例如:执行以下操作可以将使用tar命令进行备份时出现的错误信息保存到error.log文件中。

image-20240303111411436

使用“2>”操作符时,会像使用“>”操作符一样覆盖目标文件的内容,若要追加内容而不是覆盖文件,应改为用“2»”操作符。

当命令输出的结果可能既包括标准输出(正常执行)信息,又包括错误输出信息时,可以使用操作符“>”“»”将两类输出信息分别保存到不同的文件,也可以使用“&>”操作符将两类输出信息保存到同一个文件。

例如:在编译源码包的自动化脚本中,若要忽略make、make install等操作过程的信息,可以将其定向到空文件/dev/null。

image-20240303111419883

在脚本文件中重定向标准输出和标准错误到同一个文件除了&>外,也可以使用”exec >log.txt 2>&1” 命令。

重定向和管道符是shell环境中十分常用的功能,若能熟练掌握并灵活运用,将有助于编写简洁但功能强大的shell脚本程序。

7、位置变量

Shell解释执行用户的命令时,将命令行的第一个字作为命令名,而其它字作为参数。由出现在命令行上的位置确定的参数称为位置参数

$0 获取当前执行shell脚本或程序的名称,包括脚本路径,命令本身。注意:$0属于预定义变量而不是位置变量。

$n 获取当前脚本的第n个参数 n=1,2…..n 当n大于9时 用${10}表示。

image-20240306125950343

二、shell变量及其应用

1、位置变量

Shell解释执行用户的命令时,将命令行的第一个字作为命令名,而其它字作为参数。由出现在命令行上的位置确定的参数称为位置参数

$0 获取当前执行shell脚本或程序的名称,包括脚本路径,命令本身。注意:$0属于预定义变量而不是位置变量。

$n 获取当前脚本的第n个参数 n=1,2…..n 当n大于9时 用${10}表示。

image-20240306125950343

拓展:

判断条件

1
2
3
4
5
6
7
8
9
10
11
-eq  相等

-ne  不等

-lt  更小

-gt  更大

-le  更小或更大

-ge  更大或相等

2、特殊变量

(1)预定义变量

有些变量是一开始执行Script脚本时就会设定,且不能被修改,我们叫他们为预定义变量。这些变量当一执行程序时就有了,以下是一些预定义变量:

  • $* : 表示所有位置参数的内容,即以一个字符串显示所有向脚本传递的参数;$*以”$1 $2 … $n”的形式输出所有参数
  • $# :表示命令行中位置参数的个数,传递到脚本的参数个数
  • $@ :与$*相同$@以”$1” “$2” … “$n” 的形式输出所有参数
  • $$:当前进程的进程号PID
  • $?:显示上一条命令的退出状态;0表示没有错误,其他任何值表明有错误
  • $!:后台运行的最后一个进程的进程号pid

(2)数学运算

  • expr命令

expr只能进行简单的整数运算,不支持小数运算,运算符和运算数之间至少要有一个空格

image-20240306130858595

  • 浮点运算 bc

脚本中使用bc

1
2
3
#!/bin/bash
VAR1=$(echo "scale=4;12.5 / 7" | bc)
echo "The is $VAR1"

脚本应用:

编写运行状况监控脚本/opt/monitor.sh,用于记录CPU负载、内存和交换空间、磁盘空间、最近的用户登录情况等信息,以及当时的时间信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
用vim命令在/opt目录是新建一个脚本文件monitor.sh,内容如下:

\#!/bin/bash

mkdir -p /var/log/runrec

RecFile="/var/log/runrec/running.today"

RecTime=$(date +"%Y-%m-%d %H:%M")

LoadRec=$(uptime)

MemRec=$(free -m)

DiskRec=$(df -hT)

LastLoginRec=$(last -n 20)

echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Record Time: $RecTime

cpu Load information:$LoadRec

Memory information:$MemRec

Disk Usage information:$DiskRec

Last login 20 users record:$LastLoginRec" >> $RecFile