百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

一步一步了解并搞懂shell脚本 shell 脚本教程

liuian 2024-12-16 14:46 39 浏览

提醒:本文为合集文章,后续持续更新!

关注我持续进步!

Shell脚本并不能作为正式的编程语言,因为它是在Linux的shell中运行的,所以称为shell脚本。事实上,shell脚本就是一些命令的集合。比如,我想实现这样的操作:

(1) 进入/tmp/目录;

(2) 列出当前目录中所有的文件名;

(3) 把所有当前的文件复制到/root/目录下;

(4) 删除当前目录下所有的文件。

完成以上简单的4步需要在shell窗口中输入4次命令,按4次回车,这不算太难。但如果是输入复杂的命令,一次一次敲键盘会很麻烦。我们不妨把所有的操作都记录到一个文档中,然后去调用文档中的命令,这样一步操作就可以完成。其实这个文档就是shell脚本,只是这个shell脚本有它特殊的格式。

Shell脚本能帮助我们很方便地管理服务器,因为我们可以指定一个任务计划,定时去执行某个shell脚本以满足需求。这对于Linux系统管理员来说是一件非常值得自豪的事情。我们可以在Linux服务器上部署监控的shell脚本,然后脚本中可以加上邮件通知来告之出现故障。比如,网卡流量出现异常或者Web服务器停止服务,就可以发一封邮件给管理员。这样可以让管理员及时知道服务器出问题了。

在正式编写shell脚本之前,阿铭建议凡是自定义的脚本都放到/usr/local/sbin/目录下。这样做的目的是:一来可以更好地管理文档;二来以后接管你工作的管理员都知道自定义脚本放在哪里,方便维护。

13.1.1 shell脚本的创建和执行

下面请跟着阿铭编写第一个shell脚本,如下所示:

# cd /usr/local/sbin/
# vim first.sh //加入如下内容
#! /bin/bash
## This is my first shell script.
## Writen by Aming 2022-12-02.
date
echo "Hello world!"

shell脚本通常都以.sh为后缀名。这并不是说不加.sh的脚本就不能执行,只是大家的一个习惯而已。所以,以后如果发现了以.sh为后缀的文件,那么它可能是一个shell脚本。本例中,脚本文件first.sh的第1行要以#! /bin/bash开头,表示该文件使用的是bash语法。如果不设置该行,你的shell脚本也可以执行,但是不符合规范。#表示注释,后面跟一些该脚本的相关注释内容,以及作者、创建日期或者版本等。当然,这些注释并非必需的,但阿铭不建议省略。因为随着工作时间的逐渐过渡,写的shell脚本也会越来越多,如果有一天你回头查看自己写过的某个脚本,很有可能忘记该脚本是用来干什么的以及什么时候写的。所以写上注释是有必要的。另外,系统管理员并非只有你一个,写上注释有助于其他管理员查看你的脚本。

下面我们执行一下这个脚本,如下所示:

# sh first.sh
Fri Dec  2 22:16:56 CST 2022
Hello world!

其实shell脚本还有一种执行方法,如下所示:

# ./first.sh
-bash: ./first.sh: 权限不够
# chmod +x first.sh
# ./first.sh
Fri Dec  2 22:16:56 CST 2022
Hello world!

使用该方法运行shell脚本的前提是脚本本身有执行权限,所以需要给脚本加一个x权限。另外,使用sh命令执行一个shell脚本时,可以加-x选项来查看这个脚本的执行过程,这样有利于我们调试这个脚本。如下所示:

# sh -x first.sh
+ date
Fri Dec  2 22:17:43 CST 2022
+ echo 'Hello world!'
Hello world!

本例中有一个date命令,之前阿铭从未介绍过,这个命令在shell脚本中使用非常频繁,因此有必要介绍一下它的用法。

13.1.2 命令date

date命令在shell脚本中最常用的几个用法如下。

  • date +%Y:表示以四位数字格式打印年份。
  • date +%y:表示以两位数字格式打印年份。
  • date +%m:表示月份。
  • date +%d:表示日期。
  • date +%H:表示小时。
  • date +%M:表示分钟。
  • date +%S:表示秒。
  • date +%w:表示星期。结果显示0则表示周日。

下面阿铭举几个比较实用的例子来帮助你掌握date命令的用法,示例代码如下:

