科普文:一天学会shell编程

news2024/9/9 4:35:52

1.shell概叙

        本文将从shell执行、语法、实战三个方面来讲解shell编程,其实shell编程就是个批处理,将你平时在服务器上单独执行的命令,按照一定要求组织起来,写在一起,然后统一执行,就完事了。

        对于运维人员来说,收集一下服务器信息、写个巡检报告、静默安装oracle、批量安装jdk、nginx、redis、mysql啥的还是很有用的。

        开发人员掌握一些shell编程(java进程启动脚本、maven打包编译脚本、docker服务编排脚本等等),也便于在linux服务器上处理问题。

        只要你能静下来,把本文看完,并将里面的示例敲一遍,执行一遍,可以百分百保证你已经学会了shell编程。话不多说,直接开干。

1.1 什么是shell?

        shell是一个用C 语言编写的程序,它是用户使用Liunx的桥梁。shell既是一种命令语言,又是一种程序设计语言。shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问Liunx内核服务。

        在计算机科学中,Shell俗称壳(用来区别于核),是指“为使用者提供操作界面”的软件(command interpreter,命令解析器)。它类似于DOS下的COMMAND.COM和后来的cmd.exe。它接收用户命令,然后调用相应的应用程序。

图形界面shell 和命令行式shell

        shell从操作界面来分,可以分成:图形界面shell 、命令行式shell。

        一:图形界面shell (Graphical User Interface shell 即 GUI shell) 例如:应用最为广泛的Windows Explorer(微软的Windows系列操作系统),还有也包括广为人知的Linux shell,其中Linux shell包括X Window Manager(BlackBox和FluxBox),以及功能更强大的CDE、GNOME、KDE、 Xfce。

        二:命令行式shell (Command Line Interface shell ,即CLI shell)。命令式shell就代表了shell,也是我们平常口中的shell,所以本文的重点就是讲命令行式shell。

交互式shell和非交互式shell

        交互式模式就是shell等待用户的输入,并且执行用户提交的命令。这种模式被称作交互式是因为shell与用户进行交互。这种模式也是大多数用户非常熟悉的:登录、执行一些命令、签退。当用户签退后,shell也终止了。

        shell也可以运行在另外一种模式:非交互式模式。在这种模式下,shell不与用户进行交互,而是读取存放在文件中的命令,并且执行它们。当它读到文件的结尾,shell也就终止了。

sh、ksh、bash 

        shell从解释器来分:sh、ksh、bash、csh等等。将在1.3节中再重点讲。

1.2什么是shell脚本?

        shell脚本(shell script) ,是一种为shell编写的脚本程序,一般后缀名为 .sh
业界所说的shell 通常都是指shell脚本,但shell 和 shell script 是两个不同的概念。

        shell脚本文件命名格式:*.sh  后缀一般是".sh",当然也可以不写,比如:MySQL的mysqld_safe就没有带后缀。

        shell脚本文件执行方式:

  sh  -n  /path/to/some-script  : 只检测脚本中的语法错误,但无 法检查出命令错误,但不真正执行脚本
  sh  -x  /path/to/some_script  :调试并执行
  bash  -n  /path/to/some-script  : 只检测脚本中的语法错误,但无 法检查出命令错误,但不真正执行脚本
  bash  -x  /path/to/some_script  :调试并执行
  直接加执行权限运行:chmod +x   
  直接执行网上的脚本:   curl    http:\\sdss     2>/dev/null  | bash 

        shell脚本文件内容格式:

         包括  文件头、注释、 变量、命令、 流程控制、函数等6部分。

  1. 文件头:‌Shell脚本通常以一行特殊的注释作为文件头,‌称为Shebang行。‌Shebang行用于告诉操作系统该脚本应该用哪种解释器执行,‌通常写为#!/bin/sh#!/bin/bash,‌表示使用sh或bash解释器。‌

  2. 注释:‌Shell脚本支持两种注释方式,‌分别是单行注释和多行注释。‌单行注释以#开头,‌直到行末结束。‌多行注释使用:<<开始,‌接着是注释内容,‌最后以EOF结束。‌

  3. 变量:‌变量是Shell脚本中的基本数据类型,‌可以用于存储数字、‌字符串等信息。‌Shell脚本中的变量名通常是大写字母,‌变量值可以使用等号=进行赋值。‌在Shell脚本中,‌可以使用$符号引用变量的值。‌

  4. 命令:‌在Shell脚本中,‌命令可以是Shell命令或其他可执行程序。‌命令可以通过直接调用或使用变量调用。‌变量调用的语法为$(...)。‌

  5. 流程控制语句:‌Shell脚本支持多种流程控制语句,‌例如if语句、‌for循环语句和while循环语句等。‌

  6. 函数:即自定义函数,和C、Java中的函数定义一样,就是对重复、可复用功能的一种封装。

shell脚本示例如下:

#!/bin/bash     #文件头
source /etc/profile  #命令   引入环境变量

# This is a comment  #注释
:<<EOF               #多行注释
This is a multi-line comment.
EOF

# Define a variable
CURRENT_DATE=$(date) #变量  定义本地变量

# Print the current date
echo "The current date is: $CURRENT_DATE"  #命令 打印当前时间

