前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除
一、初始Shell
1、理解程序设计语言
- 程序 语言 编程
- 语言
- 自然语言
- 汉语 英语
- 计算机语言
- java php python go 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:解释型执行,慢
2、shell定义
Shell 也是一种程序设计语言,它有变量,关键字,各种控制语句,有自己的语法结构,利用shell程序设计语言可以编写功能很强、代码简短的程序
#! Shebang 定义解释器
3、shell的分类与切换
# 查看系统上可用的shell程序
[root@centos ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
# 查看默认shell
[root@centos ~]# echo $SHELL
/bin/bash
# shell 的切换
[root@centos ~]# vim /etc/passwd # 编辑登录shell
4、使用场景
什么时候不适合使用Shell编程:
- 资源紧张的项目,特别是那些速度是重要因素的地方(排序,散序,等等)
- 程序要进行很复杂的数学计算,特别是浮点计算,任意精度的计算,或者是复数计算
- 要求交叉编译平台的可移植性(使用C或者是Java代替)
- 需要结构化编程的复杂应用(需要变量类型检查和函数原型等等)
- 对于影响系统全局性的关键任务应用。
- 安全非常重要。你必须保证系统完整性和抵抗入侵,攻击和恶意破坏。
- 项目由连串的依赖的各个部分组成。
- 多种文件操作要求(Bash被限制成文件顺序存取,并且是以相当笨拙,效率低下的逐行的存取方式)
- 需要良好的多维数组支持。
- 需要类似链表或树这样的数据结构。
- 需要产生或操作图象或图形用户界面。
- 需要直接存取系统硬件。
- 需要端口号或是socket I/O。
- 需要使用可重用的函数库或接口。
-
所有的私有的不开源的应用程序(Shell脚本的源代码是直接可读,能被所有人看到的)
如果需要有上面的任意一种应用,考虑其他的更强大的脚本语言 ――Perl,Tcl,Python,Ruby,或者可能是其他更高级的编译型语言,例如C,C++或者是Java
5、Shell 能做什么?
- 自动化批量系统初始化程序 (update,软件安装,时区设置,安全策略...)
- 自动化批量软件部署程序 (LAMP,LNMP,Tomcat,LVS,Nginx)
- 应用管理程序 (KVM,集群管理扩容,MySQL,DELLR720批量RAID)
- 日志分析处理程序(PV, UV, 200, !200, top 100, grep/awk)
- 自动化备份恢复程序(MySQL完全备份/增量 + Crond)
- 自动化管理程序(批量远程修改密码,软件升级,配置更新)
- 自动化信息采集及监控程序(收集系统/应用状态信息,CPU,Mem,Disk,Net,TCP Status,Apache,MySQL)
- 配合Zabbix信息采集(收集系统/应用状态信息,CPU,Mem,Disk,Net,TCP Status,Apache,MySQL)
- 自动化扩容(增加云主机——>业务上线) zabbix监控CPU 80%+|-50% Python API AWS/EC2(增加/删除云主机)+ Shell Script(业务上线)
- 俄罗斯方块,打印三角形,打印圣诞树,打印五角星,运行小火车,坦克大战,排序实现
-
Shell可以做任何运维的事情(一切取决于业务需求)
二、Shell特性
1、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 错误返回值 输出到前端
2、重定向语法:
命令 | 说明 |
---|---|
命令 fd> file | 根据指定的文件描述符fd 将数据重定向输出到 file 文件中, 覆盖方式 |
命令 fd>> file | 根据指定的文件描述符fd 将数据重定向输出到 file 文件中, 追加方式 |
命令 > file fd1>& fd2 | 将 fd1 和 fd2 文件描述符合并 输出到文件。 |
fd1<& fd2 | 将 fd1 和 fd2 文件描述符合并 从文件读取输入 |
<< tag | 读取终端输入数据, 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 标记名tag可以任意 |
下面给出几个示例:
# 正确信息重定向输出
[root@centos ~]# touch redirect1.txt
[root@centos ~]# echo "正确输出重定向" >> redirect1.txt
[root@centos ~]# cat redirect1.txt
正确输出重定向
# 错误信息重定向输出
[root@centos ~]# ls java
ls: cannot access java: No such file or directory
[root@centos ~]# ls java 2> redirect2.txt
[root@centos ~]# cat redirect2.txt
ls: cannot access java: No such file or directory
# 正确和错误信息同时输出
[root@centos ~]# echo "正确信息" > redirect2.txt 2>&1
[root@centos ~]# cat redirect2.txt
正确信息
[root@centos ~]# ls java >> redirect2.txt 2>&1 # 合并时空格可有可无
[root@centos ~]# cat redirect2.txt
正确信息
ls: cannot access java: No such file or directory
# 统计文件redirect2.txt中数据行数
[root@centos ~]# cat redirect2.txt
正确信息
ls: cannot access java: No such file or directory
[root@centos ~]# wc -l < redirect2.txt
2
三、Bash初始化
1、全局配置文件
- /etc/profile: 系统级启动时执行,设置重要环境变量如PATH, USER, LOGNAME, MAIL, HOSTNAME, HISTSIZE, INPUTRC等,并执行/etc/profile.d/*.sh脚本。
- /etc/profile.d/*.sh: 系统级脚本,由/etc/profile执行。
- /etc/bashrc:系统级bash配置,影响所有bash shell。
2、个人配置文件
- ~/.bash_profile:用户级登录时执行,设置USERNAME, BASH_ENV, PATH等环境变量,PATH包含用户目录的bin路径。
- ~/.bashrc: 用户级,每次执行bash时读取,定义终端设置和shell提示符号(别名),不定义环境变量。
- ~/.bash_login:用户级,如果~/.bash_profile不存在,则读取此文件,定义登录后执行的命令。
- ~/.bash_logout:用户级,注销shell前执行的脚本,例如执行clear。
3、Shell设置文件加载顺序
登录式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(用户级) # 这个文件会记录用户先前的历史命令
4、bash shell特性
补全 bash-completion # 增加补全
历史 history
history -c # 删除显示的历史命令,不会删除文件中保存的历史命令
别名 alias
alias rmfie ="rm -rf /tem/*"
快捷键
前后台作业
重定向
管道
命令排序执行
; && ||
; 命令分割,在一行中执行多条语句
&& 一行中执行多条语句,前成功后面再执行
|| 一行中执行多条语句,前面不成功,后面再执行
通配符
{} ? *
正则表达式 脚本
5、历史命令
查看历史命令
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查看结果
6、Bash部分快捷键
Ctrl+a 切换到命令行开始(跟home一样,但是home在某些unix环境下无法使用)
Ctrl+e 切换到命令行末尾
Ctrl+u 清除剪切光标之前的内容
Ctrl+k 清除剪切光标之后的内容
ctrl+y 粘贴刚才所删除的字符
Ctrl+r 在历史命令中查找,输入关键字调出之前的命令
7、通配符置换
在 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@centos tmp]# rm -rf /tmp/*
[root@centos tmp]# touch aabcb axyzb a012b ab acb
[root@centos tmp]# ls
a012b aabcb ab acb axyzb
[root@centos tmp]# ls a*b
a012b aabcb ab acb axyzb
[root@centos tmp]# ls a?b
acb
[root@centos tmp]# rm -rf /tmp/*
[root@centos tmp]# touch axb ayb azb axyb
[root@centos tmp]# ls
axb axyb ayb azb
[root@centos tmp]# ls a[xy]b
axb ayb
[root@centos tmp]# ls a[!xy]b
azb
[root@centos tmp]# ls a[!x]b
ayb azb
[root@centos tmp]# rm -rf /tmp/*
[root@centos tmp]# touch a0b a1b a9b
[root@centos tmp]# ls a[0-9]b
a0b a1b a9b
[root@centos tmp]# rm -rf /tmp/*
[root@centos tmp]# touch aabcb axyzb a012b ab
[root@centos tmp]# ls a{abc}b
ls: cannot access a{abc}b: No such file or directory
[root@centos tmp]# ls a{abc,xyz}b
aabcb axyzb
[root@centos tmp]# ls a{abc,xyz,012}b
a012b aabcb axyzb
四、Shell脚本规范
1、格式
[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/newrain
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
2、执行脚本方式
- sh 脚本.sh
- bash 脚本.sh
- ./脚本.sh # 需要执行权限
- . 脚本.sh
- source 脚本.sh
第一行: “#!/usr/bin/env bash”叫做shebang, shell语法规定shell脚本文件第一行为整个文件的解释器 第二行:为“#”开头的行为注释行默认不会被程序所读取, 用来说明文件及标定所属人员使用, 也可用来解释程序 第七行:为格式化打印语句printf, printf可以把后面的“hello world”打印到指定的终端中,\n 为换行符
致谢
在此,我要对所有为知识共享做出贡献的个人和机构表示最深切的感谢。同时也感谢每一位花时间阅读这篇文章的读者,如果文章中有任何错误,欢迎留言指正。
学习永无止境,让我们共同进步!!