1.Shell学习
1.什么是Shell
shell是一个命令解析器,在操作系统的最外层,负责和用户对话,将用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果。
2.什么是shell脚本
当命令捉着语句不在命令行执行,而是通过一个程序文件执行的时候,改程序就是shell程序。
3.需要注意的是ishell是包含命令,变量,流行和控制语句的脚本
4.Shell脚本擅长处理纯文本类型的数据,
Rsync Nfs Crond Ssh key 基础命令 Apache Mysql Php Nginx Lvx+keepalive + Iptables +Cacti/流量监控
5.Shell脚本语言种类
UNINX主要包括2大类:
Bourne shell(sh,ksh,bash) ->bash主流
C shell(csh, tcsh)
Linux的默认是Bash -->标准的
echo $SHELL -->/bin/bash
也可以通过cat /etc/passwd 查看一个用户对应的shell6.Shell与PHP,Perl,Pph语言的差别:
Shell的优势在于快速的处理操作系统底层业务(大量的命令作支撑)
一键安装,报警脚本,常规的业务,shell更简单
Python:开发运维工具,WEB的管理界面,自动化等有优势
7.常见的Linux脚本语言解析
#!/bin/sh
#!/bin/bash
#!/bin/awk
#!/bin/perl
#!/usr/bin/env python
2. Shell脚本的建立
0.shell脚本规范
1.#!/bin/sh 开头
2.添加注释
3.开头添加版本信息
4.每次dos2unix格式化脚本 -->cat -v *.sh 可以查看
1.shell脚本(bash shell程序)中编写
脚本开头,指定哪个解析器来执行脚本的内容
默认是/bin/sh,且必须是第一行
如果环境没有,则必须在使用的时候指定解析器 sh h.sh 或 python h.py
#!/bin/bash -->必须是第一行,默认bash,如果环境没有,则必须在是用的时候指定解析器
==> #!/bin/sh -->必须是第一行
ll /bin/sh -->/bin/sh 是bash的链接文件,实为同一文件
2.脚本的执行
1.原理:
当shell脚本非交互式运行的时候,会开始寻找环境变量ENV,找到指定的(.bashrc)文件,然后从该环境变量中执行脚本内容
2.shell脚本常用的方式
1.bash *.sh | sh *.sh
2./bin/sh *.sh | ./*.sh(当前路径下)
3.source *.sh | . *.sh(用点读入或者加载指定的脚本)
-->source的作用是传递变量值到当前shell
-->我们写的*.sh本事就是一个shell,但是在脚本shell里面的结果,不会传递给当前shell,所以使用将脚本shell里面的变量定义传递给我们看到的shell去呈现
所以使用点号可以将子脚本的结果作为输入传递到我们看到的shell里面
实际例子: vim /etc/init.d/nfs -->里面调用函数库的时候就是使用点调用的
在一个脚本里面加载/调用另一个脚本里面的变量的时候,必须用点或者source
3.Shell变量的基础及深入
1.全局变量
环境变量(全局变量):定义shell的运行环境,可以再创建他们的shell以及派生出来的任意子进程shell中使用
例如:用户名,命令路径等,全局使用,每次用户登录均会初始化
修改全局变量: 用户家目录下 ~/.bash_profile
/etc/profile
/etc/profile.d/
/etc/bashrc
全局变量生效:source /etc/bashrc
==> . /etc/bashrc
全局变量查看:set
set可以像命令行一样设置传参
set -- "I am" a student -->3个参数
env
取消全局变量:unset USER自定义全局变量:
1.在修改全局变量的文件内使用export命令:
vi /etc/profile
export ftl ="Come on Ftl,Ha"; -->第一种方法
ftl = "Second Method " export ftl -->第二种方法
source vi /etc/profile
echo $ftl局部变量:只能在创建他们的shell脚本中使用,用户创建,专用shell变量
$a = ${a}2.导出变量名:
export: 设置或显示环境变量
在shell中执行程序时,shell会提供一组环境变量。
export可新增,修改或删除环境变量,供后续执行的程序使用。
export的效力仅及于该次登录操作。
export 变量名=value
其他:
变量名=value; export 变量名
declare -x 变量名=value3.单引号,双引号,不加引号的区别:
一般情况下:
单引号:输入即输出
双引号:解析变量名,不扩展正则
不加引号:连续字符串,与双引号无差异,如果字符串含有空格,则不能完整输出
特殊情况下:
awk: 单引号会解析变量,双引号则不能
建议:
1.直接定义: ftl = 22
2.有空格,双引号: ftl = "Come on boy"
3.输入即输出,单引号
4.变量名大写字母
5.引用时${FTL}或者“$(FTL)”
6.脚本中的局部变量:以local声明,只在本函数内有效
脚本中的全局变量:大写
7.变量学习: /etc/init.d/functions
4.把命令定义为变量
echo `date +%F` -->反引号
echo $(date +%F)
tar czvf hhh_${hhh}_ftl.tar.gz -->容易引起误会的加大括号 :${变量名}
推荐:平时就使用: 字符串变量用双引号括起来 “$A”或 ${A}
5.shell的特殊变量
1.位置变量
$0: 获取当前脚本的名称,包括路径(前台是加入了脚本绝对路径:sh /home/omd/hhh.sh)
$n: 获取当前的脚本的第n个参数,n=1..9,大于9,则需要大括号${10}
$*: 获取当前shell的所有参数,将所有的命令行参数视为单个字符串,相当于“$1$2$3”
$#: 当前shell命令行中参数的总个数
$@: 这个程序的所有参数,作为一个i整体传递、
basename $0: 只输出脚本名称
dirname $0: 输出路径的名称2.进程状态变量:
$$: 获取当前shell的进程号
$?: 判断上一个命令是否成功
0: 成功
2: 权限拒绝
127: 命令无效
>128:强制结束
$_: 在此之前执行的命令或脚本的最后一个参数
$@: 这个程序的所有参数3.答疑$#和$@的区别:
$*: 将所有的参数当做一个参数进行传递,"$1$2$3"
$@: 将每个参数视为单独的字符串,等同于"$1", "$2", "$3" 3个参数set -- "I am" a student -->临时定义了3个参数,set可以像命令行一样设置传参
echo $# -->输出3
for i in $*; do echo $i; done; -->"$*"由于未加引号,所以会解析"I am"为2个字符
for i in $@; do echo $i; done; -->"$@"由于未加引号,所以会解析"I am"为2个字符
for i in ; do echo $i; done; -->什么都不加,相当于引用了加引号的“$@”,输出 I am \n a student
for i in "$@"; do echo $i; done; -->输出 I am \n a student
for i in "$*"; do echo $i; done; -->输出一整行"I am a student"4.Bash内部命令和shift
echo: 变量名输出到标准设备
eval args: 读入args参数,并将他们组合成一个新的命令,然后执行
exec 参数: 当shell执行到exec的时候,不会去创建新的子进程,而是去执行指定的命令;
指定的命令执行完后,该进程(最初的shell)终止。
所以shell程序的exec后面的语句不再被执行
export 变量名=value,把他的变量带入子shell,从而让子进程继承父进程中的环境变量
read: 标准读入,传递给指定变量
wait: 等待
sleep: 休眠
exit: 0成功退出 1异常退出
shift: 重新命名所有位置的参数变量,即$2变成$1,直到$#为0
.(点): ?
readonly: 只读变量,显示所有的只读变5.Shell变量的子串应用技术
常用操作:初步测试,对原文件不生效
hello="Hello World"
${#String}: 统计字符数量 echo ${#hello}" -->11 | echo ${hello} |wc -m
${String:position:length}:
echo ${hello:2} -->删除前2个字符,也即是从第三个输出到最后 -->llo world
echo ${hello:2:2} -->删除前2个字符,取出后面的2个字符 -->ll
${String#substring} -->从变量$String开头,开始删除最短匹配字符$substring子串
${String##substring} -->从变量$String开头,开始删除最长匹配字符$substring子串
${String%substring} -->从变量$String结尾,开始删除最短匹配字符$substring子串
${String%%substring} -->从变量$String结尾,开始删除最长匹配字符$substring子串
${String/#substring/replace} -->如果$string前缀匹配了$substring,就用replace代替
${String/%substring/replace} -->如果$string后缀匹配了$substring,就用replace代替
总结一下:
# :从前匹配
% :从后匹配
::删除字符6.其他变量替换;
${value:-word}: 如果value已定义,则显示原来的默认值 -->判断变量未定义,可以解决变量未定义问题
如果value未定义,则显示值为word
result=${test:-UNSET} -->如果test有值,则赋值给result
-->如果test为空,则设置-UNSET给result
${value:=word}: 如果value已定义,则显示原来的默认值
如果value未定义,则设置默认值为word
result=${test:=UNSET} -->如果test有值,则赋值给result
-->如果test为空,则设置-UNSET给test和result${value:? "not default"}:用于捕捉变量未定义而导致的错误,并退出程序
result=${test:?"sorry"} -->如果test有值,则赋值给result
-->如果test为空,则显示-bash:test sorry,并退出${value:+word}:测试变量是否存在,如果已经定义,则返回word
result=${test:+hello} -->如果test有值,则返回hello
-->如果test为空,则返回null${value-word}:去掉冒号 httpd=${HTTPD-/usr/local/httpd} -->/etc/httpd
如果变量未存在,则用后面的替代说明: 每个运算符内的冒号都是可选的 -->用于判断测试变量是否存在
带帽号:存在且非null
去冒号:存在
/etc/init.d/httpd
/etc/init.d/crond
对路径进行操作的时候,最好先进行路径判断是否为空,然后后进入目标路径删除
path=/home/omd
cd $path
find ${path:=/home/omd/} -name "*.txt"|xargs rm -f
#rm -rf ${path:=/tmp}
--->注意增加${path:=/home/omd}和omd加反斜线,防止omd目录被干掉
shell开发规范
1.指定脚本解析器
#!/bin/sh
2.开头添加版本版权等信息
#Date
2017-0905-21:00
#Author Lvfengtao
#Mail ws415659
#Function This
script is for MysqlBakcup
#Version V1.1.1
可以配置Vim的品配置文件
~/.vimrc添加2的内容
3.脚本尽量少用中文注释
4.脚本以*.sh结尾
5.代码书写优秀习惯
1.成对的内容一起输出
{} [] '' "" ``
2.[]括号的2端必须有空格,书写时[ ],退格在书写[ fsfs
]
3.if语句格式一次成型
if 条件内容
then
内容
fi
4.for 循环一次成型
for n in list
do
内容
done;
6.通过缩写让代码易读
【更多参考】