MY_VAR = "Hello World"   #流程控制
if [ $MY_VAR = "Hello World" ]; then
    echo "The variable is equal to Hello World"
else
    echo "The variable is not equal to Hello World"
fi

#函数  定义函数
function my_function() {
    echo "This is my function"
}

my_function  #执行函数

shell脚本格式规范:

一、脚本基本格式

 1、首行为一些命令或声明

  #!/bin/bash
  #!/usr/bin/python
  #!/usr/bin/perl
  #!/usr/bin/ruby
  #!/usr/bin/lua

2、脚本注释规范

  第一行一般为调用
  程序名
  版本号
  更改后的时间
  作者相关信息
  该程序的作用
  简要说明

一、注释
头部注释
#!/bin/bash
# vim:sw=4:ts=4:et
<<INFO
SCRIPYT:test.sh
AUTHOR:anqixiang<邮箱号>
DATE:2021-09-12
DESCRIBE:描述脚本主要功能
SYSTEM:适配哪些操作系统
WARNING:警告信息
VERSION:1.1.0<可选>
MODIFY:记录修改信息,方便查看和维护
INFO

单行注释与多行注释
单行注释以#号开头,如

#修改IP地址

多行注释表示方法(INFO可以用别的标识代替,但需与结尾保持一致)

<<INFO
SCRIPYT:test.sh
AUTHOR:anqixiang<邮箱号>
DATE:2021-09-12
INFO

二、排版规范
1.程序块采用缩进,缩进为4个空格
修改vim中Tab键的距离
举例

while true
do
    sleep 5
done

2.函数
函数功能注释
所有的函数注释应该包含:

函数的描述
全局变量的使用和修改
使用的参数说明
返回值,而不是上一条命令运行后默认的退出状态
示例:

#######################################
# Cleanup files from the backup dir
# Globals:
#   BACKUP_DIR
#   BACKUP_SID
# Arguments:
#   None
# Returns:
#   None
#######################################
cleanup() {
    ...
}

函数编写
函数首字母大写,并用“_”隔开,如Modify_Ip
函数名后面必须加小括号()
第一个大括号与小括号之间保留一个空格
第二个大括号顶格单独占一行
同级别的代码块要左对齐
举例

Modify_Ip() {
	command1
	command2
	if 表达式;then
	    command 3
	else
	    command 4
	fi
}

3.命令较长需分行书写,在低优先级操作符处划分新行,用'\'标识
command 1 | command 2 \
    && command 3 \
    || command 4

4.一行只写一条语句
command 1;command 2			#不推荐
command 1					#推荐
command 2

5.逻辑运算符&&、||和重定向、管道符前后要留空格
command 1 && command 2
command 1 | command 2

# 长命令管道换行连接,管道放置于下一个命令开头,缩进4个空格
command1 \
    | command2 \
    | command3 \
    | command4

6.一个函数只完成一个功能,且不能超过100行
7.case语句格式
case $value in
val1)
    command 1
    ;;
a|b)
    command 2
    ;;
*)
    command 3
esac

8.注释与上面的代码用空行隔开
command 1
[空一行]
#注释内容
command 2

9.循环和判断
for循环
for i in 1..3
do
    if [[ $i -eq 1 ]];then
    	echo "等于1"
    elif [[ $i -eq 2 ]];then
    	echo "等于2"
    else
    	echo "等于3"
    fi
done

while
while read line
do
	...
done < file.txt
或者
command | while read line
do
    ...
done 

三、变量规范
1.变量名由字母、数字、下划线组成, 只能以字母、下划线开头
2.尽量减少全局变量,可在变量前面加local使其成为局部变量
local name=""
for name in a b
do
	echo ${name}
done

全局变量仅在当前Shell有效,使用export定义的全局变量在所有子进程中依然有效

3.环境变量和全局变量大写,局部变量小写(使用下划线连接,如host_ip )
readonly PATH_TO_FILES='/some/path'		#不能修改的变量添加readonly 属性
declare -xr BACKUP_SID='PROD'

declare解释
功能介绍:声明变量的属性,如果使用declare,后面没有任何参数,那么bash就会主动将所有变量名与内容都调出来,just as set.

语 法:declare [-aixr] variable

参数说明:
-a :将后面的variable定义为数组
-i :将后面的variavle定义为整数数字
-x :用法与export一样,就是将后面的variable变成环境变量
-r :将一个variable的亦是设置成只读,读变量不可更改内容,也不能unset

4.引用变量用\${value}
val=${value}
[[ ${value} == "test" ]] && command 1

5.不能被清除和修改的变量通过readonly variable声明
6.常用变量集中写在脚本开头,便于修改
7.对变量赋空值时,建议使用unset
unset sum

8.用ln创建软链接文件,必须先判断文件是否存在,存在时必须先删除,然后再创建软链接
[ -h /data ] && rm -rf /data
ln -sf /home/data /data

9.命令替换推荐使用$(),并用双引号括起来,在groovy中建议使用``(反撇号)
local_ip="$(ip addr | grep ......)"

四、安全清理
1.环境变量和history不能有敏感信息

