shell 脚本编程

109 阅读4分钟

1. 学习课程

www.bilibili.com/video/BV19t…

www.bilibili.com/video/BV1Jx…

2. 学习背景

老早就想学习一下shell编程了,现在有这个机会了,入职了一家创业的互联网企业,有机会接触到更多的运维知识了,所以掌握shell是很有必要的。至此好好学习和温故一下shell

3. 学习内容

1. 如果脚本未指定shebang,脚本执行的时候,默认用当前的shell去解释脚本 就是$SHELL
   如果shebang制定了可执行的解释器,如/bin/bash,/usr/bin/python,脚本在执行的时候,文件
   名会作为参数传递给解释器
   
2.  chmod +x ./hello.sh

    /bin/sh ./hello.sh  
    
    echo $SHELL
    
    echo -e 解析字符串中的特殊字符
         -n 不换行输出
         \n 换行
         \r 回车
         \b 退格
         \t 制表符
         
    eval 执行多个命令,把后边的命令传给他当做参数、
    exec date ,不创建子进程,执行后续命令,且执行完毕胡,自动exit
    
执行shell脚本的方式
    1.文件本身没有执行权限,没x权限,使用这些办法去执行,bash script.sh,或者sh 
    script.sh
    2. 使用相对路径去执行,必须要有x权限

三剑客:grep sed awk

echo $HISTSIZE 

echo $HISTFILE

! + 历史命令id 来执行这条命令

!!用来执行上次的命令

bash 特性
    1. 文件路径tab补全
    2. 命令补全
    3. 快捷键ctrl + l
    4. 通配符

sudo -i: 为了频繁的执行某些只有超级用户才能执行的权限,而不用每次输入密码,可以使用该命令。提示输入密码时该密码为当前账户的密码。没有时间限制。执行该命令后提示符变为“#”而不是“$”。想退回普通账户时可以执行“exit”或“logout” 。
shell变量:
    变量定义和赋值,变量和值之间不能有空格
    bash默认把变量类型认为是字符串,bash变量是弱类型,无需声明类型
 
 name="大碗宽面"
 echo ${name} 可以简写为 echo $name
 
 单引号变量不识别特殊语法、 双引号变量能识别特殊符号
 
 变量的作用域,本地变量只针对当前的shell进程
 $?: 记录的是上一次shell 命令执行的结果
 
 每次调用bash都会开启一个子shell,因此不保留当前的shell变量,
 调用source就是在当前shell环境加载脚本,因此保留变量

3.1 shell子串的花式用法

name=yawu,元素是有索引的,从0开始

${var}: 返回变量值

${#var}: 返回变量长度,字符长度

${#var:start}: 返回变量start数值之后的字符,start是

${#var:start:length}: 提取start之后的length限制的字符

${#var#word}: 从变量开头删除最短匹配的word子串

${#var##word}: 从变量开头,删除最长匹配的word

${#var%word}: 从变量结尾删除最短的word

${#var%%word}: 从变量结尾开始删除最长匹配的word

${#var/pattern/string}:用string 代替第一个匹配的pattern

${#var//pattern/string}:用string代替所有的pattern

unset 消除一个变量

#号写在命令行中就直接是一个注释符

3.2 字符串统计长度的方法

    name=dingyawu
   
    echo ${name} | wc -l: 统计行数
    echo ${name} | wc -L: 统计最长的行数的字符个数,
    cat test.log | wc -L : 找出文件中最长的行,并返回行的长度
    
    expr length "${name}": 利用数值计算expr命令
    
    echo "${name}" | awk '{print length($0)}': awk统计长度,length函数
    
    for num in {1..100};do echo ${num};done : 注意是两个..
    
    time 命令统计命令执行时间
    
    seq 10: 生成序列号,默认以换行分割
    
    seq -s : 10 以冒号分割
    
    反引号取得命令结果
    for n in {1..3}; do str1=`seq -s : 9`;echo ${str1}; done 
    : 理解这样一个命令
    
    shell编程尽量使用linux内置的命令,内置的操作和内置的函数,效率最高的C语言开发,效率最高
    尽可能减少管道符的操作
    
    $? 0表示成功, 1-255错误码
    

在linux中反引号中写入linux命令,执行结果会被保留下来

每个用户都有自己的环境变量配置文件, ~/.bash_profile和~/.bashrc 而且以个人配置文件优先加载变量读取,当你需要给所有用户都使用某个变量,写入全局就是用/etc/profile

set: 输出所有变量,包括全局变量和局部变量
env: 只显示全局变量
export: 显示设置的环境变量值

export | awk -F '[ :=]' '{print $3}': 

定义shell变量,变量名不需要加$,本地变量只在用户当前shell生存期中有效

read -t 15 -p "please input your name and age" your_name your_age

 $0 : 获取shell脚本文件名称
 $n: 获取脚本的第n各参数
 $#:  获取shell脚本的参数个数
 
 中括号前后必须有空格,否则报错的
 [ $# -ne 2 ] && {
 echo "must two arguments"
 exit 119
}
echo "no problem"

echo $?

怎么让程序后台执行
nohup ping baidu.com 1> /dev/null

创建5个文件夹
touch dingyawu_{1..5}_finished.log

result=${param:-dingyawu}
如果param为空,返回word字符,赋值给result

result=${param:=dingyawu}
如果param为空,返回dingyawu代替param,赋值给result

result=${param:?dingyawu}

result=${param:+dingyawu}
如果param为空,什么都不做,否则返回dingyawu

find 需要搜索的目录 -name filename -type 文件类型 -mtime +7 | xargs rm -f

find ${dir_path:=/tmp/shell/test} -name "*.tar.gz" -type f -mtime +7 | xargs rm -f

删除7天以上的数据

echo ${1.. 100}

echo ${1.. 100} | tr " " "+"

seq -s "+" 100

echo ${1.. 100} | tr " " "+" | bc

echo $((`seq -s "+" 100`))

seq -s " + " 100 | xargs expr

test -r file a -w file 
文件file同时具有rw权限返回true

test -r file o -w file 

[ 2 > 1 ] && echo yes || echo no

[ ! -d "$path" ] && mkdir $path -p


which ls

echo $SHELL

echo $HISTSIZE

vim ~/.bash_history : 存放历史命令

echo $HISTFILE : 存放用户历史命令的文件

history -c : 清空历史命令

!历史命令 : 快速执行历史命令

shell, 具体实现了shell的软件

windows 中存在 *.bat 批处理脚本
Linux 中常用 *.sh 脚本文件

变量赋值不得有空格

echo ${name} 简写为 echo $name

pstree

$?  0表示成功, 1-255表示错误码,用来表示上条命令的执行结果
单引号不能识别特殊语法,双引号可以识别特殊语法

每次调用bash 解释器执行脚本,都会开启一个子shell,因此不保留当前的shell变量,通过pstree命令查看进程树

调用source 是在当前shell环境加载脚本,因此保留变量

echo $PATH

su yauw

useradd yawu
passwd yawu

面试题:$* 和 $@ 的区别
都表示传递给函数或者脚本的所有参数,不用双引号包围,没有区别
"$*" 是一份数据, “$@” 每个参数都看成是一个数据

怎么让程序后台执行,并且日志输出到黑洞
nohup ping baidu.com & 1> /dev/null