shell编程基础

shell · 浏览次数 : 17

小编点评

Shell 脚本编程基础教程 简介 ---- Shell 是一种解释型脚本语言,用于自动化操作系统任务。它支持大多数编程语言具备的功能,如条件判断、循环、函数等。 编写规范 ---- 1. 使用 `#!/bin/bash` 指定解释器。 2. 注释以 `#` 开头。 3. 功能:输出 "Hello, World!"。 示例: ```bash #!/bin/bash echo "Hello, World!" ``` 编写一个脚本自动配置本地 yum 仓库 --------- ```bash #!/bin/bash cat<< EOF > /etc/yum.repos.d/local.repo [BaseOS] name=Local BaseOS baseurl=file:///mnt/cdrom/BaseOS enabled=1 gpgcheck=0 [AppStream] name=Local AppStream baseurl=file:///mnt/cdrom/AppStream enabled=1 gpgcheck=0 EOF sleep 2 echo "======永久挂载光驱======" >> /etc/fstab sleep 2 echo "======检查软件包数量======" | wc -l ``` 脚本的执行方式 -------- 1. 通过绝对路径或相对路径执行脚本。 2. 使用 `source` 或点(.)执行脚本文件。 父子和 shell 问题 --------- 通过 `ps` 命令查看当前 shell 进程的子进程。使用 `source` 或点(.)执行脚本时,脚本在同一 bash 环境下执行,而使用 `bash` 或路径执行时,会在子 shell 中执行。 变量 ---- 1. 变量分为系统定义变量和位置/预定义变量。 2. 变量名必须唯一,可以使用双引号或单引号界定范围。 3. 变量值可以是数字、字符串或数组。 示例: ```bash #!/bin/bash name="User123" echo $name ``` 环境变量 -------- 1. 环境变量分为全局变量和局部变量。 2. 全局变量在父 shell 和子 shell 中都可以使用。 3. 局部变量仅在当前 shell 中有效。 示例: ```bash #!/bin/bash export name="User123" echo $name ``` 特殊符号 ---- 1. 双引号用于引用整体文本,单引号用于引用整体文本并取消特殊字符含义。 2. 使用 `$()` 或 `` ` `` 取命令结果作为参数。 示例: ```bash #!/bin/bash a="123" echo $a ``` 交互式输入变量 -------- 使用 `read` 命令接受用户输入。 示例: ```bash #!/bin/bash read -p "Enter your name: " name echo "Hello, $name!" ``` 屏蔽回显 ------ 使用 `stty -echo` 禁止回显,使用 `stty echo` 恢复回显。 示例: ```bash #!/bin/bash stty -echo read -p "Enter your password: " pass echo "Password: $pass" stty echo ``` 总结 -- 本教程介绍了 Shell 脚本编程的基础知识,包括其定义、执行方式、变量、特殊符号以及交互式输入。掌握这些基础知识有助于编写高效的 Shell 脚本。

正文

shell脚本编程基础

【1】、shell概述

  • shell是一门编程语言,如:C、C++、java、PHP、python Go等

  • 语言分类

    编程型语言:C、C++、Go等为编译型语言。程序运行需要提前编译,编译语言都有编译器

    解释型语言:shell、PHP、python等为解释型语言,程序在运行时不需要提前编译,一边执行,一边解释,每种解释型语言都有解释器

  • shell语言支持大部分编程语言都具备的功能:if判断、for循环、函数、数组、加减乘除、逻辑运算等

  • 脚本的本质就是命令的堆积

【2】、shell编写规范

系统解释器

[root@xu script]# cat /etc/shells
/bin/sh		#Unix解释器
/bin/bash	#Linux默认解释器
/usr/bin/sh
/usr/bin/bash

这就是一个简单的shell script,在我们编写完成后,要给script加上可执行的权限

#!/bin/bash
#首先要进行环境指定,指定编译器,一般我们会使用/bin/bash,标准解释器
# '#'表示注释、‘#!’表示指定解释器

#功能:输出hello world
echo hello world

在脚本中不能出现交互式命令

#例如创建用户并且给用户设置密码
#!/bin/bash
#creat user
useradd zhanghaowei
echo 123 | passwd --stdin zhanghaowei
#我们使用设置密码的方式采用非交互式的方式

