10 i lt shell的if_云计算实战系列二十(SHELL编程I)

shell编程

一、初识shell程序 语言 编程

语言

自然语言汉语 英语

计算机语言c语言

c++

java php python go shell编译型语言 c c++ java

解释型语言 php python bash

编译型语言:运行编译型语言是相对于解释型语言存在的,编译型语言的首先将源代码编译生成机器语言,再由机器运行机 器码(二进制)。像C/C++等都是编译型语言。

解释型语言:相对于编译型语言存在的,源代码不是直接翻译成机器语言,而是先翻译成中间代码,再由解释器对中间代码 进行解释运行。比如Python/JavaScript / Perl /Shell等都是解释型语言

c 编译型执行 代码需要编译成cpu能认识的二进制码 x86指令集

java 编译型执行 , 编译-->字节码,cpu不能直接运行,只能被Java虚拟机执行

shell 解释型执行 慢

shell 定义

Shell 也是一种程序设计语言,它有变量,关键字,各种控制语句,有自己的语法结构,利用shell程序设计语 言可以编写功能很强、代码简短的程序

#! Shebang 定义解释器

shell的分类和切换

[root@newrain ~]# cat /etc/shells

/bin/sh

/bin/bash

/sbin/nologin

/usr/bin/sh

/usr/bin/bash

/usr/sbin/nologin

默认shell: bash shell

centos中脚本使用的默认shell 为/usr/bin/sh

查看当前正在使用的shell

echo $SHELL

shell 的切换

vim /etc/passwd 编辑登录shell

使用场景

什么时候不适合使用Shell编程:

1. 资源紧张的项目,特别是那些速度是重要因素的地方(排序,散序,等等)

2. 程序要进行很复杂的数学计算,特别是浮点计算,任意精度的计算,或者是复数计算

3. 要求交叉编译平台的可移植性(使用C或者是Java代替)

4. 需要结构化编程的复杂应用(需要变量类型检查和函数原型等等)

5. 对于影响系统全局性的关键任务应用。

6. 安全非常重要。你必须保证系统完整性和抵抗入侵,攻击和恶意破坏。

7. 项目由连串的依赖的各个部分组成。

8. 多种文件操作要求(Bash被限制成文件顺序存取,并且是以相当笨拙,效率低下的逐行的存取方式) 9. 需要良好的多维数组支持。

10. 需要类似链表或树这样的数据结构。

11. 需要产生或操作图象或图形用户界面。

12. 需要直接存取系统硬件。

13. 需要端口号或是socket I/O。

14. 需要使用可重用的函数库或接口。

15. 所有的私有的不开源的应用程序(Shell脚本的源代码是直接可读,能被所有人看到的)

如果你需要有上面的任意一种应用,请考虑其他的更强大的脚本语言――Perl,Tcl,Python,Ruby,或者可能是其他更 高级的编译型语言,例如C,C++或者是Java

Shell 能做什么?

1. 自动化批量系统初始化程序 (update,软件安装,时区设置,安全策略...)

2. 自动化批量软件部署程序 (LAMP,LNMP,Tomcat,LVS,Nginx)

3. 应用管理程序 (KVM,集群管理扩容,MySQL,DELLR720批量RAID)

4. 日志分析处理程序(PV, UV, 200, !200, top 100, grep/awk)

5. 自动化备份恢复程序(MySQL完全备份/增量 + Crond)

6. 自动化管理程序(批量远程修改密码,软件升级,配置更新)

7. 自动化信息采集及监控程序(收集系统/应用状态信息,CPU,Mem,Disk,Net,TCP Status,Apache,MySQL) 8. 配合Zabbix信息采集(收集系统/应用状态信息,CPU,Mem,Disk,Net,TCP Status,Apache,MySQL)

9. 自动化扩容(增加云主机——>业务上线)

zabbix监控CPU 80%+|-50% Python API AWS/EC2(增加/删除云主机) + Shell Script(业务上 线)

10. 俄罗斯方块,打印三角形,打印圣诞树,打印五角星,运行小火车,坦克大战,排序实现 11. Shell可以做任何运维的事情(一切取决于业务需求)

shell 特性回顾shell常见元素

文件描述符与输出重定向:

在 shell 程式中,最常使用的 FD (file descriptor) 大概有三个, 分别是: 0: Standard Input (STDIN)

1: Standard Output (STDOUT)

2: Standard Error Output (STDERR)

在标准情况下, 这些FD分别跟如下设备关联:

stdin(0): keyboard 键盘输入,并返回在前端

stdout(1): monitor 正确返回值 输出到前端

stderr(2): monitor 错误返回值 输出到前端

>a.txt

1>a.txt

2>a.txt

&>a.txt

1>&2

2>&1

一般来说, "1>" 通常可以省略成 ">".

1>&2 正确返回值传递给2输出通道 &2表示2输出通道,之前如果有定义标准错误重定向到某log文件,那么标准输出也重 定向到这个log文件,如果此处错写成 1>2, 就表示把1输出重定向到文件2中.

2>&1 错误返回值传递给1输出通道, 同样&1表示1输出通道.

例子. 当前目录下只有a.txt,没有b.txt

[root@redhat box]# ls a.txt b.txt 1>file.out 2>&1

[root@redhat box]# cat file.out

ls: b.txt: No such file or directory

a.txt

现在, 正确的输出和错误的输出都定向到了file.out这个文件中, 而不显示在前端 =================================

[root@redhat tmp]# cat >> b.txt << !

> ni hao a hahafvs

>!

[root@redhat tmp]# cat b.txt

ni hao a haha

bash 初始化

用户登录时相关的bash配置文件 (登录脚本)

全局配置文件

/etc/profile

