Shell脚本和编程
为什么要学习shell?(学习shell的价值):
1.Linux服务器的基本操作和管理;
2.前端Node.js服务的进程管理,问题排查,资源监控等运维操作;
3.使用shell编写TCE,SCM,Docker脚本,完成服务编译和部署。
第一章:Shell基础
概念
发展
构成
第二章:语法和命令
自定义变量
#!/bin/bash
#变量名=变量值(等号左右不能有空格)
page_size=1
page_num=2
#将命令赋值给变量
_ls=ls
#将命令结果赋值给变量
file_list=$(ls -a)
#默认字符串,不会进行 + 运算
total=page_size*page_num
#声明变量为整型
let total=page_size*page_num
declare -i total=page_size*page_num
#导出环境变量
export total
declare -x total
系统环境变量
运算符和引用
管道
管道与管道符 | ,作用是将前一个命令的结果传递给后面的命令
语法:cmd1 | cmd2
要求:管道右侧的命令必须能接受标准输入才行,比如grep命令,ls,mv等不能直接使用,可以使用xargs预处理
注意:管道命令仅仅处理stdout,对于stderr会予以忽略,可以使用set -o pipefail设置shell遇到管道错误退出
#!/bin/bash
cat platform.access.log | grep ERROR
netstat -an | grep ESTABLISHED | wc -l
find . -maxdepth l -name "*.sh" | xargs ls -l
重定向
判断命令
shell中提供了test,[,[[三种判断符号,可用于:
- 整数测试
- 字符串测试
- 文件测试
语法:
- test condition- [ condition ]
- [ [condition ]]
注意:
- 中括号前后要有空格符;- [和test是命令,只能使用自己支持的标志位,<,>,=只能用来比较字符串;
- 中括号内的变量,最好都是用引号括起来;
- [[更丰富,在整形比较中支持<,>,=,在字符串比较中支持=~正则
#!/bin/bash
#整数测试
test $n1 -eq $n2
test $n1 -lt $n2
test $n1 -gt $n2
#字符串测试
test -z $str_a
test -n $str_a
test $str_a = $str_b
#文件测试
test -e /dmt && echo "exist"
test -f /usr/bin/npm && echo "file exist"
分支语句
语法1:
if condition;then
程序段
elif condition;then
程序段
else
程序段
if
语法2:
case $变量 in:
"第一个变量内容")
程序段
;;
"第一个变量内容")
程序段
;;
*)
程序段
;;
esac
#!/bin/bash
level=0
if [ -n "$level" ]; then
if [ "$level" == 0 ]; then
prefix=ERROR
elif [ "$level" == 1 ]; then
prefix=INFO
else
echo "log level not supported"
fi
fi
echo "[${prefix}] $message"
#!/bin/bash
read -p "please inpout (Y/N) : " yn
if [ "$yn" == "y" -o "$yn" == "Y" ]; then
echo "ok continue"
fi
if [ "$yn" == "y" ] || [ "$yn" == "Y" ]; then
echo "ok continue too"
fi
#!/bin/bash
name=john
case $name in
"nick")
echo "hi nick"
;;
"john")
echo "my name is john"
;;
*)
echo "404"
;;
esac
循环
while循环while condiction ; do 程序段; done
until循环
until condiction ; do 程序段; done
for循环
for var in [words...]; do 程序段; done
#!/bin/bash
let num=0
while [ $num -lt 10 ];
do
echo "current idx: $num"
((num++))
done
#!/bin/bash
#对列表进行循环
for foo in a b c
do
echo $foo
done
#数值方法循环
for((i=0;i<10;i++))
do
echo $i
done
函数
#语法一: funcName(){ echo "abc";}
#语法二: function funcName(){echo "abc";}
注意
- shell自上而下执行,函数必须在使用前定义
- 函数获取变量和shell script类似,$0代表函数名,后续参数通过$1,$2...获取
- 函数内return仅仅表示函数执行状态,不代表函数执行结果
- 返回结果一般使用echo,printf,在外面使用$(),``获取结果
- 如果没有return,函数状态是上一条命令的执行状态,存储在$?中
#!/bin/bash
printName(){
if [ $# -lt 2 ]; then
echo "illegal parameter."
exit 1
fi
echo "firstname is :$1"
echo "lastname is :$2"
}
printName jacky chen
#!/bin/bash
function test(){
local word="hello world"
echo $word
return 10
unset word
}
content=`test`
echo "状态码: $?"
echo "执行结果: $content"
第三章:执行过程和原理
执行
1.shell脚本一般以.sh结尾,也可以没有,这是一个约定;第一行需要指定用什么命令解释器来执行
1. #! /bin/bash
2.#! /usr/bin/env bash
2.启动方式
#文件名启动
./filename.sh
#解释器运行
bash ./filename.sh
# source 运行
source ./filename.sh
shell展开
大括号展开(Brace Expansion){...}
一般由三部分组成,前缀,一对大括号,后缀,打括号内可以是逗号分隔的字符串序列,也可以是序列表达式{x..y[..incr]}
#字符串序列
a{b,c,d}e => abe ace ade
#表达式序列,(数字可以使用incr调整增量,字母不行)
{1..5} => 1 2 3 4 5
{1..5..2} =>1 3 5
{a..e} => a b c d e
波浪号展开(Tilde Expansion)~
#当前用户的主目录
~ => $HOME
~/foo => $HOME/foo
#指定用户的主目录)
~fred/foo => 用户fed的$HOME/foo
#当前工作目录
~+/foo => $pwp/fpp
#上一个工作目录
~-/foo => ${OLDPWD-'~-'}/foo
命令替换
在子进程中执行命令,并用得到的结果替换包裹的内容,形式上有两种:$(...)或`...`
#!/bin/bash
echo $(whoimi)
foo(){
echo "asdasd"
}
a=`foo`
文件名展开
当有单词没有被引号包裹,且其中出现了'*','?',and,'['字符,则shell会去按照正则匹配的方式查找文件名进行替换,如果没找到则保持不变
#!/bin/bash
$ echo D*
#输出当前目录下所有以D字母开头的目录,文件