Shell脚本编程实战
wptr33 2024-12-10 21:20 23 浏览
做 Java 的肯定都接触过 Linux 系统,那么很多时候我们在开发的过程中都是把我们项目打成一个jar包,或者是war包的形式,然后通过 XFTP 上传到我们服务器的指定目录,然后运行一端启动脚本,让我们的项目变得可以访问 就像 ./sh service.sh start 然后启动我们写好的 sh 的shell脚本。接下来我们就来学习一下关于 Shell 脚本是如何写出来的。
Shell 脚本
Shell 脚本是什么?Shell是一个命令解释器,它的作用是解释执行用户输入的命令及程序等,也就是说,我们用户每输入一条命令,Shell 就会相对应的执行一条命令。当命令或程序语句不在命令行下执行,而是通过一个程序文件来执行时,该程序文件就被称为Shell脚本。
在我们的 Shell 脚本中,会有各种各样的内容,赋值,计算,循环等一系列的操作,接下来我们就来看看这个 Shell 脚本怎么写吧
1.查看自己当前系统默认的 Shell
echo $SHELL
输出:/bin/bash
2.查看系统支持的Shell
cat /etc/shells
输出:
/bin/sh /bin/bash /usr/bin/sh /usr/bin/bash
也就是说,我们的云服务器是支持我们在这里给他安排 Shell 脚本的
Shell 脚本怎么写出来的
我们这时候先来安排一下 sh 的文件,创建一个文件夹,然后在其中创建一个 sh 的文件。
mkdir /usr/local/shelltest
touch test.sh
创建完成我们编辑一下内容
vim test.sh
#!/bin/bash
echo "Hello World Shell"
然后我们出来运行一下我们的 Shell 的第一个脚本
bash test.sh
出来的结果是 Hello World Shell
一个及其简单的脚本出现了,接下我们就分析一波我们写了点啥?
#!/bin/bash
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell
我们在之前也使用了 echo $SHELL 来查看了自己系统默认的是哪一种 sh 解析器,之前看到的是/bin/bash,所以我们在写 Shell 脚本的时候,我们在开头默认的约定中,我们写了这个是用 /bin/bash 来进行解释的,
那么我们如何像之前调用我们的当前目录中的 Shell 脚本一样去调用他呢?就像这个样子的 ./sh service.sh start
1.授权,
我们先不授权试一下看看能通过 ./test.sh 进行调用么
bash: ./test.sh: Permission denied 会提示这个,也就是没有授权定义,
授权命令:chmod +x test.sh
2.执行 ./test.sh
然后调用就能正常输出了,就是说,在当前的目录下执行这个脚本命令。
Shell 脚本的变量
- 定义变量和使用
变量命名实际上很简单,我们先来试一下
name=zhiyikeji
这时候我们怎么使用变量呢?实际上只要在前面加上一个符号就可以 $
echo $name
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo $name
zhiyikeji
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo ${name}
zhiyikeji
上面的两种写法都是可以的,外面的大括号加和不加区别不大,可以省略,直接就$name 就可以使用你定义的变量
使用括号的意义一般在于区别某些变量,比如你写了一串的内容,可能写的是 echo $nameismyfriend,如果连在一起,是不是有点尴尬,这时候就可以使用括号区别一下,echo ${name}ismyfriend 不使用括号的时候,他就去找nameismyfriend这个变量了,就无法出来我们要的效果。
- 删除自己定义的变量
unset name
这时候我们就把我们刚才定义的 name=zhiyikeji 这个变量给去掉了,我们可以调用一下我们的变量看是什么?
echo $name
[root@iZbp10j01t7sgfqekyefpoZ ~]# unset name
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo $name
这是不是就证明我们自己定义的变量已经删除了
- 只读变量
那么我们需要一个关键字,大家肯定能想到是什么关键字 readonly
我们先给name赋值,然后使用 readonly 设置只读,然后再改变一下试试,
[root@iZbp10j01t7sgfqekyefpoZ ~]# name=zhiyikeji
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo $name
zhiyikeji
[root@iZbp10j01t7sgfqekyefpoZ ~]# readonly name
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo $name
zhiyikeji
[root@iZbp10j01t7sgfqekyefpoZ ~]# name=ceshi
-bash: name: readonly variable
[root@iZbp10j01t7sgfqekyefpoZ ~]#
竟然是真的,如果不设置只读,是不是会重新可以进行赋值,我们测试个年龄,
[root@iZbp10j01t7sgfqekyefpoZ ~]# age=10
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo $age
10
[root@iZbp10j01t7sgfqekyefpoZ ~]# age=20
[root@iZbp10j01t7sgfqekyefpoZ ~]# echo $age
20
所以我们就可以肯定,readonly就是设置只读的关键词,记住了么?
那么设置只读的变量可以删除么?毕竟总有杠精的面试官会提问这个棘手的问题,但是,阿粉试过的所有方式好像都是不行的,阿粉就直接重启了自己的服务器,这样临时的变量就不存在了!
Shell 脚本的流程控制
说真的,Shell脚本的流程控制数一般才是yyds,为什么这么说,因为你在写大部分的脚本的时候,流程控制的地方永远是最多的,判断,选择,等等一系列的函数,当时熟练使用的时候,就发现这东西确实很有意思。
IF
我们先说最简单的 if else 这也是我们最经常使用的判断,在写 Shell 脚本的时候,就不像我们的 Java 中直接写
if(...){
}else{
....
}
Xshell 中的语法就不是这个样子的,Xshell语法:
if ...
then
...
else
...
fi
末尾的 fi 就是 if 倒过来拼写,我们可以写一个 if 的脚本试一下这个流程能否理解。
#! /bin/bash
if [ $1 -gt 2 ];
then
echo "值大于2"
else
echo "值小于2"
exit
fi
这里申明一下,
- -ge标识的是大于等于符号;
- -le表示的是小于等于符号;
- -gt 表示大于符号;
- -lt 表示小于符号;
- -eq 表示等于符号;
- -ne 表示不等于符号;
我们在上面这段脚本中写就是内容就是,我们给脚本传入一个值,然后比对这个值和2的大小关系,然后输出我们指定的内容。
运行后就能看到
[root@iZbp10j01t7sgfqekyefpoZ shelltest]# sh test2.sh 1
值小于2
[root@iZbp10j01t7sgfqekyefpoZ shelltest]# sh test2.sh 3
值大于2
$1 表示我们给 Shell 脚本输入的第一个参数, $0就是你写的shell脚本本身的名字,$2 是我们给 Shell 脚本传的第二个参数
大家在部署某些项目的时候,是不是启动命令就很简洁,就是 sh service.sh start 类似这种的,那我们来看看一般这种是怎么写的,这就用到了另外一块的内容,和 if 类似,在 Java 中也有,那就是 Case.
Case
我们先来看看 Case 的语法,
case ... esac 实际上就和 Java 中的 Case 是非常相似的,case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令.esac是一个结束的标志。
case 值 in
匹配值1)
command1
command2
;;
匹配值2)
command1
command2
;;
esac
光说不练,假把式,我们来搞一下试试写一个脚本来搞一下。就用我们刚才说的 sh servic.sh start 来进行测试。
case $1 in
start)
#输出启动命令
echo "start已经开始"
;;
stop)
#输出停止命令
echo "stop命令执行"
;;
esac
exit
我们来看看运行结果
[root@iZbp10j01t7sgfqekyefpoZ shelltest]# sh service.sh start
start已经开始
[root@iZbp10j01t7sgfqekyefpoZ shelltest]# sh service.sh stop
stop命令执行
那么这段 Shell 脚本是什么意思呢?其实很简单,匹配我们传入的第一个字符,和 start 还有 stop 进行比较,如果匹配上之后,输出命令,最后退出即可。
是不是感觉没有那么复杂了呢?
For
说到流程控制,那么肯定不能不说 for , 毕竟 for 循环在 Java 中那可是重头戏。
我们先看他的格式
for i in item1 item2 ... itemN
do
command1
command2
...
commandN
done
那么我们有没有说像是 Java 中那种 for 循环一样的方式呢?比如说这个for ((i=1; i<=j; i++))
实际上也是支持这种的,我们来写一个试试。
j=$1
for ((i=1;i<=j;i++))
do
echo $i
done
执行一下看看
[root@iZbp10j01t7sgfqekyefpoZ shelltest]# sh fortest.sh 6
1
2
3
4
5
6
既然有 for 那是不是就有 while 呢?是的,没错,确实是有 while ,也是循环的意思,但是写法有略微不一样的地方
While
while condition
do
command
done
我们来举个尝试打印九九乘法表来看一下
a=1
b=1
while ((a <=9))
do
while ((b<=a))
do
let "c=a*b" #声明变量c
echo -n "$a*$b=$c "
let b++
done
let a++
let b=1 #因为每个乘法表都是1开始乘,所以b要重置
echo "" #显示到屏幕换行
done
[root@iZbp10j01t7sgfqekyefpoZ shelltest]# sh whileTest.sh
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
是不是也挺简单的?
其实 Shell 脚本的编写一般都是在实际应用中提升,单纯的写测试脚本,也是可以让自己对知识的掌握比较充分,而我们一般都是写一些比较简单的脚本,复杂的不是还有运维么?
相关推荐
- MySQL进阶五之自动读写分离mysql-proxy
-
自动读写分离目前,大量现网用户的业务场景中存在读多写少、业务负载无法预测等情况,在有大量读请求的应用场景下,单个实例可能无法承受读取压力,甚至会对业务产生影响。为了实现读取能力的弹性扩展,分担数据库压...
- 3分钟短文 | Laravel SQL筛选两个日期之间的记录,怎么写?
-
引言今天说一个细分的需求,在模型中,或者使用laravel提供的EloquentORM功能,构造查询语句时,返回位于两个指定的日期之间的条目。应该怎么写?本文通过几个例子,为大家梳理一下。学习时...
- 一文由浅入深带你完全掌握MySQL的锁机制原理与应用
-
本文将跟大家聊聊InnoDB的锁。本文比较长,包括一条SQL是如何加锁的,一些加锁规则、如何分析和解决死锁问题等内容,建议耐心读完,肯定对大家有帮助的。为什么需要加锁呢?...
- 验证Mysql中联合索引的最左匹配原则
-
后端面试中一定是必问mysql的,在以往的面试中好几个面试官都反馈我Mysql基础不行,今天来着重复习一下自己的弱点知识。在Mysql调优中索引优化又是非常重要的方法,不管公司的大小只要后端项目中用到...
- MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)
-
目录1.索引基础...
- 你会看 MySQL 的执行计划(EXPLAIN)吗?
-
SQL执行太慢怎么办?我们通常会使用EXPLAIN命令来查看SQL的执行计划,然后根据执行计划找出问题所在并进行优化。用法简介...
- MySQL 从入门到精通(四)之索引结构
-
索引概述索引(index),是帮助MySQL高效获取数据的数据结构(有序),在数据之外,数据库系统还维护者满足特定查询算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构...
- mysql总结——面试中最常问到的知识点
-
mysql作为开源数据库中的榜一大哥,一直是面试官们考察的重中之重。今天,我们来总结一下mysql的知识点,供大家复习参照,看完这些知识点,再加上一些边角细节,基本上能够应付大多mysql相关面试了(...
- mysql总结——面试中最常问到的知识点(2)
-
首先我们回顾一下上篇内容,主要复习了索引,事务,锁,以及SQL优化的工具。本篇文章接着写后面的内容。性能优化索引优化,SQL中索引的相关优化主要有以下几个方面:最好是全匹配。如果是联合索引的话,遵循最...
- MySQL基础全知全解!超详细无废话!轻松上手~
-
本期内容提醒:全篇2300+字,篇幅较长,可搭配饭菜一同“食”用,全篇无废话(除了这句),干货满满,可收藏供后期反复观看。注:MySQL中语法不区分大小写,本篇中...
- 深入剖析 MySQL 中的锁机制原理_mysql 锁详解
-
在互联网软件开发领域,MySQL作为一款广泛应用的关系型数据库管理系统,其锁机制在保障数据一致性和实现并发控制方面扮演着举足轻重的角色。对于互联网软件开发人员而言,深入理解MySQL的锁机制原理...
- Java 与 MySQL 性能优化:MySQL分区表设计与性能优化全解析
-
引言在数据库管理领域,随着数据量的不断增长,如何高效地管理和操作数据成为了一个关键问题。MySQL分区表作为一种有效的数据管理技术,能够将大型表划分为多个更小、更易管理的分区,从而提升数据库的性能和可...
- MySQL基础篇:DQL数据查询操作_mysql 查
-
一、基础查询DQL基础查询语法SELECT字段列表FROM表名列表WHERE条件列表GROUPBY分组字段列表HAVING分组后条件列表ORDERBY排序字段列表LIMIT...
- MySql:索引的基本使用_mysql索引的使用和原理
-
一、索引基础概念1.什么是索引?索引是数据库表的特殊数据结构(通常是B+树),用于...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
程序员的开源月刊《HelloGitHub》第 71 期
-
详细介绍一下Redis的Watch机制,可以利用Watch机制来做什么?
-
假如有100W个用户抢一张票,除了负载均衡办法,怎么支持高并发?
-
如何将AI助手接入微信(打开ai手机助手)
-
Java面试必考问题:什么是乐观锁与悲观锁
-
redission YYDS spring boot redission 使用
-
SparkSQL——DataFrame的创建与使用
-
一文带你了解Redis与Memcached? redis与memcached的区别
-
如何利用Redis进行事务处理呢? 如何利用redis进行事务处理呢英文
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)