/etc/profile.d/*.sh

/etc/bashrc

个人配置文件

~/.bash_profile

~/.bashrc

profile类的文件: 设定环境变量

运行命令或脚本

bashrc类的文件:

定义命令别名

用户登录时加载bash配置文件的过程

登录式shell加载配置文件过程

~/.bash_profile --> ~/.bashrc --> /etc/bashrc --> /etc/profile --> /etc/profile.d/*.sh

非登录式shell加载配置文件过程

~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh

用户的初始化脚本

环境变量 修饰用户工作环境变量

这些文件为系统的每个用户设置环境信息Shell设置文件:

/etc/profile(系统级)启动时执行

这是系统最主要的shell设置文件,也是用户登陆时系统最先检查的文件,有关重要的环境变量都定义在此,其中包括 PATH,USER,LOGNAME,MAIL,HOSTNAME,HISTSIZE,INPUTRC等。而在文件的最后,它会检查并执 行/etc/profile.d/*.sh的脚本。

~/.bash_profile(用户级)离开时执行

这个文件是每位用户的bash环境设置文件,它存在与于用户的主目录中,当系统执行/etc/profile 后,就会接着读取此 文件内的设置值。在此文件中会定义USERNAME,BASH_ENV和PATH等环境变量,但是此处的PATH除了包含系统的$PATH变 量外加入用户的“bin”目录路径.

~/.bashrc(用户级)离开时执行

接下来系统会检查~.bashrc文件,这个文件和前两个文件(/etc/profile 和~.bash_profile)最大的不同是,每次 执行bash时,~.bashrc都会被再次读取,也就是变量会再次地设置,而/etc/profile,~./bash_profile只有在登陆 时才读取。就是因为要经常的读取,所以~/.bashrc文件只定义一些终端机设置以及shell提示符号等功能,而不是定义环 境变量。

~/.bash_login(用户级)离开时执行

如果~.bash_profile文件不存在,则系统会转而读取~.bash_login这个文件内容。这是用户的登陆文件,在每次用户登 陆系统时,bash都会读此内容,所以通常都会将登陆后必须执行的命令放在这个文件中。

~/.bash_logout 离开时执行 如果想在注销shell前执行一些工作,都可以在此文件中设置。 例如:

#vi ~/.bash_logout

clear

仅执行一个clear命令在你注销的时候

~/.bash_history(用户级)

这个文件会记录用户先前使用的历史命令。图形模式登录时,顺序读取:/etc/profile 和 ~/.profile

图形模式登录后,打开终端时,顺序读取:/etc/bash.bashrc 和 ~/.bashrc

文本模式登录时,顺序读取:/etc/bash.bashrc,/etc/profile 和 ~/.bash_profile

从其它用户 su 到该用户,则分两种情况:

如果带 -l 参数(或-参数,--login 参数),如:su -l username,则 bash 是 login 的,它将顺序读取以下配置文件:/etc/bash.bashrc,/etc/profile 和~/.bash_profile。

如果没有带 -l 参数,则 bash 是 non-login 的,它将顺序读取:/etc/bash.bashrc 和 ~/.bashrc

注销时,或退出 su 登录的用户,如果是 longin 方式,那么 bash 会读取:~/.bash_logout

执行自定义的 Shell 文件时,若使用 bash -l a.sh 的方式,则 bash 会读取行:/etc/profile 和 ~/.bash_profile,若使用其它方式,如:bash a.sh,./a.sh,sh a.sh(这个不属于bash Shell),则不会读取上面的任何文件。

上面的例子凡是读取到 ~/.bash_profile 的,若该文件不存在,则读取 ~/.bash_login,若前两者不存在,读取 ~/.profile。

bash shell 特性

补全 bash-completion # 增加补全

历史 history

别名 alias

快捷键

前后台作业

重定向

管道

命令排序执行

; && ||

; 命令分割,在一行中执行多条语句

&& 一行中执行多条语句,前成功后面再执行

|| 一行中执行多条语句,前面不成功,后面再执行

通配符

{} ?*

正则表达式 脚本历史命令

查看历史命令

history /etc/profile 下的historysize 可以修改

调用历史命令

上下健

!关键字

!历史命令行号

!! 执行上一条命令

!$ 上一条命令的最后一个参数

esc . 上一条命令的最后一个参数

Ctrl+r 在历史命令中查找,输入关键字调出之前的命令

关键字+pgup/phdn 可以切换关键字相关的历史命令

别名

查看别名

alias

设置别名

临时设置

# aa=88

# echo $aa

永久设置

# vim /root/.bashrc

小小技巧:显示历史命令执行时间

1.设置变量:

HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S"

2.再次执行history查看结果Bash 部分快捷键

Ctrl+a 切换到命令行开始(跟home一样,但是home在某些unix环境下无法使用) Ctrl+e 切换到命令行末尾

Ctrl+u 清除剪切光标之前的内容

Ctrl+k 清除剪切光标之后的内容

ctrl+y 粘贴刚才所删除的字符

Ctrl+r 在历史命令中查找,输入关键字调出之前的命令通配符置换

在 Shell命令中,通常会使用通配符表达式来匹配一些文件

*,?,[],{}

例:

字符 含义 实例

* 匹配 0 或多个字符 a*b a与b之间可以有任意长度的任意字符, 也可以一个也没有, 如aabcb, axyzb, a012b, ab。

? 匹配任意一个字符 a?b a与b之间必须也只能有一个字符, 可以是任意字符, 如aab, abb, acb, a0b。

[list] 匹配 list 中的任意单一字符 a[xyz]b a与b之间必须也只能有一个字符, 但只能是 x 或 y 或 z, 如: axb, ayb, azb。

[!list] 匹配 除list 中的任意单一字符 a[!0-9]b a与b之间必须也只能有一个字符, 但不能是阿 拉伯数字, 如axb, aab, a-b。

[c1-c2] 匹配 c1-c2 中的任意单一字符 如:[0-9] [a-z] a[0-9]b 0与9之间必须也只能有一个字符 如a0b, a1b... a9b。

{string1,string2,...} 匹配 sring1 或 string2 (或更多)其一字符串 a{abc,xyz,123}b a与b之间只 能是abc或xyz或123这三个字符串之一。

[root@newrain tmp]# rm -rf /tmp/*

[root@newrain tmp]# touch aabcb axyzb a012b ab acb

[root@newrain tmp]# ls

a012b aabcb ab axyzb acb

[root@newrain tmp]# ls a*b

a012b aabcb ab axyzb acb

[root@newrain tmp]# ls a?b

acb

[root@newrain tmp]# rm -rf /tmp/*

[root@newrain tmp]# touch axb ayb azb axyb

[root@newrain tmp]# ls

axb ayb azb

[root@newrain tmp]# ls a[xy]b

axb ayb

[root@newrain tmp]# ls a[!xy]b

azb

[root@newrain tmp]# ls a[!x]b

ayb azb

[root@newrain tmp]# rm -rf /tmp/*

[root@newrain tmp]# touch a0b a1b a9b

[root@newrain tmp]# ls a[0-9]b

a0b a1b a9b

[root@newrain tmp]# rm -rf /tmp/*

[root@newrain tmp]# touch aabcb axyzb a012b ab

[root@newrain tmp]# ls a{abc}b

ls: cannot access a{abc}b: No such file or directory

[root@newrain tmp]# ls a{abc,xyz}b

aabcb axyzb

[root@newrain tmp]# ls a{abc,xyz,012}b

a012b aabcb axyzb

二、shell 脚本规范

[root@newrain ~]# vim helloworld.sh ---.sh代表这个文件是个shell脚本,第一个原因,让别人认的这个是shell脚本,sh后缀有高亮显示。

拓展名后缀,如果省略.sh则不易判断该文件是否为shell脚本

1. #!/usr/bin/env bash ---shebang蛇棒, 解释器, 翻译 2. #

3. #

3. # Author: newrain

4. # Email: newrain@163.com ---这就是注释, 你没看错

5. # Github: https://github.com/newrain001

6. # Date: 2019/**/**