# date +"%Y-%m-%d %H:%M:%S"
2022-12-02 22:18:03

有时,在脚本中会用到一天前的日期,如下所示:

# date -d "-1 day" +%d
01

或者一小时前,如下所示:

# date -d "-1 hour" +%H
21

甚至一分钟前,如下所示:

# date -d "-1 min" +%M
17


13.2 shell脚本中的变量

在shell脚本中使用变量会使我们的脚本更加专业,更像是一门语言。如果你写了一个长达1000行的shell脚本,并且脚本中多次出现某一个命令或者路径,而你觉得路径不对想修改一下,就得一个一个修改,或者使用批量替换的命令修改。这样做很麻烦,并且脚本也显得臃肿了很多。变量就是用来解决这个问题的。定义变量的格式为:“变量名=变量的值”。在脚本中引用变量时需要加上符号$,这跟前面介绍的在shell中自定义变量是一致的。

下面我们编写第一个与变量相关的脚本,如下所示:


# vim variable.sh
#! /bin/bash
## In this script we will use variables.
## Writen by Aming 2022-12-02.
d=`date +%H:%M:%S`
echo "The script begin at $d."
echo "Now we'll sleep 2 seconds."
sleep 2
d1=`date +%H:%M:%S`
echo "The script end at $d1."

本例中使用到了反引号,它的作用是将引号中的字符串当成shell命令执行,返回命令的执行结果。d和d1在脚本中作为变量出现。

下面来看看该脚本的执行结果,如下所示:

# sh variable.sh
The script begin at 22:23:04.
Now we'll sleep 2 seconds.
The script end at 22:23:06.


13.2.1 数学运算

示例命令如下:

# vim sum.sh
#! /bin/bash
## For get the sum of two numbers.
## Aming 2022-12-02.
a=1
b=2
sum=$[$a+$b]
echo "$a+$b=$sum"

数学计算要用[ ]括起来,并且前面要加符号$。该脚本的结果如下:

# sh sum.sh
1+2=3


13.2.2 和用户交互

示例脚本如下:

# cat read.sh
#! /bin/bash
## Using 'read' in shell script.
## Aming 2022-12-02.
read -p "Please input a number: " x
read -p "Please input another number: " y
sum=$[$x+$y]
echo "The sum of the two numbers is: $sum"

read命令用于和用户交互,它把用户输入的字符串作为变量值。该脚本的执行过程如下:

# sh read.sh
Please input a number: 2
Please input another number: 10
The sum of the two numbers is: 12

我们不妨加上-x选项再来看看这个执行过程:

# sh -x read.sh
+ read -p 'Please input a number: ' x
Please input a number: 22
+ read -p 'Please input another number: ' y
Please input another number: 13
+ sum=35
+ echo 'The sum of the two numbers is: 35'
The sum of the two numbers is: 35


13.2.3 shell脚本预设变量

有时我们会用到类似/etc/init.d/iptables restart(该命令来源于早期CentOS系统)命令,前面的/etc/init.d/iptables文件其实就是一个shell脚本。脚本后面为什么可以跟一个restart字符串呢?这就涉及shell脚本的预设变量了。实际上,shell脚本在执行时,后面可以跟一个或者多个参数。比如下面的脚本:

# vim option.sh //内容如下
#! /bin/bash
sum=$[$1+$2]
echo "sum=$sum"

该脚本的执行结果如下:

# sh -x option.sh 1 2
+ sum=3
+ echo sum=3
sum=3

你可能会问:脚本中的$1和$2是从哪里来的?这其实就是shell脚本的预设变量。本例中,$1和$2的值就是在执行时分别输入的1和2,$1就是脚本的第一个参数,$2是脚本的第二个参数,以此类推。当然一个shell脚本的预设变量是没有限制的。

另外还有一个$0,它代表脚本本身的名字。我们不妨把脚本修改一下,如下所示:

#! /bin/bash
echo "$1 $2 $0"

该脚本的执行结果如下:

# sh option.sh 1 2
1 2 option.sh


13.3 shell脚本中的逻辑判断

如果你学过C等语言,相信你不会对if感到陌生。在shell脚本中,我们同样可以使用if逻辑判断。

13.3.1 不带else

具体格式如下:

if 判断语句; then
command
fi

示例脚本如下:

# cat if1.sh
#! /bin/bash
read -p "Please input your score: " a
if ((a<60)); then
echo "You didn't pass the exam."
fi

if1.sh中出现了((a<60))这样的形式,这是shell脚本中特有的格式,只用一个小括号或者不用都会报错,请记住这个格式。阿铭还会用另外一种格式,后面会介绍到。

该脚本的执行结果如下:

# sh if1.sh
Please input your score: 90
# sh if1.sh
Please input your score: 33
You didn't pass the exam.


13.3.2 带有else

具体格式如下:

if 判断语句; then
command
else
command
fi

示例脚本如下:

# vim if2.sh //内容如下
#! /bin/bash
read -p "Please input your score: " a
if ((a<60)); then
echo "You didn't pass the exam."
else
echo "Good! You passed the exam."
fi

该脚本的执行结果如下:

# sh if2.sh
Please input your score: 80
Good! You passed the exam.
# sh if2.sh
Please input your score: 25
You didn't pass the exam.

脚本if2.sh和脚本if1.sh唯一的区别是:如果输入大于或等于60的数字会有提示。

13.3.3 带有elif

具体格式如下:

if 判断语句1; then
command
elif 判断语句2; then
command
else
command
fi

示例脚本如下:

# vim if3.sh //内容如下
#! /bin/bash
read -p "Please input your score: " a
if ((a<60)); then
echo "You didn't pass the exam."
elif ((a>=60)) && ((a<85)); then
echo "Good! You pass the exam."
else
echo "Very good! Your score is very high!"
fi

这里的&&表示“并且”的意思,当然也可以使用||表示“或者”。

该脚本的执行结果如下:

# sh if3.sh
Please input your score: 90
Very good! Your score is very high!
# sh if3.sh
Please input your score: 60
Good! You pass the exam.

以上只是简单介绍了if语句的结构。判断数值大小除了可以用(())的形式外,还可以使用[]。但是不能使用>、<、=这样的符号了,要使用-lt (小于)、-gt(大于)、-le(小于或等于)、-ge(大于或等于)、-eq(等于)、-ne(不等于)。下面阿铭就以命令行的形式简单比较一下,不再写shell脚本。示例代码如下:

# a=10; if [ $a -lt 5 ]; then echo ok; fi
# a=10; if [ $a -gt 5 ]; then echo ok; fi
ok
# a=10; if [ $a -ge 10 ]; then echo ok; fi
ok
# a=10; if [ $a -eq 10 ]; then echo ok; fi
ok
# a=10; if [ $a -ne 10 ]; then echo ok; fi

下面是在if语句中使用&&和||的情况,示例代码如下:

# a=10; if [ $a -lt 1 ] || [ $a -gt 5 ]; then echo ok; fi
ok
# a=10; if [ $a -gt 1 ] || [ $a -lt 10 ]; then echo ok; fi
ok


13.3.4 和文档相关的判断

Shell脚本中if还经常用于判断文档的属性,比如判断是普通文件还是目录,判断文件是否有读、写、执行权限等。if常用的选项有以下几个。

  • -e:判断文件或目录是否存在。
  • -d:判断是不是目录以及是否存在。
  • -f:判断是不是普通文件以及是否存在。
  • -r:判断是否有读权限。
  • -w:判断是否有写权限。
  • -x:判断是否可执行。

使用if判断时的具体格式如下:

if [ -e filename ] ; then
command
fi

示例代码如下:

# if [ -d /home/ ]; then echo ok; fi
ok
# if [ -f /home/ ]; then echo ok; fi

因为/home/是目录而非文件,所以并不会显示ok。其他示例如下所示:

# if [ -f /root/test.txt ]; then echo ok; fi
ok
# if [ -r /root/test.txt ]; then echo ok; fi
ok
# if [ -w /root/test.txt ]; then echo ok; fi
ok
# if [ -x /root/test.txt ]; then echo ok; fi
# if [ -e /root/test1.txt ]; then echo ok; fi


感谢阅读,关注我持续进步!

相关推荐

GANs为何引爆机器学习?这篇基于TensorFlow的实例教程为你解惑!

「机器人圈导览」:生成对抗网络无疑是机器学习领域近三年来最火爆的研究领域,相关论文层出不求,各种领域的应用层出不穷。那么,GAN到底如何实践?本文编译自Medium,该文作者以一朵玫瑰花为例,详细阐...