五、建议
判断推荐使用[[ ]]
判断命令是否存在用command -v代替which(command是内部命令,系统自带;如果命令不存在不会输出任何信息)
路径尽量保持绝对路径,不易出错,如果非要用相对路径,最好用./修饰
简单的if尽量使用&& ||,写成单行。比如[[ x > 2]] && echo x
使用rm删除目录的时候建议先cd到父目录,再删除子目录

1.3什么是shell解释器?

        前面虽然两次提到了#! ,但是本着重要的事情说三遍的精神,

        这里再强调一遍:在 shell 脚本,#! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 解释器。#! 被称作shebang(也称为 Hashbang )。

        #! 决定了脚本可以像一个独立的可执行文件一样执行,而不用在终端之前输入sh, bash, python, php等。  

# 以下两种方式都可以指定 shell 解释器为 bash,第二种方式更好
#!/bin/bash
#!/usr/bin/env bash  ## 推荐

      各主要操作系统下缺省的shell:

  • AIX下是Korn Shell。
  • Solaris缺省的是Bourne shell。
  • FreeBSD缺省的是C shell。
  • HP-UX缺省的是POSIX shell。
  • Linux是Bourne Again shell。

        十五年或者二十年前,一些服务器监控系统,为了获取服务器的资源使用情况,统一用sh解释器来执行和编写服务器信息收集脚本,因为sh可以在bash、ksh、csh下面都能运行,而bash、ksh、csh之间有兼容性问题,写出来的脚本不一定能通用。

2.shell变量

 1、变量类型

  内置变量:PS1,PATH,  UID    HOSTNAME  $$  BASHPID  PPID  $?  HISTSIZE

2、变量数据类型:

  字符  

  数值:整型、浮点型,bash不支持浮点数

3、变量全名法则

  区分大小写、不能使用程序中的保留字和内置变量,如:if ,for;   

  只能使用数字、字母及下划线,且不能以数字开头,

4、变量定义

  普通变量:生效范围为当前SHELL进程,对当前SHELL之外的其它SHELL进程,均无效

  环境变量:生效范围为当前SHELL进程及其子进程

  本地变量:生效范围为当前SHELL进程中某代码片断,通用指函数

  变量赋值:name='value',,,赋值为临时生产,退出后变量自动删除;脚本中的变量会随着脚本结束而删除

      直接字串:name='root'

      变量引用:name="$USER"

      命令引用:name=`COMMAND`   或者  name=$(COMMAND)

5、引用 

  弱引用:"$name"  其中的变量引用会被替换为变量值

  强引用:'$name'  其中的变更引用不会被替换为变量值,而保持原字符串

  追加:NAME  +=:DJY

6、变量显示和删除

  set  显示所有变量

  unset <name>  删除变量

7、环境变量

  可以使子进程,继承父进程的变量,但是无法让父进程使用子进程的变量

  一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程

  一般只在系统配置文件中使用,在脚本中较少使用

  显示所有环境变量:env    printenv    export     declare   -x

8、bash内建的 环境变量

  PATH   SHELL  USER   UID   HOME   PWD   SHLVL   LANG   MAIL   HOSTNAME    HISTSIZE  

9、只读变量

   readonly name         declare   -r name 

10、位置变量

  在bash  shell中内置的变量,在脚本代码中调用通过命令行传递给脚本的参数  

    清空所有位置变量:set  --

11、退出状态码变量: 

  $?的值为0       代表成功   ;  $ ?  取值范围 0-255

  ?的值为1-255    代表失败

  自定义退出状态码:  exit  [n]

12、展开命令行

  

 

  13、脚本安全和SET

  set命令:可以用来定制shell环境

  

    

3.格式化输出  printf  

   .

  

 1、常用格式替换符

  

   

 2、常用转义字符  

  

3、格式化输出示例

# 单引号
printf '%d %s\n' 1 "abc"
#  Output:1 abc

# 双引号
printf "%d %s\n" 1 "abc"
#  Output:1 abc

# 无引号
printf %s abcdef
#  Output: abcdef(并不会换行)

# 格式只指定了一个参数,但多出的参数仍然会按照该格式输出
printf "%s\n" abc def
#  Output:
#  abc
#  def

printf "%s %s %s\n" a b c d e f g h i j
#  Output:
#  a b c
#  d e f
#  g h i
#  j

# 如果没有参数,那么 %s 用 NULL 代替,%d 用 0 代替
printf "%s and %d \n"
#  Output:
#   and 0

# 格式化输出
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
#  Output:
#  姓名     性别   体重kg
#  郭靖     男      66.12
#  杨过     男      48.65
#  郭芙     女      47.99

4.shell运算符

一、算术运算

    SHELL允许在某些情况下对算术表达式进行求值;   bash  只支持整数,不支持小数

1、实现算术运算  

 2、内建的随机数生成器变量

  $RANDOM   取值范围:0-32767

3、增强型赋值:let varOPERvalue  

 二、逻辑运算  

     与:&    或:|    非:!  异或:^      相同为假,不同为真

1、 短路运算

  短路与  &&          CMD1  &&  CMD2     当1为真时,再计算2值; 当1为假时,结果为0,不再执行2

  短路或 ||

  短路与  和短路或  组合    :  CMD1  && CMD2   ||  CMD3            先执行与再执行或,反过来不使用。