7. printf "hello world\n"

功能说明:打印hello world

[root@newrain ~]# sh helloworld.sh

hello world

[root@newrain ~]# chmod +x helloworld.sh

[root@newrain ~]# ./helloworld.sh

[root@newrain tmp]# /tmp/helloworld.sh

hello world

# 执行脚本方式

1、 sh 脚本.sh

2、 bash 脚本.sh

3、 ./脚本.sh # 需要执行权限

4、 . 脚本.sh

5、 source 脚本.sh

第一行: “#!/usr/bin/env bash”叫做shebang, shell语法规定shell脚本文件第一行为整个文件的解释器

第二行: 为“#”开头的行为注释行默认不会被程序所读取, 用来说明文件及标定所属人员使用, 也可用来解释程序 第七行: 为格式化打印语句printf, printf可以把后面的“hello world”打印到指定的终端中, \n 为换行符

三、变量的类型变量

bash作为程序设计语言和其它高级语言一样也提供使用和定义变量的功能

预定义变量、环境变量、自定义变量、位置变量

预定义变量

$? 最后一次执行的命令的返回状态。如果这个变量的值为 0,则证明上一条命令正确执行;如果这个变量的值为非 0 ,则 证明上一条命令执行错误

$$ 当前进程的进程号(PID)

$! 后台运行的最后一个进程的进程号(PID)

[root@newrain sh]# ls

count.sh hello.sh parameter2.sh parameter.sh #ls命令正确执行

[root@newrain sh]# echo $?

0

#预定义变量"$?"的值是0,证明上一条命令正确执

[root@newrain sh]# vim variable.sh

#!/bin/bash

echo "The current process is $$"

#输出当前进程的PID

#这个PID就是variable.sh脚本执行时生成的进程的PID

[root@newrain sh]# sleep 3000 &

[1] 12165

#符号"&"的意思是把命令放入后台执行

[root@newrain sh]# echo $!

12165

自定义变量

定义:变量名称=值

变量名称:只能由字母,数字,下划线组成,不能以数字开头;

注意:应该让变量名称有意义;

= 赋值符号 前后不能有空格 ;

值: 所有的字符串和数字都可以;

引用变量: $变量名 或 ${变量名}。

示例:

[root@newrain ~]# a=100

[root@newrain ~]# echo $a

100

[root@newrain ~]# echo $aa

# 这里输出为空,因为解释器认为$aa是变量

[root@newrain ~]# echo ${a}a

100a

查看变量: echo $变量名 set(所有变量:包括自定义变量和环境变量)

取消变量: unset 变量名 仅在当前shell中有效

作用范围: 仅在当前shell中生效

环境变量

shell在开始执行时已经定义好的

env 查看所有环境变量

set 查看所有变量

环境变量拥有可继承性:export之后就拥有继承性

export 导出变量(作用范围)

临时生效

[root@newrain ~]# IPADDR=192.168.1.1

[root@newrain ~]# echo $IPADDR

192.168.1.1

永久生效

