目录
一.初识shell脚本
1.1shell的定义
shell 是一种程序设计语言,它有变量,关键字(内置变量,预定义好的),各种控制语句,有自己的语法结构,利用shell程序设计语 可以编写功能很强、代码简短的程序操作系统级别的功能可以随心所欲, 应用级别相对来说难搞一些 。
#! Shebang 定义解释器 解释标识 申明告诉操作系统,我这个文件你给我用什么方式去执行。
1.2shell的分类
Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
Linux 的 Shell 种类众多,常见的有:
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
- C Shell(/usr/bin/csh)
- K Shell(/usr/bin/ksh)
- Shell for Root(/sbin/sh)
- ……
shell的详细分类:
1.sh(全称 Bourne Shell): 是UNIX最初使用的 shell,而且在每种 UNIX 上都可以使用。
Bourne Shell 在 shell 编程方面相当优秀,但在处理与用户的交互方面做得不如其他几种 shell。2.bash(全称 Bourne Again Shell): LinuxOS 默认的,它是 Bourne Shell 的扩展。 与 Bourne Shell 完全兼容,并且在 Bourne Shell 的基础上增加了很多特性。可以提供命令补全,命令编辑和命令历史等功能。它还包含了很多 C Shell 和 Korn Shell 中的优点,有灵活和强大的编辑接口,同时又很友好的用户界面。
3.csh(全称 C Shell): 是一种比 Bourne Shell更适合的变种 Shell,它的语法与 C 语言很相似。
4.Tcsh: 是 Linux 提供的 C Shell 的一个扩展版本。Tcsh 包括命令行编辑,可编程单词补全,拼写校正,历史命令替换,作业控制和类似 C 语言的语法,他不仅和 Bash Shell 提示符兼容,而且还提供比 Bash Shell 更多的提示符参数。
5.ksh (全称 Korn Shell): 集合了 C Shell 和 Bourne Shell 的优点并且和 Bourne Shell 完全兼容。pdksh: 是 Linux 系统提供的 ksh 的扩展。pdksh 支持人物控制,可以在命令行上挂起,后台执行,唤醒或终止程序。
1.3shell脚本的使用场景
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)
8. 自动化扩容(增加云主机——>业务上线)
zabbix监控CPU 80%+|-50% Python API AWS/EC2(增加/删除云主机) + Shell Script(业务上 线)
10. Shell可以做绝大部分运维事务(取决于业务需求)
当然,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
2.shell脚本的详细配置
2.1shell的特性
1.重定向
关于重定向可以参考我的这篇帖子:
https://blog.csdn.net/cainiao1024c/article/details/141564710?spm=1001.2014.3001.5502
2.文件描述符(file descriptor)
文件描述符与输出重定向:
在 shell 程式中,最常使用的 FD (file descriptor) 大概有三个, 分别是:
0: Standard Input (STDIN) #标准正确输入
1: Standard Output (STDOUT) #标准正确输出
2: Standard Error Output (STDERR) #标准错误输出
3或者3 以上的文件句斌都会对应到一个文件
在标准情况下, 这些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输出通道.
2.2脚本的调用形式
用户登录时相关的bash配置文件主要有两种: (登录脚本)
#全局配置文件
/etc/profile # 登录执行
/etc/profile.d/*.sh
/etc/bashrc # bash
#个人配置文件
~/.bash_profile
~/.bashrc #执行bash生效
两类文件的作用:
profile类的文件: 设定环境变量,运行命令或脚本
bashrc类的文件: 定义命令别名
用户登录时加载bash配置文件的过程:
1.登录式shell加载配置文件过程
~/.bash_profile --> ~/.bashrc --> /etc/bashrc --> /etc/profile --> /etc/profile.d/*.sh
2.非登录式shell加载配置文件过程
~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh
各类主要初始化脚本的主要内容:
1./etc/profile(系统级)启动时执行:
这是系统最主要的shell设置文件,也是用户登陆时系统最先检查的文件,有关重要的环境变量都定义在此,其中包括 PATH,USER,LOGNAME,MAIL,HOSTNAME,HISTSIZE,INPUTRC等。而在文件的最后,它会检查并执 行/etc/profile.d/*.sh的脚本。
2.~/.bash_profile(用户级)离开时执行:
这个文件是每位用户的bash环境设置文件,它存在与于用户的主目录中,当系统执行/etc/profile 后,就会接着读取此 文件内的设置值。在此文件中会定义USERNAME,BASH_ENV和PATH等环境变量,但是此处的PATH除了包含系统的$PATH变 量外加入用户的“bin”目录路径.
3.~/.bashrc(用户级)离开时执行
接下来系统会检查~.bashrc文件,这个文件和前两个文件(/etc/profile 和~.bash_profile)最大的不同是,每次 执行bash时,~.bashrc都会被再次读取,也就是变量会再次地设置,而/etc/profile,~./bash_profile只有在登陆 时才读取。就是因为要经常的读取,所以~/.bashrc文件只定义一些终端机设置以及shell提示符号等功能,而不是定义环境变量。
4.~/.bash_login(用户级)登录时执行
如果~.bash_profile文件不存在,则系统会转而读取~.bash_login这个文件内容。这是用户的登陆文件,在每次用户登 陆系统时,bash都会读此内容,所以通常都会将登陆后必须执行的命令放在这个文件中。
5.~/.bash_logout 离开时执行
如果想在注销shell前执行一些工作,都可以在此文件中设置。 例如:#vi ~/.bash_logout
6.~/.bash_history(用户级)
这个文件会记录用户先前使用的历史命令。
2.3读取顺序
- 图形模式登录时,顺序读取:/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。
2.4shell脚本中的快捷键
Ctrl+a 切换到命令行开始(跟home一样,但是home在某些unix环境下无法使用)
Ctrl+e 切换到命令行末尾
Ctrl+u 清除剪切光标之前的内容
Ctrl+k 清除剪切光标之后的内容
ctrl+y 粘贴刚才所删除的字符
Ctrl+r 在历史命令中查找,输入关键字调出之前的命令
2.5关于通配符
在 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这三个字符串之一。
2.6shell脚本的编写规范
[root@localhost ~]# vim helloworld.sh ---.sh代表这个文件是个shell脚本,第一个原因,让别人认的这个是shell脚本,sh后缀有高亮显示。
拓展名后缀,如果省略.sh则不易判断该文件是否为shell脚本
1. #!/usr/bin/env bash ---shebang蛇棒, 解释器, 翻译 2. #
3. #
3. # Author: newrain #作者
4. # Email: [email protected] ---这就是注释, 你没看错
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.路径执行 绝对/相对路径 需要添加执行权限
2、bash/sh 不需要执行就可以执行,是在新bash执行
3、. 或者 source 不需要执行权限 是在当前shell执行
# 执行脚本方式
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 为换行符
2.7变量的类型
shell中的变量类型主要有四类:
预定义变量、环境变量、自定义变量、位置变量
预定义变量
$? 最后一次执行的命令的返回状态。如果这个变量的值为 0,则证明上一条命令正确执行;如果这个变量的值为非 0 ,则 证明上一条命令执行错误
$$ 当前进程的进程号(PID)
$! 后台运行的最后一个进程的进程号(PID)
!$ 历史命令上一条命令的参数
[root@localhost sh]# ls
count.sh hello.sh parameter2.sh parameter.sh #ls命令正确执行
[root@localhost sh]# echo $?
0
#预定义变量"$?"的值是0,证明上一条命令正确执
[root@localhost sh]# vim variable.sh
#!/bin/bash
echo "The current process is $$"
#输出当前进程的PID
#这个PID就是variable.sh脚本执行时生成的进程的PID
[root@localhost sh]# sleep 3000 &
[1] 12165
#符号"&"的意思是把命令放入后台执行
[root@localhost sh]# echo $!
12165
自定义变量
定义: 变量名称=值
变量名称:只能由字母,数字,下划线组成,不能以数字开头;
注意:应该让变量名称有意义;
= 赋值符号 前后不能有空格 ;
值: 所有的字符串和数字都可以;
引用变量: $变量名 或 ${变量名}。
示例:
[root@newrain ~]# a=100
[root@localhost ~]# echo $a
100
[root@localhost ~]# echo $aa
# 这里输出为空,因为解释器认为$aa是变量
[root@localhost ~]# 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:存储所有命令所在的路径
位置变量
$0 $1 $2 $3 $... # 10 $10 ${10}
#/test.sh 2 3 5 hello
2 是第1个位置参数
3 是第2个位置参数
5 是第3个 依次类推
例子:
[root@localhost shell]# cat weizhi.sh
#!/bin/bash
#...
echo 我的第一个位置参数是:$1
echo 我的第二个位置参数是:$2
echo 我的第三个位置参数是:$3
echo 我的第四个位置参数是:$4
echo 一共有 $# 个位置参数
echo 你输入的参数分别是:$*
我的第一个位置参数是:2
我的第二个位置参数是:3
我的第三个位置参数是:5
我的第四个位置参数是:hello
一共有4个位置参数
你输入的参数分别是:2 3 5 hello
标签:profile,Shell,脚本语言,sh,etc,shell,基础理论,bash From: https://blog.csdn.net/cainiao1024c/article/details/141855711