【3】、如何写好一个shell脚本

  • 明确任务需求
  • 按照需求整理好每一个步骤,先后顺序
  • 运行脚本,并根据运行结果排除错误
  • 优化脚本并达到最后的结果
  • 脚本程序规范
    • 声明解释器(shebang)

      • !/bin/bash

    • 注释

      • 对脚本的描述
    • 执行指令

      • Linux命令

【4】、编写脚本

  • 自动配置本地yum仓库的脚本

    [BaseOS]
    name=local_BaseOS
    baseurl=file:///mnt/cdrom/BaseOS
    enable=1
    gpgcheck=0
    
    [AppStream]
    name=local_AppStream
    baseurl=file:///mnt/cdrom/AppStream
    enable=1
    gpgcheck=0
    EOF
    
    sleep 2
    echo "======永久挂载光驱======"
    echo "/dev/cdrom        /mnt/cdrom      iso9660 defaults        0 0" >> /etc/fstab
    
    sleep 2
    echo "======检查软件包数量======"
    yum list | wc -l
    

【5】、脚本的执行方式

  • 方式一:赋予脚本执行权限后,可用绝对路径和相对路径执行

  • 方式二:调用解释器执行脚本文件,会开启jie'shi'q

  • 方式三:source和 . :执行脚本文件

  • #绝对路径执行脚本
    [root@xu script]# /script/hello.sh 
    hello world
    #相对路径执行脚本
    [root@xu script]# ./hello.sh 
    hello world
    
  • #调用解释器执行脚本,调用解释器时可以不给执行权限
    [root@xu script]# bash /script/hello.sh 
    hello world
    
  • 父子shell问题

    #我们知道脚本的执行是通过调用bash解释器去执行,我们通过sshd连接一个会话可以存在多个bash进程
    ─sshd(1065)───sshd(1896)───sshd(1900)───bash(1901)───bash(2093)───bash(2114)───pstree(2135)
    #通过pstree我们可以看到当前session存在多个bash环境,都是由systemd进程创建出来的,而我们现在处于bash(2114)环境中,如果此时我们执行脚本采用的环境时bash(2114)环境。
    #如果我们使用路径(source)去执行脚本和使用bash去执行脚本就会产生区别
    #采用.(source)去执行脚本,是在当前的bash环境下执行的,而使用bash或path去执行脚本则是在当前的bash环境下创建出一个子bash去执行脚本,并切换当前环境为新的脚本
    

【6】、变量

  • shell中变量类型只有string,没有别的;比方说在python中变量是有不同的类型的(list、dic、str。。。),但是在shell中只有str.

  • 变量的存在让脚本变得更加灵活,能够应对不同的场景

  • 语法:变量名="变量值"

  • $:调用变量

    [root@xu ~]# name=$(hostname)
    [root@xu ~]# echo $name
    xu
    

1、变量分类

(1)、系统定义变量

# 系统自定义的系统变量
[root@moudle01 17:23:53  /script]# echo $PWD
/script
[root@moudle01 17:23:59  /script]# echo $SHELL
/bin/bash
[root@moudle01 17:24:05  /script]# echo $HOME
/root
[root@moudle01 17:24:14  /script]# echo $USER
root
[root@moudle01 17:24:51  /script]# echo $UID
0

(2)、位置变量和预定义变量

在shell中也存在着和C语言相似的参数传递问题

只不过在shell中的参数问题是通过命令去完成的,我们在执行一个shell scrip时可以写上参数,将参数传递进shell script,同时在shell中去接收通过命令传入的参数。

位置参数:在执行脚本的命令中写上的参数就是位置参数,从1开始

在接收时可以使用以下标识符

  • $0:提取文件名(用source执行脚本时,不显示文件名而是解释器名字)
  • ${1}:提取位置参数为1的值
  • ...
  • ${20}: 提取位置参数为20的值
  • $*:接收所有参数
  • $@:接收所有参数
  • $$:提取当前进程的PId
  • $?:上一条命令的执行结果(上一个程序/命令的返回状态码)
  • $#:所有参数个数
#!/bin/bash
echo $1
echo $2
echo $3
echo $0
echo $*
echo $#
echo $$
echo $?
[root@moudle01 21:10:40  /script]# bash test04.sh  a b c d
a
b
c
test04.sh
a b c d
4
2728
0
[root@moudle01 21:18:33  /script]# kjasdhfsdlgasgasgadfg
-bash: kjasdhfsdlgasgasgadfg: command not found
[root@moudle01 21:18:45  /script]# echo $?
127
[root@moudle01 21:18:49  /script]# echo $?
0