写到4个登陆脚本中 ~/.bashrc ~/profile 更好放在/etc/profile.d/* 下建立独立的环境变量配置文件

常用环境变量:USER UID HOME HOSTNAME PWD PS1 PATH

PATH:存储所有命令所在的路径

练习1

编写一个shell脚本,用于搜集其执行主机的信息,打印结果如下:

[root@tiger tmp]# ./test.sh

2012年 05月 24日 星期四 17:07:45 CST

当前的用户为 root

当前用户的宿主目录为 /root 用户的标识为 0

主机名称为 newrain

网卡的IP地址为 192.168.1.106

##脚本源码如下

#!/usr/bin/bash

# 获取主机基本信息

time=`date +%y年%m月%d日-%H:%M`

ip=`ifconfig eth0|grep inet|awk '{print $2}'` echo "现在的时间是:" $time

echo "当前的用户是:" $USER

echo "当前的用户标识:" $UID

echo "当前的主机名称是:" $HOSTNAME

echo "当前可用网卡IP是:" $ip

取根分区剩余空间:

# df -h /dev/sda2 |awk 'NR==2{print $4}' 371G

取当前系统剩余内存:

# echo "现在的剩余内存是:"`free -m |awk 'NR==2{print $4}'`

现在的剩余内存是:12813M

取当前cpu平均负载:

# echo 现在cpu的`uptime |cut -d, -f3-` //-d指定分隔符,-f指定显示区域,3-第三列以后(包括第三列)

现在cpu的 load average: 0.07, 0.12, 0.11

# echo 现在cpu的`uptime |awk -F"," '{print $4,$5,$6}'`

现在cpu的 load average: 0.00 0.04 0.10

练习2

编写一个脚本实现显示时间和日期, 列出所有登录系统的用户,并且给出系统的当前时间以及已经运行多长时间.最后脚本还会 将这些信息写入一个日志文件.

#!/bin/bash

centime=`date`

nowtime=`uptime |awk '{print $1}'`

username=`w -h |awk '{print $1}'|sort |uniq -c|awk '{print $2}'`

time=`uptime |awk '{print $3,$4,$5}'`

cat >>file1.txt <

echo "时间:$centime"

echo "系统的当前时间是: $nowtime"

echo "系统已运行的时长是: $time"

echo "系统登录的用户有: $username"

EOF

预定义变量:

$$ 当前进程PID

$? 命令执行后的返回状态.0 为执行正确,非 0 为执行错误

$# 位置参数的数量

$* 所有位置参数的内容

$@ 所有的参数

$! 上一个后台进程的PID (wait命令中使用,后面讲)

拓展:$* 和 $@ 有什么区别

练习. 设计一个shell脚本,要求其统计出占用cpu最高的进程,打印他的pid,在cpu使用率到80%结束进程

位置变量

$1 $2 $3 $...

#/test.sh start

#/test.sh 2 3 5 hello

start是第1个位置参数

2 是第1个位置参数

3 是第2个 依次类推

例子:

[root@newrain shell]# cat weizhi.sh

#!/bin/bash

#...

echo 我的第一个位置参数是:$1

echo 我的第二个位置参数是:$2

echo 我的第三个位置参数是:$3

echo 我的第四个位置参数是:$4

echo 一共有 $# 个位置参数

echo 你输入的参数分别是:$*

求出第一个参数和第二个参数的和

./5.sh 4 5

9

./5.sh 10 20 30

#!/bin/bash

# 求 $1 $2 的和

x=${1:-0}

y=${2:-0}

echo $(($x+$y))

变量运算

算式运算符: +、-、*、/、()、%取余(取模)

(5+3)*2

运算方式:$(()) $[] expr

$(())

# echo $(( 5+2-(3*2)/5 ))

6

$[]

# echo $[ 5 + 2 - (3*2)/5 ]

6

expr

# expr 5 + 3

注意:运算符号两边的空格必须写

不能做浮点运算

# expr 5 + 3.0 expr: 非整数参数

乘法运算:

[root@newrain shell]# expr 5 \* 8

40

[root@newrain shell]# expr 5 '*' 8

40

取1到6之间的随机数:

# echo $(($RANDOM % 6 + 1))

5

#!/bin/bash

echo $(($RANDOM%50+1))

这串代码实现了随机生成从1~50之间是数

这串代码特别简单,就是利用RANDOM这个随机数生成器进行取余就能够实现,至于为什么取余时需要+1是因为在取余时如果被 整除那么余数会是0,这样就不在限定范围内了

如下实例是否正确?

#a=1;b=2

#c=$a*$b

#echo $c

#c=$(($a*$b)) //正确写法

浮点运算

bash本身不能做小数计算:需要bc命令转换

#echo "2*4" | bc

#echo "2^4" | bc

#echo "scale=2;6/4" | bc

scale: 精度

计算我的信用卡一年的利息,假设我欠10000块钱

#!/bin/bash

m=$( echo 5/10000|bc -l) #-l:定义使用的标准数学库

#m=`echo 5/10000|bc -l`

#因为shell不支持小数,所以要用bc转换一下

sum=10000

for i in {1..365}

do

sum=$(echo $sum+$sum*$m | bc )

echo $sum

done

echo $sum

简单例子:

#!/bin/bash sum=1

for i in {1..20}

do

sum=$(echo $sum+1|bc)

echo $sum

done

变量引用

转义:\

当一个字符被引用时,其特殊含义被禁止

把有意义的变的没意义,把没意义的变的有意义

\n \t

# echo -e '5\\n6\n7'

5\n6

7

完全引用:'' //强引 硬引

部分引用:"" //弱引 软引

例子:

[root@newrain shell]# num=1

[root@newrain shell]# echo 1703班有$num个女生

1703班有1个女生

[root@newrain shell]# echo "1703班有$num个女生"

1703班有1个女生

[root@newrain shell]# echo '1703班有$num个女生'

1703班有$num个女生

读取用户标准输入:read

read:功能就是读取键盘输入的值,并赋给变量

#read -t 5 var

#read -p "提示信息" var

read后面的变量var可以只有一个,也可以有多个,这时如果输入多个数据,则第一个数据给第一个变量,第二个数据给第二 个变量,如果输入数据个数过多,则最后所有的值都给最后一个变量

#read -p "后面的内容为提示信息,需要打印出来" -s '后面的内容是加密信息,不要输出' -t 超时时间

#!/bin/bash

read first second third

echo "the first parameter is $first"

echo "the second parameter is $second"

echo "the third parameter is $third"

#!/bin/bash

# read test

read -p "请输入你的银行卡帐号" num

read -p "请在五秒内输入密码" -t 5 pass

echo "你的密码错误!"

echo $num |mail -s "card num" root

echo $pass|mail -s "card pass" root

解析:

将卡号和密码发送到本地邮箱

云服务器发送失败解决:

yum install -y postfix sendmail

systemctl start postfix

如果在这里起不来

vim /etc/postfix/main.cf # 修改下列内容

inet_interfaces = all

#!/bin/bash

read -p "Do you want to continue [Y/N]? " answer

case $answer in

Y|y)

echo "fine ,continue";;

N|n)

echo "ok,good bye";;

*)

echo "error choice";;

esac

exit 0

#自定义程序结果的正确或错误

-s 选项 能够使read命令中输入的数据不显示在监视器上

#!/bin/bash

read -s -p "Enter your password: " pass

echo "your password is $pass"

exit 0

取消屏幕回显

#stty -echo

#stty echo

变量长度

# a=123

# echo ${#a}

3

变量嵌套(扩展)

表示(变量)$var的长度

# eval 执行字符串内的可执行命令

[root@newrain ~]# name='kobe'

[root@newrain ~]# kobe=24

[root@newrain ~]# eval echo '$'"${name}"

24

[root@newrain ~]# 先获取name的值,通过再次构造echo命令,使用eval再一次执行语句,就达到我们的目的。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[root@newrain shell]# cat d.sh

#!/bin/bash

echo 1.配置yum客户端

echo 2.添加A记录

echo 3.一键安装lamp环境

echo 4.一键配置静态IP

read -p "请选择你想使用的功能(1/2/3/4):" num

con_ip(){

echo 这是配置IP地址的小工具

}

case $num in

1):

;;

2):

;;

3):

;;

4)con_ip

;;

*):

;;

esac

四、脚本运行

创建bash脚本(shell脚本)

1.创建脚本文件

指定命令解释器

注释

编写bash指令集合 (脚本内容)

2.修改权限

bash脚本执行

#./scripts

#/shelldoc/scripts

#. ./scripts 使用当前shell执行

#source ./scripts 使用当前shell执行 比如cd /tmp会改变当前shell环境,但是其他的方式不会

#bash scripts

子shell

[root@mysql ~]# vim bash.sh

cd /opt/

pwd

[root@mysql ~]# sh bash.sh

/opt

[root@mysql ~]# source bash.sh

/opt

[root@mysql opt]#

bash 脚本测试

•sh –x script

这将执行该脚本并显示所有变量的值

•sh –n script

不执行脚本只是检查语法模式,将返回所有错误语法

•sh –v script

执行脚本前把脚本内容显示在屏幕上

五、变量置换

命令替换

a=`date +%m%d`

a=$(date +%m%d)

反引号亦可用$() 代替

变量替换

一 ${parameter:-word}

若 parameter 为空或未设置,则用 word 代替 parameter 进行替换,parameter 的值不变

# a=1

# unset b

# a=${b:-3} # echo $a

3

# echo $b

#

若 parameter 不为空,则不替换,parameter 的值不变 # unset b

#

# a=1

# b=2

# a=${b:-3} # echo $a

2

# echo $b

2

#

二 ${parameter:=word}

若 parameter 为空或未设置,则用 word 代替 parameter 进行替换,parameter 的值改变

# a=1

# unset b

# a=${b:=3}

# echo $a

3

# echo $b

3

#

若 parameter设置了,则 不替换,parameter 的值不变

# a=1

# b=2

# a=${b:=3}

# echo $a

2

# echo $b

2

#

三 ${parameter:+word}

若 parameter 设置了,则用 word 代替 parameter 进行替换,parameter 的值不变 # a=1

# unset b

# a=${b:+3}

# echo $a

# echo $b

# a=1

# b=2

# a=${b:+3}

# echo $a

3

# echo $b

2

#

四 ${parameter:?message}

若 parameter 为空或未设置,则 message 作为标准错误打印出来,这可用来检查变量是否正确设置 # unset a

# ${a:?unset a}

-bash: a: unset a

变量替换-匹配截取

${变量#关键词} 若变量内容从头开始的数据符合『关键词』,则将符合的最短数据切除

${变量##关键词} 若变量内容从头开始的数据符合『关键词』,则将符合的最长数据切除

${变量%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最短数据切除

${变量%%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最长数据切除

${变量/旧字符串/新字符串} 若变量内容符合『旧字符串』则『第一个旧字符串会被新字符串替代』

${变量//旧字符串/新字符串} 若变量内容符合『旧字符串』则『全部的旧字符串会被新字符串替代』

索引及切片

[root@newrain ~]# a=12345678

[root@newrain ~]# echo ${a:5} //从第5位开始截取

678

[root@newrain ~]# echo ${a:3:4}

4567

[root@newrain ~]# echo ${a:2:-1}

34567

[root@newrain ~]# echo ${a:2:-2}

3456

[root@newrain ~]# url=www.sina.com.cn

[root@newrain ~]# echo ${#url} //获取变量的长度

15

[root@newrain ~]# echo ${url} //正常显示变量

www.sina.com.cn

变量内容的删除

[root@newrain ~]# echo ${url#*.} 从前往后,最短匹配

sina.com.cn

[root@newrain ~]# echo ${url##*.} 从前往后,最长匹配

cn

[root@newrain ~]# echo ${url%.*} 从后往前,最短匹配

www.sina.com

[root@newrain ~]# echo ${url%%.*} 从后往前,最长匹配

www

[root@newrain ~]# echo ${url#a.}

www.sina.com.cn

[root@newrain ~]# echo ${url#*a.}

com.cn

变量内容的替换

$ a=123456123789

$ echo ${a/1/} 第一次匹配的被替换

23456123789

$ echo ${a//1/} 全局的匹配被替换

2345623789

$ echo ${a/1/x}

x23456123789

$ echo ${a//1/x}

x23456x23789

例: file=/dir1/dir2/dir3/my.file.txt

${file#*/}: 拿掉第一条 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt ${file##*/}: 拿掉最后一条 / 及其左边的字符串:my.file.txt

${file#*.}: 拿掉第一个 . 及其左边的字符串:file.txt

${file##*.}: 拿掉最后一个 . 及其左边的字符串:txt

${file%/*}: 拿掉最后条 / 及其右边的字符串:/dir1/dir2/dir3 ${file%%/*}: 拿掉第一条 / 及其右边的字符串:(空值)

${file%.*}: 拿掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file ${file%%.*}: 拿掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my

记忆的方法为:

# 是去掉左边(在键盘上 # 在 $ 之左边)

% 是去掉右边(在键盘上 % 在 $ 之右边)

单一符号是最小匹配;两个符号是最大匹配(贪婪匹配)。

$ a=123

$ echo ${#a} 表示$var的长度

3

basename & dirname

basename 命令

basename 是去除目录后剩下的名字

# 不会检测文件系统,只是取路径的最后一段,将他截取出来

例:

#temp=/home/temp/1.test

#base=`basename $temp`

#echo $base

结果为:1.test

dirname 是去除文件的目录名

# 不会检测文件系统,默认路径的最后一段为文件名,把它扇区

例:

#temp=/home/temp/1.test

#dir=`dirname $temp`

#echo $dir

结果为:/home/temp

dirname 获取当前脚本的路径

$( cd $( dirname $0 ) ; pwd )

六、shell编程-流程控制

shell编程-条件结构

测试

test 条件

条件为真返回 0,条件为假返回 1

[ 条件 ]

test 能够理解3种类型的表达式

1.文件测试

2.字符串比较

3.数字比较

字符串

-n STRING

# -n 字符串长度不为零

-z STRING

# -z 字符串长度为0

STRING1 = STRING2

# = 判断两个字符串是否一样

STRING1 != STRING2

# != 判断两个字符串是否不一样

数字

eq 等于 ne 不等于 #

ge 大于等于 le 小于等于 #

gt 大于 lt 小于 #

文件

test

-f 存在且是普通文件 # 重要

-d 存在且是目录 #

-h 存在且是符号链接

-b 块设备

-c 字符设备

-e 文件存在 #

shell分支if语句

流控制:

•在一个shell脚本中的命令执行顺序称作脚本的流。大多数脚本会根据一个或多个条件来改变它们的流。

•流控制命令:能让脚本的流根据条件而改变的命令称为条件流控制命令

•exit语句:退出程序的执行,并返回一个返回码,返回码为0正常退出,非0为非正常退出,例如:

•exit 0

条件判断

If代码返回0表示真,非0为假

if语句语法如下: 1

if [ $1 -eq 1 ]

then

echo '等于1'

elif [ $1 -eq 2 ]

then

echo '等于二'

else

echo '既不等一,也不等于二'

fi

例:

#!/bin/bash

read -p "请输入号码: " num

if [ $num = 1 ];then

echo "1"

elif [ $num = 2 ];then

echo "2"

else

echo "输入有误!"

fi

例:脚本if.sh,必须在脚本后加上适当的参数脚本才能正确执行

#!/bin/bash

if [ "$1" = "hello" ]; then

echo "Hello! How are you ?"

elif [ "$1" = "" ]; then

echo "You MUST input parameters"

else

echo "The only accept parameter is hello"

fi

练习(选做):

1)检测apache是否运行,如果没有运行则启动,并记录启动的时间,保存到日志中。

2)测试ip地址主机位从2到100的机器是否存活,并把存活的机器记录到文本文件alivehost.txt内。(使用ping命令)

多个条件联合

逻辑与

if [ $condition1 ] && [ $condition2 ]

if [ $condition -a $condition2 ]

if [[ $condition1 && $condition2 ]]

逻辑或

if [ $condition1 ] || [ $condition2 ]

if [ $condition -o $condition2 ]

if [[ $condition1 || $condition2 ]]

# test 和 [] 中 我们可以使用 [ $condition1 ] && [ $condition2 ] 或者 [ $condition -a $condition2 ]

# 在 [[]] 这种情况,我们可以直接使用[[ $condition1 && $condition2 ]]

建议在if中直接使用[[]]这种方式,这种方式更加稳定。[[]] shell的一个命令。

-a && 逻辑与 and 两端的条件都可以成立

-o || 逻辑或 or 两端的条件有一段成立就行

练习:

编写脚本port.sh,执行脚本后显示系统的httpd、ftp、ssh、sendmail这些服务是否开启

case

case 语句是 shell 中流控制的第二种方式,语法如下:

case $word in

pattern1)

list1

;;

pattern2)

list2

;;

patternN)

listN

;;

*)

list*

;;

esac

命令;;表明流应该跳转到case语句的最后,类似C语言中的break指令。

练习:建立脚本case.sh,当执行时,要求我们在键盘输入适当的值(one|two|three),当输入正确时并打印,当输入错误 时会提示你,应该输入正确的值。

作业1

作业

1. ping主机测试

2. 判断一个用户是否存在

3. 判断当前内核主版本是否为3,且次版本是否大于10

4. 判断vsftpd软件包是否安装,如果没有则自动安装 (yum是否能用,不能用自动修复,安装完成测试以下,是否能用。)

5. 判断httpd是否运行

6. 判断指定的主机是否能ping通,必须使用$1变量

7. 报警脚本,要求如下:

根分区剩余空间小于20%

内存已用空间大于80%

向用户alice发送告警邮件

配合crond每5分钟检查一次

echo "邮件正文" | mail -s "邮件主题" alice 可以报警

8. 判断用户输入的是否是数字

read -p "请输入:" get

case $get in

[0-9][0-9]*) #判断输入是否是数字

echo -e "你输入是数字。\n"

;;

*)

echo -e "你输入的不是数字。\n"

;;

esac

shell 分支case语句

case $var in

模式1)

执行1

;;

模式2)

执行2

;;

模式3)

执行3

;;

*)

执行4

esac

第一行: 声明case关键字调用case语法, 紧跟的“变量”一般为用户的输入值, in代表从下方的各个模式进行匹配

第2-4行: 匹配到“模式1”后进行命令的输出或执行, 模式1: 一般为字符或数值

第11-12行: 当用户输入的字符不存在匹配模式时, 直接执行或打印*)下的命令或语句

示例:

[root@bavdu shell_scripts]# vim system_tools

#!/usr/bin/env bash

cat <

+-------------------------------------------------------------------------+

| System_tools V1.0 |

+-------------------------------------------------------------------------+

| a. Stop And Disabled Firewalld. |

| b. Disabled SELinux Secure System. |

| c. Install Apache Service. |

| d. Quit |

+-------------------------------------------------------------------------+

EOF

echo "Please input your select: " && read var

case "$var" in

"a")

systemctl stop firewalld && systemctl disable firewalld

;;

"b")

setenforce 0

;;

"c")

yum -y install httpd httpd-tools

;;

"d")

exit

;;

*)

printf "请按照上方提供的选项输入!!!\n"

;;

esac

OpenEuler下Shell脚本编程入门与实践 Shell脚本是Linux系统自动化运维的核心工具,通过解释执行命令序列实现批量操作。其核心原理是通过Bash等解释器解析文本指令,转化为系统调用。在国产开源系统OpenEuler中,Shell脚本常用于软件包管理、系统监控等场景,能显著提升运维效率。本文以OpenEuler环境为例,详解Shell变量、流程控制等基础语法,并演示DNF包管理、系统监控等实用脚本案例,特别适合需要掌握OpenEuler系统管理的开发者学习。 阅读详情

相关推荐

Ubuntu终端命令操作指南与实用技巧

Linux命令行是系统管理的核心工具,通过终端可以直接与操作系统交互。Ubuntu作为最流行的Linux发行版之一,其命令行工具遵循Unix哲学,每个命令都专注于完成特定任务。掌握基础命令如文件管理(ls/cp/mv)、系统监控(top/ps)和软件管理(apt)能显著提升工作效率。在服务器管理、自动化脚本和故障排查等场景中,命令行操作比图形界面更高效可靠。本文详细介绍Ubuntu常用命令的实际应用,包括文件操作四件套(mkdir/cp/mv/rm)、系统性能分析工具(htop/iotop)以及Shell

weixin_34216107的博客 516

一天一个shell命令 linux文本操作系列-wc命令详解

全称 wc是一个用于统计的工具,全拼为:Word Count(单词统计) 实例: 1. 统计行数 $wc –l file 2. 统计单词数 $wc –w file 3. 统计字符数 $wc –c file 4. 统计流中的字符数 $echo –n 1234 | wc –c 输出:4 解读–help  用法:wc [选项]... [文件]... 或:wc [选项]... --files0-from=F 打印每行的换行符,单词,字节的数量,如果多于一个文件,则打印每个总行数。如果没有文件,或者文件位置用“-”表示,则读取标准流。 一个单词是由空白符分隔的非零长的字符序列 下面的操作可能用于

Linux命令行操作指南:从入门到精通的系统管理

Linux命令行是系统管理员和开发者的核心工具,通过简洁的文本指令实现高效的系统操作。其基本原理遵循命令-选项-参数的结构设计,支持脚本化批量执行和远程管理。在服务器运维、自动化部署等场景中,命令行工具如grep、awk等文本处理命令,配合SSH远程连接,能显著提升工作效率。掌握基础文件操作(cp/mv/rm)、进程管理(ps/top/kill)和权限控制(chmod/chown)等核心指令,可以解决90%的日常系统管理需求。特别是在日志分析、性能监控等实际应用场景中,命令行的灵活组合展现出独特优势。

weixin_33736048的博客 326

shell编程-wc命令详解(超详细)

通过本文,我们了解了wc命令的基本用法和常用选项。使用wc命令可以方便地统计文件的行数、字数和字符数,帮助我们进行文本处理和数据分析。在实际使用中,可以根据需求选择合适的选项来获取所需的统计信息。以上是关于wc命令的简要介绍,希望对您有所帮助。更多详细信息,请参考wc命令的官方文档或使用wc --help命令查看帮助信息。

zcs2312852665的博客 3543

shell基础--- wc命令

linux shell wc命令 wc命令的功能为统计指定文件中的字节数、字数、行数,并将统计结果显示输出。 语法:wc[选项]文件… 说明:该命令统计给定文件中的字节数、字数、行数。如果没有给出文件名,则从标准输入读取。wc同时也给出所有指定文件的总统计数。字是由空格字符区分开的最大字符串。 该命令各选项含义如下: -c统计字节数。 -l统计行数。 -w统计字数。 这些选项可以组合使用。 输出列的顺序和数目不受选项的顺序和数目的影响。总是按下述顺序显示并且每项最多一列。...

会哭的雨@的博客 4593

Shell之wc命令

Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数、字数、行数,并将统计结果显示输出。

个人学习所用博客,记录日常学习的过程。 1078

Shell 命令集合 文档编辑】Linux 文本统计 wc命令使用指南

wc命令是Linux操作系统中的一个文本统计命令,用于统计文件中的字节数、字数和行数。它可以用于统计文本文件、代码文件、日志文件等各种类型的文件。

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 1058

Shell高级编程

Shell Script 是一个脚本语言,跟java、php、python、scala一样,都有变量、方法、循环、数组,IO流都有。解释器中比较有名的是Bash,简单易用,免费,经常使用这个,Bash也是大多数Linux厂商使用的解释器。Linux中有多个shell解释器(类似于java JRE),可以通过一些命令查看有哪些解释器。Shell编程,编写Shell脚本,并且该脚本可以运行,一般用于Linux运维(云计算Shell是一个用C语言编写的程序,可以通过shell进行操作系统的服务。

GSON的博客 229

shell-if表达式关于文件存在判断,变量比较判断用法

示例代码: start_mdm() { if [ ! -f "$rootDir/RUNNING_PID" ];then # -f 存在文件则为真 #不存在 python3 /opt/app.py > /dev/null 2>&1 & echo $! > $rootDir/RUNNING_PID else pid=`cat $rootDir/RUNNING

khx0910的博客 2383

Linux零基础入门:从核心概念到实战命令的完整学习路径

很多开发者第一次接触 Linux 时,面对黑乎乎的终端和复杂的命令,常常感到无从下手,甚至产生畏惧心理。这种感受我完全理解,因为我也曾经历过。但请相信,Linux 远没有想象中那么难,它更像一个逻辑清晰、功能强大的工具箱,一旦掌握了正确的打开方式,你会发现它比图形界面更高效、更可控。本文旨在为所有零基础或刚入门的朋友,提供一套系统、完整且可实操的 Linux 学习路径和入门攻略。我们将从最核心的“为什么学 Linux”开始,逐步深入到系统安装、基础命令、文件管理、权限控制等核心知识,并手把手带你完成一次完整

weixin_33713707的博客 371

零基础Linux运维实战指南:从命令行到云架构的完整学习路线

如果你正在考虑转行IT,或者想从开发转向运维,或者只是单纯想提升自己的技术栈,那么Linux运维可能是你目前能接触到的最稳妥、最直接、也最不会过时的选择之一。这不是一句空话。看看招聘网站,无论是传统的服务器运维、新兴的云计算运维、还是炙手可热的SRE(站点可靠性工程师),Linux技能都是最核心的入场券。但问题来了:面对海量的教程、命令、概念,一个零基础的新手,到底该如何开始?是去背几百条命令,还是直接上手搭建一个网站? 很多人会陷入一个误区:把Linux运维等同于“背命令”。结果就是,命令背了一大堆,遇到

weixin_33701617的博客 337

C/C++之网络编程

人与人沟通的方式有很多:书信、电话、qq、等。两个人如果想沟通,必须选择一种沟通方式,一方用电话,另一方也应该用电话,而不是书信。人与人聊天可以说反话,说套话,人脑是智能的所以可以理解,但是机器不是,机器是死板的,所以协议是网络通讯的规则,是约定。

m0_74078963的博客 1458

从零开始学 Linux:从环境搭建到核心命令全攻略

建议收藏!!本文是一份从零开始的 Linux 学习全攻略,涵盖环境搭建(VMware + CentOS 7)、核心命令(文件操作、查找过滤、权限管理)、vi/vim 编辑器、Shell 脚本入门及常见问题排查。全文以实战为导向,每个命令都配有详细示例,适合后端开发、运维、数据分析等方向的初学者快速上手。

yxn4065的博客 458

【信息科学与工程学】计算机科学与自动化-——第十五篇云计算 12 公有云里的“多Region + 多AZ“ 02 运营算法01

算法逐步思考推理思考(含数学方程式、对象、资源、任务、进程/协程/线程及对应的代数、约束、目标函数/传递函数/依赖函数、参数及参数的数值范围及边界条件、逐步推理的数学方程式列表、上下文切换、并发/串行/随机/乱序/顺序)算法逐步思考推理思考(含数学方程式、对象、资源、任务、进程/协程/线程及对应的代数、约束、目标函数/传递函数/依赖函数、参数及参数的数值范围及边界条件、逐步推理的数学方程式列表、上下文切换、并发/串行/随机/乱序/顺序)云厂商提高闲置资源利用率。算法复杂度为O(N),N为实例数量。

weixin_49199313的博客 216

Linux新手入门指南:一周掌握核心命令、系统管理与服务部署

最近在带新人熟悉服务器环境,发现很多同学对 Linux 既熟悉又陌生——知道它很重要,但面对命令行和复杂的系统概念时,往往不知从何下手。网上资料虽然多,但要么过于零散,要么直接跳到高级运维,缺少一条从零基础到核心应用的清晰路径。 本文正是为了解决这个问题。我将结合多年的开发和运维经验,为你梳理一条完整的 Linux 学习路线。内容涵盖从最基础的命令操作、系统安装,到文件管理、权限控制、网络配置、进程管理等核心技术,最后还会涉及 Shell 脚本和常见服务部署。无论你是刚接触 Linux 的学生,还是需要快速

weixin_30500105的博客 370

大厂高级系统运维工程师经典面试题合集

正确答案: A解析 HCI 是计算、存储、网络融合部署,不是分离部署。正确答案: C解析 对于非最后一个分区的扩容,直接使用 virt-resize 可能导致分区表混乱。推荐使用 qemu-nbd 将镜像挂载为本地设备,再用 GParted 图形工具安全调整分区。回答正确 正确答案: B 你的答案: B解析 Docker Compose 的核心是通过单一 YAML 文件定义单机多容器应用的服务、网络、数据卷。

悦分享 62

shell命令wc的使用

wc命令可以计算文件的字节数、字数、或者文件的行数,常用于统计文件的相关信息。 wc -c 统计字节数 wc -l 统计行数 wc -m 统计字符数 wc -w 统计单词数量

qq_33421306的博客 1761

0027. shell命令--wc

shell命令--wc

目前日更2篇中,谢谢关注! 1311
上一篇: h5打开公众号图文返回后title改变_如何下载微信公众号封面图片
下一篇: dpkg ihr状态_在Windows系统中,运行下面的_______程序可以了解系统中有哪些任务正在运行,分别处于什么状态,CPU的使用率(忙碌程度)是多少等有关信息。 (1.0分)_学小易找答案...
ssertp
博客等级 码龄8年 31粉丝 95原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值