Shello脚本和编程 | 青训营笔记

70 阅读2分钟

Shell脚本和编程

为什么要学习shell?(学习shell的价值):
       1.Linux服务器的基本操作和管理;
       2.前端Node.js服务的进程管理,问题排查,资源监控等运维操作;
       3.使用shell编写TCE,SCM,Docker脚本,完成服务编译和部署。

第一章:Shell基础

概念

屏幕截图 2023-04-15 174447.png

发展

屏幕截图 2023-04-15 174613.png

构成

屏幕截图 2023-04-15 174738.png

第二章:语法和命令

屏幕截图 2023-04-15 175059.png

自定义变量

#!/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

屏幕截图 2023-04-15 182703.png

系统环境变量

屏幕截图 2023-04-15 182747.png

运算符和引用

屏幕截图 2023-04-15 183257.png

管道

       管道与管道符 | ,作用是将前一个命令的结果传递给后面的命令
       语法: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

重定向

屏幕截图 2023-04-15 185127.png

判断命令

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"

屏幕截图 2023-04-15 194846.png

屏幕截图 2023-04-15 194914.png

第三章:执行过程和原理

执行

1.shell脚本一般以.sh结尾,也可以没有,这是一个约定;第一行需要指定用什么命令解释器来执行

1. #! /bin/bash
2.#! /usr/bin/env bash

2.启动方式

#文件名启动
./filename.sh

#解释器运行
bash ./filename.sh

# source 运行
source ./filename.sh

屏幕截图 2023-04-15 195754.png

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

屏幕截图 2023-04-15 200806.png

命令替换

在子进程中执行命令,并用得到的结果替换包裹的内容,形式上有两种:$(...)或`...`

#!/bin/bash
echo $(whoimi)
foo(){
    echo "asdasd"
}
    a=`foo`
文件名展开

当有单词没有被引号包裹,且其中出现了'*','?',and,'['字符,则shell会去按照正则匹配的方式查找文件名进行替换,如果没找到则保持不变

#!/bin/bash
$ echo D*
#输出当前目录下所有以D字母开头的目录,文件

屏幕截图 2023-04-15 201626.png

屏幕截图 2023-04-15 201707.png

屏幕截图 2023-04-15 201844.png

屏幕截图 2023-04-15 201921.png