三、条件测试命令

1、条件测试命令格式

  test   EXPRESSION

  [EXPRESSION]    和test等价,建议使用【】

  [[EXPRESSION]]   相当于增强版的【】,支持【】的用法 ,且支持扩展正则表达式和通配符

2、变量测试 

  【 -v  NAME】  判断NAME变量是否定义 

3、数值测试

  -eq  是否等于    ==

  -ne  是否不等于    !=

  -gt  是否大于    >

  -ge  是否大于等于  >=

  -lt  是否小于    <

  -le  是否小于等于  <=

 4、字符串测试

 5、文件测试  

   

   

 四、关于()和{}

  (CMD1; CMD2;...)和{CMD1;CMD2; ....;}都可以将多个命令组合在一起,批量执行  

 五、组合测试条件

 1、第一种方式  

2、第二种方式  

六、使用read命令来接受输入

  使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量,如果变量名没有指定,默认标准输入的值赋值给系统内置变量REPLY

  格式:   read [options] [name...]

 常见选项:  

-p           指定要显示的提示
-s            静默输入, 一般用于密码
-n  N        指定输入的字符长度N
-d  '字符'   输入结束符
-t  N        TIMEOUT为N秒

5.Shell流程控制

        Shell流程控制是Shell脚本编程中的重要组成部分,它允许我们根据条件、循环或其他逻辑结构来控制脚本的执行流程。

        通过掌握条件语句、循环语句、选择语句和其他控制语句的用法,我们可以编写出更加智能、灵活、高效、可靠的自动化脚本,以满足各种复杂的自动化需求。

        在实际应用中,我们可以根据具体的任务需求选择合适的流程控制结构,并结合Shell的其他功能(如变量、函数、管道等)来实现更加复杂的自动化任务。

1、条件语句

        条件语句根据指定的条件来决定脚本的执行路径。在Shell脚本中,常用的条件语句有if、elif和else。这些语句允许我们根据条件表达式的值来执行不同的命令或命令组。

    1. if语句:当条件为真时执行相应的命令或命令组。

    2. elif语句:在if语句中,当第一个条件不满足时,可以使用elif来指定另一个条件进行判断。

    3. else语句:在if或elif条件都不满足时,执行else块中的命令或命令组。

2、循环语句

        循环语句允许我们重复执行某个命令或命令组,直到满足某个条件为止。Shell脚本中常用的循环语句有for、while和until。

    1. for循环:遍历一个列表或序列中的元素,并对每个元素执行相应的命令或命令组。

    2. while循环:当条件为真时,重复执行命令或命令组。

    3. until循环:与while循环相反,当条件为假时重复执行命令或命令组。

3、选择语句

    1. case语句:用于基于多个可能的值进行条件选择。

4、其他控制语句

        除了条件语句、选择语句和循环语句外,Shell还提供了其他一些控制语句,如break(跳出循环)、continue(跳过当前循环迭代)、exit(退出脚本)等。这些语句用于更精细地控制脚本的执行流程。

if语句

1、基本语法:

if [ 条件表达式 ]  
then  
    # 当条件为真时执行的命令  
elif [ 另一个条件表达式 ]  
then  
    # 当另一个条件为真时执行的命令  
else  
    # 当所有条件都不为真时执行的命令(可选)  
fi

2、注意事项:

    1. [ 条件表达式 ] 中的空格是必需的。方括号与条件表达式之间以及方括号内部的操作符和变量之间都需要有空格。

    2. 条件表达式通常使用测试命令(如 [ -f file ] 检查文件是否存在)或比较操作符(如 [ $a -eq $b ] 比较两个数字是否相等)。

    3. then、elif、else 和 fi 是 if 语句的关键字,用于定义条件块。

3、示例:

    声明一个名为AGE的变量,根据这个变量的值来输出不同的消息。

#!/bin/bash

AGE=25

if [ $AGE -lt 18 ]
then
    echo "You are a teenager."
elif [ $AGE -ge 18 ] && [ $AGE -lt 65 ]
then
    echo "You are an adult."
else
    echo "You are a senior citizen."
fi
# 输出:You are an adult.

        在这个示例中,使用了两个条件表达式:$AGE -lt 18(检查年龄是否小于18)和 $AGE -ge 18 && $AGE -lt 65(检查年龄是否在18到65岁之间)。根据AGE变量的值,脚本会输出相应的消息。

        在比较操作符(如-lt、-ge)和变量之间必须添加空格。还使用了逻辑操作符&& 来组合两个条件表达式。

图片

for循环

    在Shell脚本中,for循环是一种常用的控制结构,用于迭代一系列的值或元素。Shell脚本中的for循环有几种不同的形式,但最常见的是基于列表或数组的循环,以及基于范围的循环。

1、基于列表或数组的循环

    • 使用空格分隔的值列表

    • for element in value1 value2 value3
      do
          echo "$element"
      done
      # 输出
      value1
      value2
      value3

    • 使用数组(注意:不是所有的Shell都支持数组)

  • array=("value1" "value2" "value3")
    for element in "${array[@]}"
    do
        echo "$element"
    done
    # 输出
    value1
    value2
    value3

    • 从文件中读取每一行