创建用户tom,密码123

#!/bin/bash
  
useradd $1
echo $2  | passwd --stdin $1

2、env和set

env:所有环境变量

set:所有变量

[root@moudle01 21:30:10  /script]# abcd=6666666
[root@moudle01 21:30:55  /script]# set | grep abcd
abcd=6666666
[root@moudle01 21:31:00  /script]# env | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

3、常用的特殊符号

  • “”:双引号,引用整体,界定范围

  • ‘’:单引号,引用整体,并且取消所有特殊字符含义,界定范围

    [root@moudle01 21:32:13  /script]# a="  a"
    [root@moudle01 21:36:17  /script]# echo "$a"
      a
    # 如果有特殊符号,定义时单引号和双引号都行,在引用时只能使用双引号
      [root@moudle01 21:36:25  /script]# echo '$a'
    $a
    
    
  • $[]、$(())、expr:四则运算

    [root@xu script]# echo $[1+1]
    2
    [root@xu script]# echo $[2*3]
    6
    [root@xu script]# echo $[2-3]
    -1
    [root@xu script]# echo $[6/3]
    2
    [root@xu script]# echo $[10%3]
    1
    # expr 运算符号两侧必须加空格
    [root@moudle01 16:13:56  ~]# expr 1 + 1
    2
    
  • $():取命令结果作为参数

  • ``:反撇号,将命令的输出结果作为参数

    [root@moudle01 21:40:57  /script]# date
    Wed Jun 12 21:41:07 CST 2024
    [root@moudle01 21:38:26  /script]# a=`date`
    [root@moudle01 21:40:54  /script]# echo $a
    Wed Jun 12 21:40:54 CST 2024
    [root@moudle01 21:41:07  /script]# x=$(ls)
    [root@moudle01 21:42:37  /script]# echo $x
    abc rsync_inotify.sh test01.sh test02.sh test03.sh test04.sh test05.sh
    

4、read

交互式输入变量

[root@moudle01 21:48:04  /script]# read -p "请输入:" a
请输入:123
[root@moudle01 21:48:47  /script]# echo $a
123
#!/bin/bash
read -p "请输入要创建的用户名:" a
useradd $a
read -p "请输入用户的密码:" p
echo $p  | passwd --stdin $a

[root@moudle01 21:50:41  /script]# source test05.sh 
请输入要创建的用户名:xxx
请输入用户的密码:123
Changing password for user xxx.
passwd: all authentication tokens updated successfully

5、屏蔽回显

在敲完之后,你在后面输入的所有内容都看不到

[root@moudle01 21:51:16  /script]# stty -echo

显示回显

[root@moudle01 21:51:16  /script]# stty echo

写入创建用户的脚本,让密码输入更加安全

#!/bin/bash
read -p "请输入要创建的用户名:" a
useradd $a
stty -echo
read -p "请输入用户的密码:" p
stty echo
echo ""
echo $p  | passwd --stdin $a

[root@moudle01 21:59:24  /script]# source test05.sh 
请输入要创建的用户名:aaa
请输入用户的密码:
Changing password for user aaa.
passwd: all authentication tokens updated successfully.

6、export命令

  • 环境变量(全局变量):系统在全局生效的变量

    普通变量(局部变量):只针对局部环境生效,如当前某一个login.bash脚本生效

    全局变量和局部变量就是相对于父子shell(bash)。环境变量(全集变量)就是父shell也可以使用,普通变量(局部变量)只有子shell可以使用

  • 变量生存周期

    1、永久变量:写入文件,反复读取、加载,让其永久生效,如/etc/profile的PATH修改

    2、临时变量:如命令行export定义的一个变量存储数据,关闭shell后失效

  • 在定义变量时有两种选择

  • 1、加export:在父shell中定义的变量可以在子shell中去使用,也就是全局变量

    • [root@xu ~]# export name="xuruizhao"
      [root@xu ~]# echo ${name}
      xuruizhao
      [root@xu ~]# bash
      Skill is acquired through repeated practice, and practice makes perfect.
      [root@xu ~]# bash
      Skill is acquired through repeated practice, and practice makes perfect.
      [root@xu ~]# echo ${name}
      xuruizhao
      

    2、不加export:只对当前的shell有效,子shell看不到,也就是局部变量

    • [root@xu ~]# name="hello world"
      [root@xu ~]# echo ${name}
      hello world
      [root@xu ~]# bash
      #我们切换了bash环境,也就是进入了子shell,由于没有加export子shell中是不能使用父shell中定义的变量
      Skill is acquired through repeated practice, and practice makes perfect.
      [root@xu ~]# echo ${name}
                              
      [root@xu ~]# 
      

