zoukankan      html  css  js  c++  java
  • 《Linux.Shell编程从入门到精通》读书笔记

    第一章 第一个Shell程序

    • 以 #!解析器名称 开头,表示选择哪个解释器解释shell脚本
    • source命令
    • export命令
    • env命令
    • unset命令
      第二章 shell编程基础
    • 函数传递
    • 标准输入输出符号
      第三章 编程的基本元素
    • 获取命令执行返回值
    • $((数值计算)) 获取数值计算结果 如:$((100 - 2*100/400))
    • 替换运算符
    • 模式匹配运算符
    • shift命令可以截取参数列表最左端的一个参数
    • type命令判断被执行命令的来源(别名、关键字、函数、内置命令、外部命令)
    • test命令用于评估表达式,返回零(true)或者非零(false)
    • 逻辑运算符
    • 运算符号
    • 执行反单引号(`)之间的命令,引用结果作为字符串
    • getopt命令用于分析命令标志和参数
      第四章 正则表达式
    • 元字符
    • POSIX字符集
    • 后向引用
    • 交替、分组
      第五章 基本文本处理
    • 排序文本
    • 文本去重
    • 统计文本
    • 打印和格式化输出
    • 提取文本开头和结尾
    • 字段处理
    • 文本替换
    • Linux下的配置文件
      第六章 文件和文件系统
    • 文件
    • 文件系统
      第七章 流编辑器sed
    • 工作地址范围
    • 命令
    • [:特殊字符:]用于匹配特俗字符
      第八章 文本处理利器awk
    • awk代码结构
    • 内建变量
    • 局部变量
    • 字符串函数
      第九章 进程
    • 进程管理命令
    • init进程
    • 调度系统任务
    • 加载proc虚拟文件系统:mount -t proc proc /proc
      第十章 OpenSSH
    • 安装openssh
    • 使用SSH登录远程主机(要求远程主机正在运行sshd)
      第十一章 实用程序(日志处理程序、系统监控程序)
    • 日志清理程序
    • 系统监控程序

    第一个Shell程序

    以 #!解析器名称 开头,表示选择哪个解释器解释shell脚本

    source命令
    使用source执行shell脚本时,不会创建子进程,而在父进程中直接执行。
    当需要在程序中修改当前shell本身的环境变量时,使用source命令
    source命令也可用来读入包含函数的文件
    使用方法:source fileName 或者 . fileName

    export命令
    export命令用于设置或显示环境变量
    使用方法:export [-fnp] [变量名称]=[变量设置值]
    -f 代表[变量名称]中为函数名称
    -n 删除指定的变量。变量实际上并没有删除,只是不会输出到后续指令的执行环境中
    -p 列出所有的shell赋予程序

    env命令
    env命令用于临时改变环境变量值

    unset命令
    从当前shell删除变量或函数

    shell编程基础

    函数传递
    $0 $1 $2 位置参数
    $* 以一个单字符串显示所有向脚本传递的参数
    $@ 所有向脚本传递的参数
    $# 传入函数的参数个数
    $$ 脚本运行的当前进程id号
    $! 后台运行的最后一个进程id号
    $? 显示最后命令的退出状态
    $- 显示shell使用的当前选项

    标准输入输出符号
    0<:标准输入
    1> 或者 >:重定向标准输出
    2>:重定向标准错误
    &>:标准输出和标准错误

    编程的基本元素

    获取命令执行返回值

    1. $(命令) 如:$(date +%Y%m%d%H%M%S)
    2. 命令 如:echo 123

    $((数值计算)) 获取数值计算结果 如:$((100 - 2*100/400))

    替换运算符

    1. ${varname:-word}
      如果varname存在且非null,则返回varname的值;否则,返回word
    2. ${varname:=word}
      如果varname存在且非null,则返回varname的值;否则,将varname的值设置为word,然后返回word
    3. ${varname:?message}
      如果varname存在且非null,则返回varname的值;否则打印message,并退出当前脚本
    4. ${varname:+word}
      如果varname存在且非null,则返回word;否则返回null

    模式匹配运算符

    1. ${varname#pattern}
      如果模式匹配变量取值的开头处,则删除匹配的最短部分,并返回剩下部分
    2. ${varname##pattern}
      如果模式匹配变量取值的开头处,则删除匹配的最长部分,并返回剩下部分
    3. ${varname%pattern}
      如果模式匹配变量取值的结尾处,则删除匹配的最短部分,并返回剩下部分
    4. ${varname%%pattern}
      如果模式匹配变量取值的结尾处,则删除匹配的最长部分,并返回剩下部分
    5. ${varname/pattern/string} ${varname//pattern/string}
      将varname中匹配模式的最长部分替换为string
      第一种格式中,只有匹配的第一部分被替换,第二种格式中,varname中所有匹配的部分都被替换
      如果模式以#开头,则必须匹配varname的开头,如果模式以%开头,则必须匹配varname的结尾

    shift命令可以截取参数列表最左端的一个参数

    type命令判断被执行命令的来源(别名、关键字、函数、内置命令、外部命令)

    test命令用于评估表达式,返回零(true)或者非零(false)

    逻辑运算符

    1. 关于文件与目录的侦测逻辑卷标!
      -f 常用!侦测『文件』是否存在 eg: if [ -f filename ]
      -d 常用!侦测『目录』是否存在
      -b 侦测是否为一个『 block 文件』
      -c 侦测是否为一个『 character 文件』
      -S 侦测是否为一个『 socket 标签文件』
      -L 侦测是否为一个『 symbolic link 的文件』
      -e 侦测『某个东西』是否存在!
    2. 关于程序的逻辑卷标!
      -G 侦测是否由 GID 所执行的程序所拥有
      -O 侦测是否由 UID 所执行的程序所拥有
      -p 侦测是否为程序间传送信息的 name pipe 或是 FIFO
    3. 关于文件的属性侦测!
      -r 侦测是否为可读的属性
      -w 侦测是否为可以写入的属性
      -x 侦测是否为可执行的属性
      -s 侦测是否为『非空白文件』
      -u 侦测是否具有『 SUID 』的属性
      -g 侦测是否具有『 SGID 』的属性
      -k 侦测是否具有『 sticky bit 』的属性
    4. 两个文件之间的判断与比较 ;例如[ test file1 -nt file2 ]
      -nt 第一个文件比第二个文件新
      -ot 第一个文件比第二个文件旧
      -ef 第一个文件与第二个文件为同一个文件( link 之类的文件)
    5. 逻辑的『和(and)』『或(or)』
      && 逻辑的 AND 的意思
      || 逻辑的 OR 的意思

    运算符号
    = 等于 应用于:整型或字符串比较 如果在[] 中,只能是字符串
    != 不等于 应用于:整型或字符串比较 如果在[] 中,只能是字符串
    < 小于 应用于:整型比较 在[] 中,不能使用 表示字符串
    大于 应用于:整型比较 在[] 中,不能使用 表示字符串
    -eq 等于 应用于:整型比较
    -ne 不等于 应用于:整型比较
    -lt 小于 应用于:整型比较
    -gt 大于 应用于:整型比较
    -le 小于或等于 应用于:整型比较
    -ge 大于或等于 应用于:整型比较
    -a 双方都成立(and) 逻辑表达式 –a 逻辑表达式
    -o 单方成立(or) 逻辑表达式 –o 逻辑表达式
    -z 空字符串
    -n 非空字符串

    执行反单引号(`)之间的命令,引用结果作为字符串

    getopt命令用于分析命令标志和参数

    正则表达式

    元字符
    ^ 锁定行或字符串的开始
    $ 锁定行或字符串的结尾
    当^和$结合使用时,意味着模式必须匹配整个串
    . 匹配除了换行符以外的任意字符
    [...] 方括号表达式,匹配括号内任意一个字符;如果^符号位于方括号的开始,则不匹配方括号中的任意字符
    转义字符,用于打开或关闭后续字符的特殊含义
    x{m,n} 区间表达式,匹配x字符出现的次数区间
    ? 匹配前面正则表达式的零个或一个实例

    • 匹配前面正则表达式的一个或多个实例
    • 匹配零个或多个前面字符
      | 匹配前面或后面的正则表达式
      () 匹配括号括起来的正则表达式
       单词锁定符,代表单词的开头和结尾,即单词的分界处
      B 匹配两个单词组成字符间的空字符串
      < > 分别匹配单词开头和单词结尾
      换行符
      d 匹配一位数字
      w 匹配文字和数字字符
      W 匹配一个或多个非单词字符

    POSIX字符集
    [:alnum:] 数字字符
    [:alpha:] 字母字符
    [:blank:] 空格与制表符
    [:cntrl:] 控制字符
    [:digit:] 数字字符
    [:graph:] 非空格
    [:lower:] 小写字母
    [:print:] 可显示的字符
    [:punct:] 标点符号字符
    [:space:] 空白(whitespace)字符
    [:upper:] 大写字母
    [:xdigit:] 十六进制数字
    [. .] 排序符号,如[.cn.]表示cn字符序列,而单独的c和n都不行
    [= =] 等价字符集

    后向引用:匹配之前正则表达式使用(和)括起来选定之后引用的模式,使用1~9来引用选定的模式
    如:(go).*1 匹配一行中前后出现两个go

    交替、分组
    交替|:在不同序列之间用管道符号隔开
    分组():让元字符修饰前置字符串
    如:(man|woman)+ 匹配一个或多个man或者woman字符串

    基本文本处理

    排序文本
    sort命令用于排序文件,对已排序的文件进行合并,并检查文件以确定它们是否已排序

    文本去重
    uniq命令用于文本去重(在使用uniq命令前,先使用sort命令,使所有重复行相邻)

    统计文本
    wc命令用于统计文本行数、字数以及字符数

    打印和格式化输出
    pr命令用于将文本转换成适合打印的文件
    fmt命令用于编排文本文件
    fold命令限制文本宽度

    提取文本开头和结尾
    head命令提取文件开头
    tail命令提取文件结尾

    字段处理
    cut命令用于从一个文本文件或者文本流中提取文本列
    join命令用于根据指定栏位,找到两个文件中指定栏位内容相同的行,将它们合并,并根据要求的格式输出内容

    文本替换
    tr命令用于替换字符

    Linux下的配置文件
    /etc/group 用户组定义
    /etc/passwd 用户信息定义
    /etc/inittab init的配置文件,在Linux启动时扮演重要角色
    /etc/shadow 用户密码的存放地址
    /etc/crontab cron(定期执行命令的程序)的配置文件
    /etc/fstab 文件系统信息

    文件和文件系统

    文件
    ls命令用于列出文件
    chown命令用于改变文件的所有者
    chgrp命令用于改变文件的用户组
    umask命令用于指定哪些权限在新文件的默认权限中被删除
    chmod命令用于修改文件权限
    touch命令更新文件的访问和修改时间
    find命令用于寻找文件
    xargs命令用于遍历处理文件
    comm命令用于比较两个已排序文件之间的差异
    diff命令用于比较两个文件之间的差异

    文件系统
    fdisk命令用于查看/修改系统的分区表
    mkfs命令用于创建文件系统
    mount命令用于加载文件系统到指定的加载点
    umount命令用于卸载已经加载的文件系统
    df命令用于显示当前挂载情况

    流编辑器(sed)

    工作地址范围

    1. 行地址 如:删除第一行 sed -e '1d' filePath
    2. 行范围地址 如:打印1到5行 sed -n -e '1,5p' filePath
    3. 正则表达式地址 如:打印所有以开头的注释行 sed -n -e '/^#/p' filePath
    4. 两个用逗号分开的正则表达式之间的地址 如:打印从包含'BEGIN'的行开始,并且包含'END'的行结束的文本块 sed -n -e '/BEGIN/,/END/p' filePath

    命令

    1. d 删除
    2. p 打印
    3. s/// 替换
    4. = 打印行号
    5. i 插入
    6. a 追加

    [:特殊字符:]用于匹配特俗字符

    文本处理利器(awk)

    awk代码结构

    1. 处理输入前的初始化
      BEGIN{
      ....
      }
    2. 处理输入过程
      [ 条件 ] {
      ...
      }
    3. 处理完所有输入后的扫尾工作
      END{
      ...
      }

    内建变量
    FILENAME 当前输入文件的名称
    FS 字段分隔符(支持正则表达式),默认为空格
    OFS 输出字段分隔字符,默认为空格
    ORS 输出记录分隔字符,默认为
    RS 输入记录分隔字符
    NF 当前记录的字段数
    NR 在工作中的记录数
    FNR 当前输入文件的记录数

    局部变量:列在函数参数列表中并且在字首前置一些额外的空白 如: add(x,y, sum) {}

    字符串函数
    sub(/reg/, newsubstr, str) 只替换第一个匹配字符串
    gsub(/reg/, newsubstr, str) 将字符串str中所有符号/reg/正则的子串替换为字符串newsubstr
    index(str, substr) 返回子串substr在串str中的索引
    length(str) 返回字符串的长度
    match(str, /reg/) 如果在串str中找到正则/reg/匹配的串,则返回出现的位置,未找到则返回0
    split(str, array, sep) 使用分隔符sep把字符串分解成数组array
    substr(str, position[, length]) 返回str中从position开始的length个字符
    toupper(str) 对字符进行大小写转换
    sprintf("format", expr) 对expr使用printf格式说明

    进程

    进程管理命令
    fork函数用于创建进程
    ps命令用于查看系统正在运行的进程
    top命令用于查看系统一段时间进程的动态信息
    pstree命令用于打印进程树形结构
    Ctrl+C快捷键用于中断前台进程
    Ctrl+快捷键用于杀死前台进程
    Ctrl+Z快捷键用于挂起前台进程
    bg命令用于将挂起进程转换为后台进程
    fg命令用于将后台进程转换为前台进程
    jobs命令用于显示当前shell的进程状况
    kill命令用于向指定进程发送信号
    init命令用于进程初始化工具,可切换运行等级

    init进程

    1. /etc/inittab init程序读取的配置文件
      基本格式为 id:runlevels:action:process
      • id为1~2个字符,配置行的唯一标识,在配置文件中不能重复
      • runlevels(运行等级)取值如下
        • 等级0表示:表示关机(千万不能把initdefault 设置为0)
        • 等级1表示:单用户模式
        • 等级2表示:无网络连接的多用户命令行模式
        • 等级3表示:有网络连接的多用户命令行模式
        • 等级4表示:不可用
        • 等级5表示:带图形界面的多用户模式
        • 等级6表示:重新启动(千万不要把initdefault 设置为6)
      • action取值如下
        • respawn 启动并监视第4项指定的process,若process终止则重启它
        • wait 执行第4项指定的process,并等待它执行完毕
        • once 执行第4项指定的process
        • boot 不论在哪个执行等级,系统启动时都会运行第4项指定的process
        • bootwait 不论在哪个执行等级,系统启动时都会运行第4项指定的process,且一直等它执行完备
        • off 关闭任何动作,相当于忽略该配置行
        • ondemand 进入ondemand执行等级时,执行第4项指定的process
        • initdefault 系统启动后进入的执行等级,该行不需要指定process
        • sysinit 不论在哪个执行等级,系统会在执行boot 及bootwait之前执行第4项指定的process
        • powerwait 当系统的供电不足时执行第4项指定的 process,且一直等它执行完毕
        • powerokwait 当系统的供电恢复正常时执行第4项指定的process,且一直等它执行完毕
        • powerfailnow 当系统的供电严重不足时执行第4项指定的process
        • ctrlaltdel 用户按下【Ctrl+Alt+Del】时执行的操作
        • kbrequest 当用户按下特殊的组合键时执行第4项指定的process,此组合键需在keymaps文件定义
      • process为所要执行的shell命令。任何合法的shell语法均适用于该字段。
    2. /etc/rc.d/rcX.d文件(X代表运行等级)含有各个运行等级服务启动和终止配置
      /etc/rc.d/init.d目录下存放着对应运行等级的服务脚本
    3. 修改配置/etc/inittab后马上生效:kill -1 1 或者 init q

    调度系统任务

    1. crontab命令用于调度重复性的任务
      控制访问的文件:cron.allow、cron.deny
    2. at命令用于调度只执行一次的任务
      控制访问的文件:at.deny

    加载proc虚拟文件系统:mount -t proc proc /proc

    SSH

    安装openssh

    • 替换阿里云的源
      echo "http://mirrors.aliyun.com/alpine/latest-stable/main/" > /etc/apk/repositories
      echo "http://mirrors.aliyun.com/alpine/latest-stable/community/" >> /etc/apk/repositories

    • 同步时间
      cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

    • 更新源、安装openssh 并修改配置文件、生成key、启动sshd服务
      apk update &&
      apk add --no-cache openssh-server tzdata &&
      sed -i "s/#PermitRootLogin.*/PermitRootLogin yes/g" /etc/ssh/sshd_config &&
      ssh-keygen -t rsa -P "" -f /etc/ssh/ssh_host_rsa_key &&
      ssh-keygen -t ecdsa -P "" -f /etc/ssh/ssh_host_ecdsa_key &&
      ssh-keygen -t ed25519 -P "" -f /etc/ssh/ssh_host_ed25519_key &&
      /usr/sbin/sshd -D

    使用SSH登录远程主机(要求远程主机正在运行sshd)

    • 基于口令的登录方法
      ssh -l 登录账号 远程主机

    • 基于密钥对的登录方法

      • 生成密钥对:ssh-keygen -d
      • 把公钥上传到服务器上(/.ssh/id_dsa.pub、/.ssh/authorized_keys)
      • 测试自动登录:ssh [登录账号@]远程主机 (需要输入第一步输入的passphrase,若想不输入passphrase可以考虑ssh-agent)

    实用程序

    日志清理程序
    把以下代码保存为log_clean.sh文件中即可使用
    内含操作:备份重要的日志、限制日志目录大小、清理老旧日志

    
    # maximum log size
    alarmrate=500
    # the max size file can reach
    file_max_size=5
    # this is the directory where fresh logs are originally written
    working_dir=/mnt/soho_storage/log
    # this is the frequency our program runs
    SLEEPTIME=5
    
    # append year.month.day and timestamp to log filename
    filenameConvert()
    {
        timestamp=$(date +%Y%m%d%H%M%S)
        timestamp=`echo $timestamp`
        RETVAL=$1.$timestamp
    }
    
    # search dir to fetch the oldest log
    searchdir()
    {
        oldestlog=`ls -rt | head -n 1 | awk '{print $1}'`
    }
    
    # this function clean old logs under working dir if it reaches it's size limitation
    clear_old_log_under_working_dir()
    {
        cd $working_dir
        while true
        do
            logsize=`du -ms $working_dir | awk '{print $1}'`
            if [ $logsize -gt $alarmrate ]
            then
                searchdir
                rm -rf $oldestlog
            else
                break;
            fi
        done
    }
    
    # this is the main process of our log backup activity
    backuplog_process()
    {
        cd $log_ram_dir
        for i in * 
        do
            file_size=`du -m $i | awk '{print $1}'`
            # need to backup log file
            case $i in access.log | error.log | apcupsd.events | soho.log)
                if [ ! -d $working_dir ]
                then
                    mkdir -p $working_dir
                fi
                if [ file_size -gt file_max_size ]
                then
                    filenameConvert $i
                    cp $log_ram_dir/$i $working_dir/$RETVAL
                    echo "" > $log_ram_dir/$i
                    clear_old_log_under_working_dir
                fi
                ;;
            *)
                if [ file_size -gt file_max_size ]
                then
                    echo "" > $log_ram_dir/$i
                fi
        done
    }
    
    while true
    do
        backuplog_process
        sleep $SLEEPTIME
    done
    
    

    系统监控程序
    把以下代码保存为system_monitor.sh文件中即可使用
    内含操作:监控内存、硬盘、CPU、进程,形成状态报告

    
    # maximum ratio of memory usage
    mem_quota=80
    # hard disk
    hd_path=/dev/sda1
    # maximum ratio of hard disk usage
    hd_quota=80
    # maximum ratio of cpu usage
    cpu_quota=80
    # time gap between two times fetching cpu status
    time_gap=60
    # generate report every 10 minutes
    runtime_gap=60
    
    # fetch the ratio of memory usage
    # @return 1: if larger than $mem_quota
              0: if less than $mem_quota
    watch_memory()
    {
        mem_total=`cat /proc/meminfo | grep MemTotal | awk '{print $2}'`
        mem_free=`cat /proc/meminfo | grep MemFree | awk '{print $2}'`
        mem_usage=$((100-mem_free*100/mem_total))
        if [ $mem_usage -gt $mem_quota ]
        then
            mem_message="ALARM!! The memory usage is $mem_usage%!!"
            return 1
        else
            return 0
        fi
    }
    
    # fetch the top 10 most wasting memory process
    proc_memory_top10()
    {
        mem_busiest=`ps aux | sort -nk 4r | head -n 11`
    }
    
    # fetch the ratio of hard disk usage
    # @return 1: if larger than $hd_quota
              0: if less than $hd_quota    
    watch_hd()
    {
        hd_usage=`df | grep $hd_path | awk '{print $5}' | sed 's/%//g'`
        if [ $hd_usage -gt $hd_quota ]
        then
            hd_message="ALARM!! The hard disk usage is $hd_usage%!!"
            return 1
        else
            return 0
        fi
    }
    
    # fetch cpu status at a time point
    # format used unused
    get_cpu_info()
    {
        cat /proc/stat | grep -i "^cpu[0-9]+" | awk '{used+=$2+$3+$4;unused+=$5+$6+$7+$8} END{print used,unused}'
    }
    
    # fetch the ratio of cpu usage
    # fetch cpu stat two times, with time gap, then calculate the average status
    # @return 1: if larger than $cpu_quota
              0: if less than $cpu_quota    
    watch_cpu()
    {
        time_point_1=`get_cpu_info`
        sleep $time_gap
        time_point_2=`get_cpu_info`
        cpu_usage=`echo $time_point_1 $time_point_2 | awk '{used=$3-$1;total+=$3+$4-$2-$1}';print $used*100/total`
        if [ $cpu_usage -gt $cpu_quota ]
        then
            cpu_message="ALARM!! The cpu usage is over $cpu_usage%!!"
            return 1
        else
            return 0
        fi
    }
    
    # fetch the top 10 busiest processes
    proc_cpu_top10()
    {
        proc_busiest=`ps aux | sort -nk 3r | head -n 11`
    }
    
    while true
    do
        # report content
        report=""
        # memory monitor
        if [ `watch_memory` -eq 1 ]
        then
            report=$report'
    '$mem_message
            proc_memory_top10
            report=$report'
    '$mem_busiest
        fi
        # hard disk monitor
        if [ `watch_hd` -eq 1 ]
        then
            report=$report'
    '$hd_message
        fi
        # cpu monitor
        if [ `watch_cpu` -eq 1 ]
        then
            report=$report'
    '$cpu_message
            proc_cpu_top10
            report=$report'
    '$proc_busiest
        fi
        # feedback report
        if [ -n $report ]
        then
            # todo...
        fi
        # sleep time
        sleep $((runtime_gap-time_gap))
    done
    
    
  • 相关阅读:
    PNG文件格式具体解释
    opencv2对读书笔记——使用均值漂移算法查找物体
    Jackson的Json转换
    Java实现 蓝桥杯VIP 算法训练 装箱问题
    Java实现 蓝桥杯VIP 算法训练 装箱问题
    Java实现 蓝桥杯VIP 算法训练 单词接龙
    Java实现 蓝桥杯VIP 算法训练 单词接龙
    Java实现 蓝桥杯VIP 算法训练 方格取数
    Java实现 蓝桥杯VIP 算法训练 方格取数
    Java实现 蓝桥杯VIP 算法训练 单词接龙
  • 原文地址:https://www.cnblogs.com/phonecom/p/10052319.html
Copyright © 2011-2022 走看看