高丽大学等机构联合发布StarGAN:可自定义表情和面部特征

原文来源:arXiv、GitHub作者:YunjeyChoi、MinjeChoi、MunyoungKim、Jung-WooHa、SungKim、JaegulChoo「雷克世界」编译:嗯~...

TensorFlow和PyTorch相继发布最新版,有何变化

原文来源:GitHub「机器人圈」编译:嗯~阿童木呀、多啦A亮Tensorflow主要特征和改进在Tensorflow库中添加封装评估量。所添加的评估量列表如下:1.深度神经网络分类器(DNNCl...

「2022 年」崔庆才 Python3 爬虫教程 - 深度学习识别滑动验证码缺口

上一节我们使用OpenCV识别了图形验证码躯壳欧。这时候就有朋友可能会说了,现在深度学习不是对图像识别很准吗?那深度学习可以用在识别滑动验证码缺口位置吗?当然也是可以的,本节我们就来了解下使用深度...

20K star!搞定 LLM 微调的开源利器

LLM(大语言模型)微调一直都是老大难问题,不仅因为微调需要大量的计算资源,而且微调的方法也很多,要去尝试每种方法的效果,需要安装大量的第三方库和依赖,甚至要接入一些框架,可能在还没开始微调就已经因为...

大模型DeepSeek本地部署后如何进行自定义调整?

1.理解模型架构a)查看深度求索官方文档或提供的源代码文件,了解模型的结构、输入输出格式以及支持的功能。模型是否为预训练权重?如果是,可以在预训练的基础上进行微调(Fine-tuning)。是否需要...

因配置不当,约5000个AI模型与数据集在公网暴露

除了可访问机器学习模型外,暴露的数据还可能包括训练数据集、超参数,甚至是用于构建模型的原始数据。前情回顾·人工智能安全动态向ChatGPT植入恶意“长期记忆”,持续窃取用户输入数据多模态大语言模型的致...

基于pytorch的深度学习人员重识别

基于pytorch的深度学习人员重识别Torchreid是一个库。基于pytorch的深度学习人员重识别。特点:支持多GPU训练支持图像的人员重识别与视频的人员重识别端到端的训练与评估简单的re...

DeepSeek本地部署:轻松训练你的AI模型

引言:为什么选择本地部署?在AI技术飞速发展的今天,越来越多的企业和个人希望将AI技术应用于实际场景中。然而,对于一些对数据隐私和计算资源有特殊需求的用户来说,云端部署可能并不是最佳选择。此时,本地部...

谷歌今天又开源了,这次是Sketch-RNN

前不久,谷歌公布了一项最新技术,可以教机器画画。今天,谷歌开源了代码。在我们研究其代码之前,首先先按要求设置Magenta环境。(https://github.com/tensorflow/magen...

Tensorflow 使用预训练模型训练的完整流程

前面已经介绍了深度学习框架Tensorflow的图像的标注和训练数据的准备工作,本文介绍一下使用预训练模型完成训练并导出训练的模型。1.选择预训练模型1.1下载预训练模型首先需要在Tensorf...

30天大模型调优学习计划(30分钟训练大模型)

30天大模型调优学习计划,结合Unsloth和Lora进行大模型微调,掌握大模型基础知识和调优方法,熟练应用。第1周:基础入门目标:了解大模型基础并熟悉Unsloth等工具的基本使用。Day1:大模...

python爬取喜马拉雅音频,json参数解析

一.抓包分析json,获取加密方式1.抓包获取音频界面f12打开抓包工具,播放一个(非vip)视频,点击“媒体”单击打开可以复制URL,发现就是我们要的音频。复制“CKwRIJEEXn-cABa0Tg...

五、JSONPath使用(Python)(json数据python)

1.安装方法pipinstalljsonpath2.jsonpath与Xpath下面表格是jsonpath语法与Xpath的完整概述和比较。Xpathjsonpath概述/$根节点.@当前节点...

Python网络爬虫的时候json=就是让你少写个json.dumps()

大家好,我是皮皮。一、前言前几天在Python白银交流群【空翼】问了一个Python网络爬虫的问题,提问截图如下:登录请求地址是这个:二、实现过程这里【甯同学】给了一个提示,如下所示:估计很多小伙伴和...