7、let定义变量

使用let定义变量,可以在定义时进行计算

[root@moudle01 22:13:42  /script]# let a=1+1
[root@moudle01 22:14:21  /script]# echo $a
2
[root@moudle01 22:16:30  /script]# let a+=3
[root@moudle01 22:16:35  /script]# echo $a
5

8、bc命令

上面的运算均不支持小数

bc命令支持小数

[root@moudle01 16:13:58  ~]# echo "1.1+1" | bc
2.1

9、变量定义初值

#!/bin/bash
  
read -p "请输入用户名" username
if [ -z $username ];then
    echo "用户名不能为空" && exit
fi
useradd $username
read -p "请输入密码" pass
echo ${pass:-123456} | passwd --stdin $username
[root@moudle01 11:37:41  /script]# bash user_add02.sh 
请输入用户名
用户名不能为空

【7】、变量测试

两种测试格式

test

[]

1、字符串

(1)、数组测试

== 判断是否相同

! = 判断两侧是否不等

[root@moudle01 16:29:46  ~]# a=1
[root@moudle01 16:29:51  ~]# b=2
[root@moudle01 16:29:52  ~]# [ $a != $b ]
[root@moudle01 16:30:04  ~]# echo $?
0

如果一个变量值为空,我们在进行比较时,

1、可以加上双引号

2、-z:判断变量是否为空

​ ! -Z/-n:判断变量是否非空

 
[root@moudle01 16:33:11  ~]# [ a == "$c" ]
[root@moudle01 16:33:23  ~]# echo $?
1
[root@moudle01 16:33:27  ~]# [ -z "$c" ]
[root@moudle01 16:35:13  ~]# echo $?
0
[root@moudle01 16:35:16  ~]# [ -z "$a" ]
[root@moudle01 16:35:22  ~]# echo $?
1
[root@moudle01 16:38:16  ~]# c=123
[root@moudle01 16:38:23  ~]# [ -n "$c" ] 
[root@moudle01 16:38:26  ~]# echo $?
0

(2)、逻辑测试

&&与

||或

#!/bin/bash
  
[ $USER == root ] || echo "非管理员禁止执行该脚本" && exit
yum -y install vsftpd > /dev/null
systemctl start vsftpd
systemctl enable vsftpd
# 只有root用户可以执行此脚本
#!/bin/bash
  
[ $USER != root ] && echo "非管理员禁止执行" && exit2
yum -y install vsftpd > /dev/null
systemctl start vsftpd
systemctl enable vsftpd
[root@moudle01 16:57:25  /script]# ls a ||  ls b && ls c || ls && ls /etc/yum.repos.d/
a
c
bak  epel  local_yum_house.repo

2、数字

-eq:相等

-ne:不相等

-gt:大于

-ge:小于等于

-lt:小于

-le:小于等于

#!/bin/bash
  
