IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> shell 脚本初识 -> 正文阅读

[系统运维]shell 脚本初识

一、shell 脚本初识

  • 脚本:本质是一个文件,文件里面存放的是 特定格式的指令,系统可以使用脚本解析器 翻译或解析 指令 并执行(它不需要编译)
  • shell 既是应用程序 又是一种脚本语言(应用程序 解析 脚本语言)
  • 作用:通过命令行解析的方式,自动执行设定好的程序或命令代码。(若将脚本挂到定时任务中,就会自动在非工作时间里自动触发执行程序)

1、创建 shell 脚本

Shell脚本文件以“.sh”结尾

#新建文件的linux命令
touch helloworld.sh  # 在当前目录下创建
#打开文件
vim helloworld.sh 
1、输入 i 进入文件编辑模式
2、编辑内容
3、esc 退出编辑模式
4、:wq 保存并退出
  • 查看自己 linux 系统的默认解析:echo $SHELL
[root@hecs-x-medium-2-linux-20211111093159 ~]# echo $SHELL
/bin/bash
  • 查看系统支持的 Shell
[root@hecs-x-medium-2-linux-20211111093159 ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
  • 规范的Shell脚本第一行会指出由哪个程序(解释器)来执行脚本中的内容。在linux bash编程中一般为:#!/bin/bash (表示该脚本运用/bin/bash命令进行解析)【#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell】/bin/bash就是指明了解释器的具体位置。
#!/bin/bash
# 第一个shell小程序,echo 是linux 中输出命令
hello="hello world"
echo $hello
echo "helloworld!"

在这里插入图片描述

2、执行脚本的方式

2.1 在新进程中运行 Shell 脚本

  • 方法一:/bin/sh是bash的软链接,也就是说我么既可以用sh执行也可以用bash执行脚本
[root@hecs-x-medium-2-linux-20211111093159 ~]# sh helloworld.sh 
hello world
helloworld!
[root@hecs-x-medium-2-linux-20211111093159 ~]# bash helloworld.sh 
hello world
helloworld!
  • 方法二:以绝对路径的方式执行脚本(前提:将该脚本添加x执行权限 )
[root@hecs-x-medium-2-linux-20211111093159 ~]# chmod +x helloworld.sh  # 加上可执行权限
[root@hecs-x-medium-2-linux-20211111093159 ~]# /root/helloworld.sh 
hello world
helloworld!
  • 方法三:以相对路径的方式执行脚本(前提:将该脚本添加x执行权限 )
[root@hecs-x-medium-2-linux-20211111093159 ~]# chmod +x helloworld.sh  -- 同一个文件只需加一次
[root@hecs-x-medium-2-linux-20211111093159 ~]# ./helloworld.sh 
hello world
helloworld!

测试:

[root@hecs-x-medium-2-linux-20211111093159 ~]# echo $$
32257 # 当前进程号
[root@hecs-x-medium-2-linux-20211111093159 ~]# ./helloworld.sh 
3202 # 新进程
[root@hecs-x-medium-2-linux-20211111093159 ~]# echo $$
32257 
[root@hecs-x-medium-2-linux-20211111093159 ~]# bash helloworld.sh 
3221 # 新进程

2.2 在当前进程中运行 Shell 脚本

  • 方法四:以source脚本路径的方式执行脚本(等同于“.脚本路径” )只在当前环境生效【这里需要引入一个新的命令——source 命令。source 是 [Shell 内置命令] 的一种,它会读取脚本文件中的代码,并依次执行所有语句。你也可以理解为,source 命令会强制执行脚本文件中的全部命令,而忽略脚本文件的权限。】
[root@hecs-x-medium-2-linux-20211111093159 ~]# source helloworld.sh 
hello world
helloworld!
[root@hecs-x-medium-2-linux-20211111093159 ~]# . yunjisuan.sh  -- 注意此处一定要用空格隔开
hello world
helloworld!

测试:

[root@hecs-x-medium-2-linux-20211111093159 ~]# echo $$
32257
[root@hecs-x-medium-2-linux-20211111093159 ~]# source helloworld.sh 
32257  # 与当前进程号一致,说明是同一个进程

2.3 每一种方法运行的比较

./xxx.sh :先按照 文件中#!指定的解析器解析
如果#!指定指定的解析器不存在 才会使用系统默认的解析器

bash xxx.sh:指明先用bash解析器解析
如果bash不存在 才会使用默认解析器

. xxx.sh 直接使用默认解析器解析

3、shell 脚本的编写入门

  • -n 的认识
[root@hecs-x-medium-2-linux-20211111093159 ~]# echo -n "hello world"
hello world[root@hecs-x-medium-2-linux-20211111093159 ~]# 
# 如上代码:默认情况下 echo 是会换行的,在 echo 后面加上 -n 就不会换行了
hello world[root@hecs-x-medium-2-linux-20211111093159 ~]# read -n 1 sex
1[root@hecs-x-medium-2-linux-20211111093159 ~]# 
# -n 选项表示读取固定长度的字符串,那么它后面必然要跟一个数字用来指明长度,否则选项是不完整的。
  • 输入多行
[root@hecs-x-medium-2-linux-20211111093159 ~]# echo "
> hhh
> hello
> "

hhh
hello

3.1 变量的定义、引用及清除变量值

  • 赋值号=的周围不能有空格
  • 变量名由数字、字母、下划线组成;
  • 必须以字母或者下划线开头;
  • 不能使用 Shell 里的关键字(通过 help 命令可以查看保留关键字)。

以下代码不一定要在 shell 脚本中写

#!/bin/bash
num=100 # 定义变量  变量名=变量值
echo $num # 引用变量 $变量名
unset num # unset :清除变量值
echo $num

也可以

[root@hecs-x-medium-2-linux-20211111093159 ~]# name=yangzhi
[root@hecs-x-medium-2-linux-20211111093159 ~]# echo $name
yangzhi
# 变量名外面的花括号{ }是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界
[root@hecs-x-medium-2-linux-20211111093159 ~]# echo ${name} 
yangzhi
# 推荐给所有变量加上花括号{ },这是个良好的编程习惯。

执行上述文件结果如下:

[root@hecs-x-medium-2-linux-20211111093159 ~]# bash t_1.sh 
100

  • 将命令的结果赋值给变量
variable=`command`
variable=$(command)
# 第一种方式把命令用反引号` ` 包围起来,反引号和单引号非常相似,容易产生混淆,所以不推荐使用这种方式;第二种方式把命令用$()包围起来,区分更加明显,所以推荐使用这种方式。detail=$(ls) # 查看当前目录下的所有文件

例如,我在 当前目录中创建了一个名为 log.txt 的文本文件,用来记录我的日常工作。下面的代码中,使用 cat 命令将 log.txt 的内容读取出来,并赋值给一个变量,然后使用 echo 命令输出。

[root@hecs-x-medium-2-linux-20211111093159 ~]# log=$(cat log.txt)
[root@hecs-x-medium-2-linux-20211111093159 ~]# echo $log
hello world!

3.2 从键盘获取值read

#!/bin/bash
num=10
echo "num=$num"
echo "请输入num的值"
read num  # 读取键盘输入值
echo "num=$num"

执行上述文件结果如下:

[root@hecs-x-medium-2-linux-20211111093159 ~]# bash t_2.sh 
num=10
请输入num的值
200
num=200
  • 在一行上显示和添加提示 需要加上-p
#!/bin/bash
num=10
echo "num=$num"
read -p "请输入num的值:" num
echo "num=$num"

执行上述文件结果如下:

[root@hecs-x-medium-2-linux-20211111093159 ~]# bash t_3.sh 
num=10
请输入num的值:200
num=200
  • 读取多个值
#!/bin/bash
num=10
echo "num=$num"
read -p "请输入num的值:" num
echo "num=$num"
read data1 data2
echo "data1=$data1"
echo "data2=$data2"

执行上述文件结果如下:

[root@hecs-x-medium-2-linux-20211111093159 ~]# bash t_4.sh 
num=10
请输入num的值:88
num=88
100 89
data1=100
data2=89

3.3 readonly 只读变量

#!/bin/bash
readonly num=10
echo "num=$num"
num=200 # 修改 num 的值失败
echo "num=$num"

执行上述文件结果如下:

[root@hecs-x-medium-2-linux-20211111093159 ~]# bash t_5.sh 
num=10
t_5.sh: line 4: num: readonly variable
num=10

注意点:readonly 只读变量是无法删除的

验证:

[root@hecs-x-medium-2-linux-20211111093159 ~]# readonly age=10
[root@hecs-x-medium-2-linux-20211111093159 ~]# unset age
-bash: unset: age: cannot unset: readonly variable

3.4 预设变量

$# : 传给shell脚本参数的数量
$* : 传给shell 脚本参数的内容
$1$2$3...、$9 : 运行脚本时传递给其的参数,用空格隔开
$? : 命令执行后返回的状态
"$?" 用于检查上一个命令执行是否正确(在Linux 中,命令退出状态为 0 表示该命令正确执行,任何非 0 值表示命令出错)$0 : 当前执行的进程名
$$ : 当前进程的进程号
"$$" 变量最常见的用途是用作临时文件的名字以保证临时文件不会重复

测试:

#!/bin/bash
echo "参数的个数=$#"
echo "参数的内容=$*"
echo "第一个参数:$1"
echo "第二个参数:$2"
echo "第三个参数:$3"
readonly data=10
data=250
echo "data=250的结果:$?"
echo "进程名:$0"
echo "进程号:$$"

执行上述文件结果如下:

[root@hecs-x-medium-2-linux-20211111093159 ~]# bash helloworld.sh a b c
参数的个数=3
参数的内容=a b c
第一个参数:a
第二个参数:b
第三个参数:c
helloworld.sh: line 8: data: readonly variable
data=250的结果:1
进程名:helloworld.sh
进程号:12612

3.5 脚本标量的特殊用法

在这里插入图片描述

#!/bin/bash
echo "today is `date`"

执行上述文件结果如下:

[root@hecs-x-medium-2-linux-20211111093159 ~]# bash helloworld.sh 
today is Thu Nov 18 21:19:28 CST 2021
#!/bin/bash
echo "##\n##"
echo -e "&&\n&&"

执行上述文件结果如下:

[root@hecs-x-medium-2-linux-20211111093159 ~]# bash helloworld.sh 
##\n##
&&
&&
#!/bin/bash
data=10
(
 # 子 shell 完成 不会影响当前 shell 的值
 data=100
 echo "()里面的data=$data"
)
echo "当前data=$data"

执行上述文件结果如下:

[root@hecs-x-medium-2-linux-20211111093159 ~]# bash helloworld.sh 
()里面的data=100
当前data=10
#!/bin/bash
data=10
{
# 子 shell 完成 会影响当前 shell 的值
 data=100
 echo "{}里面的data=$data"
}
echo "当前data=$data"

执行上述文件结果如下:

[root@hecs-x-medium-2-linux-20211111093159 ~]# bash helloworld.sh 
{}里面的data=100
当前data=100

3.6 变量的扩展

  • 字符串的操作
    在这里插入图片描述
#!/bin/bash
str="hello:abc:lisi:zhang"
# 测量字符串的长度${#str}
echo "str长度:${#str}"
# 从下标3开始为位置提取${str:3}
echo ${str:3}
# 从下标3的位置开始提取4字节
echo ${str:3:4}
# ${str/old/new} 用new替换str中出现的第一个old
echo ${str/:/#}
# ${str//old/new} 用new替换str中所有的old
echo ${str//:/&}

执行上述文件结果如下:

[root@hecs-x-medium-2-linux-20211111093159 ~]# bash helloworld.sh 
str长度:20
lo:abc:lisi:zhang
lo:a
hello#abc:lisi:zhang
hello&abc&lisi&zhang

3.7 查看环境变量:env

[root@hecs-x-medium-2-linux-20211111093159 ~]# env
XDG_SESSION_ID=189
HOSTNAME=hecs-x-medium-2-linux-20211111093159
TERM=xterm
SHELL=/bin/bash
HISTSIZE=10000
SSH_CLIENT=116.22.199.248 4673 22
SSH_TTY=/dev/pts/1
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/musicProject/jdk/jdk1.8.0_211/bin:/root/bin
PWD=/root
JAVA_HOME=/musicProject/jdk/jdk1.8.0_211
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
CLASSPATH=.:/musicProject/jdk/jdk1.8.0_211/jre/lib/rt.jar:/musicProject/jdk/jdk1.8.0_211/lib/dt.jar:/musicProject/jdk/jdk1.8.0_211/lib/tools.jar
SSH_CONNECTION=116.22.199.248 4673 192.168.0.212 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
HISTTIMEFORMAT=%F %T root 
_=/usr/bin/env

3.8 注意事项

  1. 变量名只能包含英文字母下划线,不能以数字开头。1_num=10 错误 num_1=20 正确

  2. 等号两边不能直接接空格符,若变量中本身就包含了空格,则整个字符串都要用双引号、或单引号括起来

  3. 双引号 单引号的区别

    双引号:可以解析变量的值
    单引号:不能解析变量的值

echo "hello=$hello"  # $hello 当成变量的值处理
echo 'hello=$hello'  # $hello 当成字符串处理

3.9 Shell 数组的定义

在 Shell 中,用括号( )来表示数组,数组元素之间用空格来分隔。由此,定义数组的一般形式为:

array_name=(ele1  ele2  ele3 ... elen)

注意,赋值号=两边不能有空格,必须紧挨着数组名和数组元素。

nums=(29 100 13 8 91 44)
  • Shell 是弱类型的,它并不要求所有数组元素的类型必须相同,例如:
arr=(20 56 "http://c.biancheng.net/shell/")
  • Shell 数组的长度不是固定的,定义之后还可以增加元素。
    例如,对于上面的 nums 数组,它的长度是 6,使用下面的代码会在最后增加一个元素,使其长度扩展到 7:
nums[6]=88
  • 此外,你也无需逐个元素地给数组赋值,下面的代码就是只给特定元素赋值:
ages=([3]=24 [5]=19 [10]=12)
# 以上代码就只给第 3、5、10 个元素赋值,所以数组长度是 3

获取数组元素

  • 获取数组元素的值,一般使用下面的格式:
${array_name[index]}
# 其中,array_name 是数组名,index 是下标。例如:
n=${nums[2]}
  • 使用@*可以获取数组中的所有元素,例如:
${nums[*]}
${nums[@]}
# 两者都可以得到 nums 数组的所有元素。

获取数组长度

  • 利用@*,可以将数组扩展成列表,然后使用#来获取数组元素的个数,格式如下:
${#array_name[@]}
${#array_name[*]}
# 其中 array_name 表示数组名。两种形式是等价的,选择其一即可。
  • 如果某个元素是字符串,还可以通过指定下标的方式获得该元素的长度,如下所示:
${#arr[2]}
# 获取 arr 数组的第 2 个元素(假设它是字符串)的长度。

例子:

#!/bin/bash
nums=(29 100 13)
echo ${#nums[*]}  # 3
# 向数组中添加元素
nums[10]="http://c.biancheng.net/shell/"
echo ${#nums[@]}   # 4
echo ${#nums[10]}  # 29
# 删除数组元素
unset nums[1]
echo ${#nums[*]}  # 3

数组拼接

所谓 Shell 数组拼接(数组合并),就是将两个数组连接成一个数组。

拼接数组的思路是:先利用@*,将数组扩展成列表,然后再合并到一起。具体格式如下:

array_new=(${array1[@]}  ${array2[@]})
array_new=(${array1[*]}  ${array2[*]})
# 两种方式是等价的,选择其一即可。其中,array1 和 array2 是需要拼接的数组,array_new 是拼接后形成的新数组。

例子:

#!/bin/bash
array1=(23 56)
array2=(99 "http://c.biancheng.net/shell/")
array_new=(${array1[@]} ${array2[*]})
echo ${array_new[@]}  #也可以写作 ${array_new[*]}

# 运行结果:23 56 99 http://c.biancheng.net/shell/
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-11-20 18:49:01  更:2021-11-20 18:49:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 0:49:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码