for line in $(cat filename.txt)
do
    echo "$line"
done
    • 使用通配符迭代文件或目录

for file in /path/to/dir/*.txt
do
    echo "$file"
done

2、基于范围的循环

    在Bash中,可以使用seq命令或花括号扩展。

    • 使用seq命令

for i in $(seq 1 5)
do
    echo "$i"
done
# 输出:
1
2
3
4
5
    • 使用花括号扩展(Bash 4+)

for i in {1..5}
do
    echo "$i"
done
# 输出:
1
2
3
4
5

3、遍历命令的输出

    • 遍历ls命令的输出(注意:不要在生产环境中对ls的输出进行解析)

for file in $(ls /path/to/dir/)
do
    echo "$file"
done
    • 更安全的方法是使用find命令与-print0和read -d $'\0'组合

find /path/to/dir/ -type f -print0 | while IFS= read -r -d $'\0' file; do
    echo "$file"
done

        注意:当处理文件名或路径时,特别是当它们可能包含空格、换行符或其他特殊字符时,使用$(command)或命令替换可能会产生问题。在这种情况下,使用find命令与-print0和read -d $'\0'组合是更安全的选择。

while循环

    在Shell脚本中,while循环用于在条件为真时重复执行一系列命令。当条件变为假时,循环停止执行。

1、基本语法

while [ 条件表达式 ]  
do  
    # 当条件为真时执行的命令  
done

2、示例

    • 使用简单的条件检查

#!/bin/bash  

counter=1  

while [ $counter -le 5 ]  
do  
    echo "这是循环的第 $counter 次迭代"  
    ((counter++))  
done

# 输出:
这是循环的第 1 次迭代
这是循环的第 2 次迭代
这是循环的第 3 次迭代
这是循环的第 4 次迭代
这是循环的第 5 次迭代

        在这个例子中,初始化了一个变量counter,并使用while循环检查该变量的值是否小于或等于5。在每次循环迭代中,我们都打印出一条消息并增加counter的值。当counter的值大于5时,条件不再为真,循环停止。

    • 读取文件内容

#!/bin/bash  

while IFS= read -r line  
do  
    echo "$line"  
done < filename.txt

        在这个例子中,我们使用read命令从文件filename.txt中逐行读取内容,并将每一行存储在变量line中。IFS=用于防止文件名中的空格或特殊字符被错误地解释为字段分隔符。然后,我们打印出每一行的内容。

    • 无限循环(需要手动退出)

        有时,你可能想要创建一个无限循环,直到用户手动退出。这可以通过在循环条件中使用true来实现,因为true始终返回真。

#!/bin/bash  

while true  
do  
    echo "这是一个无限循环,按Ctrl+C退出"  
    sleep 1  # 暂停1秒,以避免过快地输出  
done

        在这个例子中,我们使用true作为while循环的条件,因此循环将无限期地继续执行。我们使用sleep 1命令在每次迭代之间暂停1秒,以避免过快地输出消息。要退出这个无限循环,你可以按Ctrl+C。

3、注意事项

    • 确保在while循环中正确地更新条件表达式中使用的变量,以避免无限循环。

    • 当从文件中读取内容时,使用read命令的-r选项可以确保按原样读取行,而不会解释反斜杠字符为转义字符。

    • 使用IFS=可以确保文件名中的空格、换行符和其他特殊字符不会被错误地解释为字段分隔符。

    • 如果在while循环中使用read命令从管道或重定向中读取输入,请确保在done关键字之后没有额外的输入重定向操作符(如<或|),因为这可能会导致语法错误。

until循环

    在Shell脚本中,until循环与while循环类似,但它会在条件表达式为假时执行循环体,直到条件表达式变为真时停止。也就是说,until循环会一直执行,直到满足某个条件为止。

1、基本语法

until [ 条件表达式 ]
do
    # 当条件为假时执行的命令
done

2、示例

    • 使用简单的条件检查

#!/bin/bash

counter=0

until [ $counter -ge 5 ]
do
    echo "这是循环的第 $counter 次迭代"
    ((counter++))
done

        在这个例子中,我们初始化了一个变量counter,并使用until循环检查该变量的值是否大于或等于5。在每次循环迭代中,我们都打印出一条消息并增加counter的值。当counter的值达到或超过5时,条件变为真,循环停止。

    • 等待某个文件出现

假设你正在等待一个名为result.txt的文件在某个目录下出现,你可以使用until循环配合文件测试操作符[ -f file ]来实现。

#!/bin/bash

until [ -f /path/to/result.txt ]
do
    echo "result.txt 文件尚未出现,等待..."
    sleep 1  # 暂停1秒,以避免过快地检查
done

echo "result.txt 文件已出现,继续执行后续操作..."

在这个例子中,until循环会一直检查/path/to/result.txt文件是否存在。如果不存在,它会打印一条消息并暂停1秒,然后再次检查。一旦文件出现,条件变为真,循环停止,并打印出相应的消息。

3、注意事项

    • 与while循环类似,确保在until循环中正确地更新条件表达式中使用的变量,以避免无限循环。

    • 使用sleep命令可以在循环迭代之间添加延迟,以避免过快地检查条件或执行其他操作。

    • 如果你的Shell脚本中同时使用了while和until循环,请确保你清楚它们之间的区别,并正确地使用它们来满足你的需求。

case语句

    在Shell脚本中,case 语句用于基于多个可能的值进行条件选择。它与C、C++、Java等编程语言中的 switch 语句类似,但Shell中使用的是 case 而不是 switch。case 语句允许脚本根据变量的值来执行不同的代码块。

1、基本语法:

case 变量 in
    模式1)
        # 当变量匹配模式1时执行的命令
        ;;
    模式2)
        # 当变量匹配模式2时执行的命令
        ;;
    ...
    *)
        # 当变量不匹配任何模式时执行的命令(可选)
        ;;
esac

2、注意事项:

    1. 每个 case 分支都以 ;; 结尾,这表示该分支的结束。

    2. *) 是一个特殊的模式,用于捕获所有不匹配前面模式的值。

    3. 可以在模式中使用通配符,如 *(匹配任何字符串)、 ?(匹配任何单个字符)等。

3、示例:

    声明一个名为 DAY 的变量,它包含了星期几的缩写(如Mon、Tue等),根据这个变量的值来输出不同的消息。

#!/bin/bash

DAY="Wed"


case $DAY in
    Mon)
        echo "Today is Monday."
        ;;
    Tue)
        echo "Today is Tuesday."
        ;;
    Wed)
        echo "Today is Wednesday."
        ;;
    Thu)
        echo "Today is Thursday."
        ;;
    Fri)
        echo "Today is Friday."
        ;;
    Sat|Sun)
        echo "Today is the weekend!"
        ;;
    *)
        echo "Invalid day: $DAY"
        ;;
esac
# 输出:Today is Wednesday.

         在这个示例中,我们根据DAY变量的值来匹配不同的case分支,并输出相应的消息。注意,在Sat|Sun)这个分支中,我们使用了 | 来表示“或”的关系,这意味着当DAY的值为Sat或Sun时,都会执行这个分支中的命令。如果DAY的值不匹配任何已知的模式,那么就会执行*)这个默认分支中的命令。

其他控制语句

1、break

    break 语句用于立即终止当前的循环(如 for、while 或 until 循环)。当遇到 break 语句时,循环将不再继续执行,而是跳转到循环之后的下一条语句。

#!/bin/bash
for i in {1..5}
do
    if [ $i -eq 3 ]; then
        break
    fi
    echo $i
done
# 输出:1 2

2、continue

    continue 语句用于跳过当前循环的剩余部分,直接开始下一次循环迭代。当遇到 continue 语句时,循环的当前迭代将立即结束,但不会终止整个循环。

#!/bin/bash
for i in {1..5}
do
    if [ $i -eq 3 ]; then
        continue
    fi
    echo $i
done
# 输出:1 2 4 5

3、exit

    exit 语句用于立即终止脚本的执行。可以为其提供一个状态码,用于指示脚本是否成功执行。状态码 0 通常表示成功,而非零值表示某种错误或异常情况。

#!/bin/bash
if [ ! -f "somefile.txt" ]; then
    echo "somefile.txt does not exist!"
    exit 1
fi
echo "Processing somefile.txt..."
# 如果 somefile.txt 不存在,则脚本会输出错误消息并退出,状态码为 1

注意:exit 语句不仅会终止当前脚本的执行,还会终止任何调用该脚本的父进程(如果它是在子shell中运行的)。因此,在脚本中使用 exit 时要小心,确保你了解其潜在影响。

6.shell示例

学习脚本

#! /bin/bash
#--------------------------------------------
# shell shell脚本学习
# author:zhouxx
#--------------------------------------------

# if语句
if [ $1="input" ]
then
	echo "Hello Shell"
elif [ $1!="output" ]
then
	echo exit
else
	echo "Good bye"
fi


# while循环
temp=$2
while [ $temp -lt 10 ]
do
	echo "whileing"
	temp=$(($temp+1))
done


# case的使用
case $temp in
	"10")
		echo "while正常执行"
		;;
	*)
		echo "while执行异常,temp=$temp"
		;;
esac

# 使用read进行终端读取
read -p "请随便输入:" input
echo "input=$input"


# 当前文件名为
echo "当前文件名为:$(basename $0)"
# 更改文件后缀
echo "文件名更换为txt:$(basename $0 .sh).txt"
# 当前文件的路径为
echo "当前文件的路径为:$(dirname $0)"


# 编写一个函数
func(){
	echo "函数func正在被调用"
	echo "传入func的参数为:$1,即文件路径"
	return 1;
}
# 调用这个函数
func "$0"
echo "函数的返回值为$?"

服务器巡检脚本

#!/bin/bash
#--------------------------------------------
# shell 服务器巡检示例
# author:zhouxx
#--------------------------------------------

#系统信息
os_system(){
os_type=`uname`
echo "当前系统是:$os_type"
os_banben=`cat /etc/redhat-release`
echo "当前系统版本是:$os_banben"
os_neihe=`uname -r`
echo "当前系统内核为:$os_neihe"
os_time=`date +%F_%T`
echo "当前系统实际为:$os_time"
os_last=`uptime |awk '{print $4 $5}'| awk -F , '{print $1}'`
echo "当前系统最后重启时间为:$os_last"
os_hostname=`hostname`
echo "当前系统主机名为:$os_hostname"
}
#网络信息
os_network(){
##主机IP地址
ip_addr=`ifconfig ens33| grep broadcast | awk '{print $2}'`
echo "当前系统ip为:$ip_addr"
##判断主机是否可以连通
ping -c1 www.baidu.com
if [ $? -eq 0 ];then
        echo "当前系统IP可以连通"
else
        echo "当前系统IP不通请联系管理员"
fi
##统计网卡流量
#流入流量
RX=`ifconfig ens33 | grep RX | head -n1 | awk '{print $3/1024/1024}'`
echo "网卡流入流量为:$RX"
#流出流量
TX=`ifconfig ens33 | grep TX | head -n1 | awk '{print $3/1024/1024}'`
echo "网卡流出流量为:$TX"
}

#硬件信息
cpu_info(){
#cpu的物理个数
cpu_phy=`cat /proc/cpuinfo | grep "physical id" | wc -l`
echo "当前系统物理cpu为:$cpu_phy"
#cpu的核心数
cpu_core=`cat /proc/cpuinfo | grep "core" | wc -l`
echo "当前系统cpu核心数为:$cpu_core"
#cpu的型号
cpu_model=`cat /proc/cpuinfo | grep "model" | sed -n '2p' | awk -F : '{print $2}'`
echo "当前系统cpu型号是:$cpu_model"
}
##内存信息
mem_info(){
mem_total=`free -m | grep Mem | awk '{print $2}'`
echo "内存总大小为:$mem_total"
mem_used=`free -m | grep Mem | awk '{print $3}'`
echo "已使用内存为:$mem_used"
mem_free=`free -m | grep Mem | awk '{print $4}'`
echo "剩余内存为:$mem_free"

#百分比
shiyong_free=`echo "scale=2;$mem_used/$mem_total*100"|bc`
echo "已使用内存百分比为:$shiyong_free"
shengyu_free=`echo "scale=2;$mem_free/$mem_total*100"|bc`
echo "剩余内存百分比为:$shengyu_free"
}
os_system
os_network
cpu_info
mem_info

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1918264.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

零基础小白人手必备“新华字典”,涵盖入门到进阶,超全语法!精炼总结64页,背完你的Python就牛了!

《Python背记手册》是一本旨在帮助初学者快速入门Python的实用手册&#xff0c;其特点鲜明&#xff0c;内容全面且易于理解。 书籍PDF已打包好&#xff0c;戳这里领取 一、书籍基本信息 作者&#xff1a;书籍的作者通常具有深厚的Python开发背景&#xff0c;有的作者是在美国攻…

MAVSDK示例takeoff_and_land编译与使用

1.克隆MAVSDK源码 ,示例位于源码的examples中 2.安装MAVSDK,下载https://github.com/mavlink/MAVSDK/releases/download/v2.12.2/mavsdk-windows-x64-release.zip 下载后解压:

三星首款智能戒指 Galaxy Ring 将于7月24日上市,售价399美元

三星电子即将推出其首款智能戒指——Galaxy Ring&#xff0c;这款创新的可穿戴设备将于7月24日上市&#xff0c;定价为399美元。Galaxy Ring的亮相标志着三星在智能穿戴设备领域的新突破&#xff0c;它不仅证明了三星在技术革新上的持续能力&#xff0c;也显示了其在健康和健身…

编号根据规则自增生成,及spring事务和锁

1、 背景 需要根据一些规则来生成自增编号&#xff0c;比如&#xff1a;95JS0001&#xff0c;950002 95JS是固定的&#xff0c;而后缀的0001的长度也是可配置的&#xff0c;因为有一张表来进行维护 CREATE TABLE number_control (id bigint NOT NULL AUTO_INCREMENT COMMENT 主…

DW03D是一款用于锂离子/聚合物电池保护的高集成度解决方案。DW03D包含内部功率MOSFET、高精度电压检测电路和延迟电路

一般概述 DW03D产品是单节锂离子/锂聚合物可充电电池组保护的高集成度解决方案。DW03D包括了先进的功率MOSFET&#xff0c;高精度的电压检测电路和延时电路。 DW03D具有非常小的TSS08-8的封装,这使得该器件非常适合应用于空间限制得非常小的可充电电池组应用。…

生信软件25 - 三代测序数据灵敏比对工具ngmlr

1. ngmlr简介 CoNvex Gap-cost Ments for Long Reads&#xff08;ngmlr&#xff09;是一种长reads比对工具&#xff0c;可以将PacBio或Oxford Nanopore灵敏地与&#xff08;大&#xff09;参考基因组&#xff08;比如人类参考基因组&#xff09;对齐&#xff0c;能快速和正确地…

OpenSSH Server远程代码执行漏洞 (CVE-2024-6387)|centos7升级到最新版本OpenSSH-9.8.p1

一、漏洞概述 漏洞名称 OpenSSH Server远程代码执行漏洞 CVE ID CVE-2024-6387 漏洞类型 竞争条件 发现时间 2024-07-01 漏洞评分 暂无 漏洞等级 高危 攻击向量 网络 所需权限 无 利用难度 高 用户交互 无 PoC/EXP 未公开 在野利用 未发现 OpenS…

MechMind结构光相机 采图SDK python调用

测试效果 Mech-Mind结构光相机 Mech Mind&#xff08;梅卡曼德&#xff09;的结构光相机&#xff0c;特别是Mech-Eye系列&#xff0c;是工业级的高精度3D相机&#xff0c;广泛应用于工业自动化、机器人导航、质量检测等多个领域。以下是对Mech Mind结构光相机的详细解析&#…

阿里巴巴国际站携手NBA传奇托尼·帕克,中国卖家又一波利好!

在全球化浪潮日益汹涌的今天&#xff0c;跨界合作已成为推动品牌国际化进程的重要力量。近日&#xff0c;阿里巴巴国际站宣布了一项震撼业界的合作——正式签约NBA&#xff08;美国职业篮球联赛&#xff09;传奇控球后卫托尼帕克&#xff08;Tony Parker&#xff09;作为其全球…

2024年10款免费的项目管理软件推荐

本文向大家推荐10款2024年免费使用的项目管理软件&#xff0c;其中包括桌面应用和基于Web平台的多种产品&#xff0c;同时还涵盖了一些优秀的开源软件。 1.禅道开源项目管理软件 禅道是一款开源的、基于Web的项目管理软件&#xff0c;其功能丰富且操作简便&#xff0c;为团队提…

生产管理系统功能全拆解:哪些功能是企业真正需要的?

制造业的伙伴经常听到“生产管理”&#xff0c;但很多人可能只是模糊地知道它与工厂、生产线有关。那么&#xff0c;到底什么是生产管理呢&#xff1f;它的重要性又体现在哪里呢&#xff1f;接下来&#xff0c;我就以轻松的方式&#xff0c;带大家走进生产管理的世界&#xff0…

笔记:Qt开发之工程的多模块设计(pri)

目标&#xff1a;对于功能模块较多的Qt项目&#xff0c;使用pri文件管理模块文件&#xff0c;降低工程复杂度&#xff0c;提高软件模块的封装性和重用性。 一、知识储备 1.1 pro与pri文件 对于模块化编程&#xff0c;Qt提供了pro和pri&#xff0c;pro管理项目&#xff0c;pri…

算法 —— 模拟

目录 替换所有的问号 提莫攻击 Z字形变换 外观数列 各位读者有听说过“建模”一词吗&#xff1f;所谓“建模”&#xff0c;就是把事物进行抽象&#xff0c;根据实际问题来建立对应的数学模型。“抽象”并不意味着晦涩难懂&#xff1b;相反&#xff0c;它提供了大量的便利。…

新兴商业模式如何破局?市场策划专家的实战指南

在这个融合了传统市场、互联网和信息技术的大潮中&#xff0c;想要在市场营销策划上玩得转&#xff0c;咱们得有超凡的全局思维和跨界的协作精神。 下面&#xff0c;我就来和大家聊聊如何在这样一个复杂环境下搞定市场营销策划&#xff0c;让你在竞争激烈的市场中脱颖而出。 …

Ubuntu编译PX4固件

目录 前言 准备编译参考 前言 要想自己编译PX4固件需要交叉编译器&#xff0c;交叉编译器可以将 x86架构 平台上写好程序编译出来&#xff0c;而编译出来的可执行文件是能用到 arm架构 的平台上。 本次编译是以 px4 v1.13.2 为例。 我的配置如下&#xff1a; 虚拟机 Ubuntu 18…

微气象仪的工作原理

型号推荐&#xff1a;云境天合TH-WQX5】风力发电传感器在风力发电系统中起着至关重要的作用&#xff0c;它们能够实时监测和记录各种关键参数&#xff0c;为风力发电机组的控制提供数据支持&#xff0c;从而确保风力发电系统的安全、高效运行。以下是对风力发电传感器的详细解析…

喜讯|华院计算法律大模型入围《2024大模型典型示范应用案例集》

2024年世界人工智能大会&#xff08;WAIC&#xff09;举办期间&#xff0c;中国信通院正式发布了《2024大模型典型示范应用案例集》&#xff08;以下简称《案例集》&#xff09;。该案例集由中国信通院华东分院、上海人工智能实验室主导&#xff0c;以产业化为导向&#xff0c;…

Vue从零到实战第一天

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

免费分享:中国冬小麦地图数据集(附下载方法)

小麦按播种和收获季节的不同&#xff0c;可分为春小麦和冬小麦两种。春小麦颗粒长而大&#xff0c;皮厚色泽深&#xff0c;蛋白质含量高&#xff0c;但筋力较差&#xff0c;出粉率低&#xff0c;吸水率高;冬小麦颗粒小&#xff0c;吸水率低&#xff0c;蛋白质含量较春小麦少&am…

element-plus 按需导入问题 404等问题

场景 新开一个项目&#xff0c;需要用element-plus这个ui库&#xff0c;使用按需引入。 这是我项目的一些版本号 "element-plus": "^2.7.6","vue": "^3.2.13","vue-router": "^4.0.3",过程&#xff08;看解决方法…