[ $# -ne 2 ] && echo "输入变量数量错误" && exit
useradd $1
echo $2  | passwd --stdin $1

3、文件

-e:判断文件是否存在,不关心文件类型

-f:判断文件是否存在,必须是普通文件

-d:判断文件是否存在,必须是目录

[root@moudle01 17:19:49  /script]# [ -e a ]
[root@moudle01 17:20:00  /script]# echo $?
0
[root@moudle01 17:20:03  /script]# [ -d a ]
[root@moudle01 17:20:09  /script]# echo $?
1
[root@moudle01 17:20:10  /script]# [ -f x ]
[root@moudle01 17:20:21  /script]# echo $?
1

-r:判断当前用户对文件是否有读权限(对root无效,只针对普通用户)

-w:判断当前用户对文件是否有写权限(对root无效,只针对普通用户)

-x:判断当前用户对文件是否有x权限

[root@moudle01 17:21:45  /script]# [ -r a ]
[root@moudle01 17:22:02  /script]# echo $?
0
[root@moudle01 17:22:05  /script]# [ -w a ]
[root@moudle01 17:22:09  /script]# echo $?
0
[root@moudle01 17:22:10  /script]# [ -x a ]
[root@moudle01 17:22:17  /script]# echo $?
1

4、编写脚本

每隔两分钟检查服务器的账户数量,如果发现增加,则给管理员发邮件

#!/bin/bash
  
num=$(cat /etc/passwd | wc -l)
[ num -gt 38 ] && echo "用户增加" | mail -s "user_info" root

# 编写计划任务
*/2 * * * * /script/test02.sh

与shell编程基础相似的内容:

shell编程基础

shell脚本编程基础 【1】、shell概述 shell是一门编程语言,如:C、C++、java、PHP、python Go等 语言分类 编程型语言:C、C++、Go等为编译型语言。程序运行需要提前编译,编译语言都有编译器 解释型语言:shell、PHP、python等为解释型语言,程序在运行时不

Linux-shell编程入门基础

本篇文章就是一个过渡学习的,先入门shell脚本,由于作者有编程基础,所以有些解释的比较少。由于现在还在努力学习中,以后等本散修进阶了之后再写进阶的、与网络安全更加贴合的shell编程

[转帖]40张图入门Linux——(前端够用,运维入门)

本文主要是Linux的入门内容,利用40张思维导图从基础、操作、实用指令、组管理和权限管理、crond任务调度、Linux磁盘分区和挂载、Linux网络环境配置、进程管理、服务管理、RPM和YUM、软件安装关键点、Shell编程共十二部分着手,从而系统的了解一下Linux(基于Centos),本文的

[转帖]Bash脚本编程学习笔记02:脚本基础和bash配置文件

脚本基础 参考资料:Shell Scripts (Bash Reference Manual) 不严谨地说,编程语言根据代码运行的方式,可以分为两种方式: 编译运行:需要先将人类可识别的代码文件编译成机器可运行的二进制程序文件后,方可运行。例如C语言和Java语言。 解释运行:需要一个编程语言的解释

[转帖]学习如何编写 Shell 脚本(基础篇)

https://juejin.cn/post/6930013333454061575 前言 如果仅仅会 Linux 一些命令,其实已经可以让你在平时的工作中游刃有余了。但如果你还会编写 Shell 脚本(尤其是前端工程师),它会令你“添光加彩”。如果本文对你有所帮助,请点个👍 👍 👍 吧。 S

shell 编程简记

1. 环境变量 环境变量是指操作系统中记录一些配置信息的变量,这些变量在不同的程序之间共享,可以被操作系统或者 shell 脚本读取和修改。 环境变量也可以类比为各个语言中的全局变量,其作用域是全局的,所有的代码段或者说作用域都可以直接访问到这个变量。 1.1 查看环境变量 查看你环境变量的命令是

[转帖]shell编程-字符截取命令

grep 命令 命令格式: grep [选项] 查找的字符串 文件名 作用: 在文件中搜索查找字符串,显示匹配字符串所在的行。 选项: -i:查找时忽略大小写。-n:显示行号。-v:反向查找(把不含有要搜索字符串的所有行显示出来)。-c:计算匹配到 ‘搜寻字符串’ 的次数。-r:在指定的目录中查找,

[转帖]Shell编程之免交互

目录 交互的概念与Linux中的运用Here Document 免交互tee命令重定向输出加标准输出支持变量替换多行注释Expect实例操作免交互预设值修改用户密码创建用户并设置密码实现 ssh 自动登录 交互的概念与Linux中的运用 交互:当计算机播放某多媒体程序的时候,编程人员可以发出指令控制

[转帖]Shell编程之函数

目录 Shell函数使用Shell函数的优点 Shell 函数定义使用原则函数传参函数变量的作用范围 函数递归阶乘递归目录函数库 Shell函数 将命令序列按格式写在一起可方便重复使用命令序列Shell函数定义 调用函数的方法 使用Shell函数的优点 使用函数可以避免代码重复使用函数可以将大的工程

[转帖]Shell编程之正则表达式与文本处理器(grep、sort、uniq、tr、cut)

目录 正则表达式概念正则表达式的作用元字符grep命令在文本中查找指定的字符串sort命令排序uniq命令快捷去重tr命令替换、压缩和删除cut命令快速裁剪命令expr substr 截取方法cut截取方法 split命令文件拆分paste命令文件合并eval变量扫描器位置锚定分组或其他扩展正则表达