Linux

初级阶段

  1. Linux是由Unix操作系统为内核的类Unix操作系统,Mac OS也属于类Unix操作系统的。

安装&网络配置

  1. 安装后好登录的第一个用户就是root,密码默认没有的可以直接进入。

  2. 登录后最前方会出现一段字符,第一个代表用户、@用于分割、第二个代表主机、~代表用户家目录、#代表是root登录,普通用户登录是$。

  3. 远程登陆我们可以使用X shell5软件链接ssh root@ip

  4. Linux查看IP有两种:ifconfigip addr

  5. 配置网络

    1. 点击编辑在下拉框中选择虚拟网络编辑,选择VMnet8后勾选Nat模式、将主机虚拟适配器链接此网络和使用本地DHCP。

    2. 设置子网和子网掩码并点击NAT设置,点进去之后设置网关即可。

    3. 配置Linux IP

      vi /etc/sysconfig/network-scripts/ifcfg-ens33   #用于进入配置文件
      #进入后不能直接编辑,需要按下i键才可以编辑,将下面的修改或添加
      bootproto=static
      onboot=yes
      IPADDR=10.0.0.10
      NETMASK=255.255.255.0
      GATEWAY=10.0.0.2
      DNS1=119.29.29.29
      按下esc保存
      :wq!强制退出
      systemctl restart network    #这条命令可以重启网络

基本知识&使用

  1. 了解一些Linux的基础只是可以让你更加方便的使用Linux。

  2. Linux快捷键

    tab                         # 用于自动补全命令/文件名/目录名
    ctrl+l                      # 清理终端显示 
    clear/cls                   # 清理终端显示
    ctrl+c                      # 终止当前操作

目录结构

  1. Linux的目录与win的不同,Linux是文件系统下直接/开始并没有什么盘这个概念的。Linux使用正斜杠来跨文件夹,它的结构是树状结构。

  2. 登录系统后,在当前命令窗口输入命令:

    ls /
    /bin:bin是Binary的缩写, 这个目录存放着最经常使用的命令。
    /boot:这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件。
    /dev:dev是Device(设备)的缩写, 该目录下存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。
    /etc:这个目录用来存放所有的系统管理所需要的配置文件和子目录。
    /home:用户的主目录,在Linux中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的。
    /lib:这个目录里存放着系统最基本的动态连接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。
    /lost+found:这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件。
    /media:linux系统会自动识别一些设备,例如U盘、光驱等等,当识别后,linux会把识别的设备挂载到这个目录下。
    /mnt:系统提供该目录是为了让用户临时挂载别的文件系统的,我们可以将光驱挂载在/mnt/上,然后进入该目录就可以查看光驱里的内容了。
    /opt:这是给主机额外安装软件所摆放的目录。比如你安装一个ORACLE数据库则就可以放到这个目录下。默认是空的。
    /proc:这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。
        这个目录的内容不在硬盘上而是在内存里,我们也可以直接修改里面的某些文件,比如可以通过下面的命令来屏蔽主机的ping命令,使别人无法ping你的机器:
        echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
    /root:该目录为系统管理员,也称作超级权限者的用户主目录。
    /sbin:s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序。
    /selinux:这个目录是Redhat/CentOS所特有的目录,Selinux是一个安全机制,类似于windows的防火墙,但是这套机制比较复杂,这个目录就是存放selinux相关的文件的。
    /srv:该目录存放一些服务启动之后需要提取的数据。
    /sys:这是linux2.6内核的一个很大的变化。该目录下安装了2.6内核中新出现的一个文件系统 sysfs 。
        sysfs文件系统集成了下面3种文件系统的信息:针对进程信息的proc文件系统、针对设备的devfs文件系统以及针对伪终端的devpts文件系统。
        该文件系统是内核设备树的一个直观反映。
        当一个内核对象被创建的时候,对应的文件和目录也在内核对象子系统中被创建。
    /tmp:这个目录是用来存放一些临时文件的。
    /usr:这是一个非常重要的目录,用户的很多应用程序和文件都放在这个目录下,类似于windows下的program files目录。
    /usr/bin:系统用户使用的应用程序。
    /usr/sbin:超级用户使用的比较高级的管理程序和系统守护程序。
    /usr/src:内核源代码默认的放置目录。
    /var:这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。
        在linux系统中,有几个目录是比较重要的,平时需要注意不要误删除或者随意更改内部文件。
    /etc:上边也提到了,这个是系统中的配置文件,如果你更改了该目录下的某个文件可能会导致系统不能启动。
    /bin, /sbin, /usr/bin, /usr/sbin: 这是系统预设的执行文件的放置目录,比如 ls 就是在/bin/ls 目录下的。
    值得提出的是,/bin, /usr/bin 是给系统用户使用的指令(除root外的通用户),而/sbin, /usr/sbin 则是给root使用的指令。
    /var:这是一个非常重要的目录,系统上跑了很多程序,那么每个程序都会有相应的日志产生,而这些日志就被记录到这个目录下,具体在/var/log 目录下,另外mail的预设放置也是在这里。
  3. 绝对路径就是更目录到文件的唯一路径,向对路径是从某个文件夹下的一段路径。

  4. 计算机中文件大小的表示方式,每一个单位乘以1024等于下一个单位。

    单位 英文 单位 英文
    字节 B(Byte) K(Kibibyte)
    M(Mebibyte) 千兆 G(Gigabyte)
    T(Terabyte) P(Petabyte)
    E(Exabyte) Z(Zettabyte)
    Y(Yottabyte)    
  5. Linux文件的含义:绿色文件代表可执行文件、蓝色文件代表文件夹、白色文件代表普通文件。

  6. Linux的文件系统

    1. 用户在硬件存储设备中执行的文件建立,写入,读取,修改,转存与控制等操作都是依赖文件系统完成的。文件系统的作用是合理规划硬盘,保证用户正常使用。/etc/fstab是用来存放文件系统的静态信息的文件,cat /etc/fstab检查Linux的文件系统。

    2. Linux系统支持数十种文件系统,常见文件系统如下。

      1. Ext3 是一款日志文件系统,能够在系统异常宕机时避免文件系统资料丢失,并能 自动修复数据的不一致与错误。

      2. Ext4 Ext3 的改进版本,作为 RHEL 6 系统中的默认文件管理系统,它支持的存储容 量高达 1EB(1EB=1,073,741,824GB),且能够有无限多的子目录。另外,Ext4 文件系统能够批量分配 block 块,从而极大地提高了读写效率。

      3. XFS 是一种高性能的日志文件系统,而且是 RHEL 7 中默认的文件管理系统,它的优势在发生意外宕机后尤其明显,即可以快速地恢复可能被破坏的文件,而且强大的 日志功能只用花费极低的计算和存储性能。并且它最大可支持的存储容量为 18EB, 这几乎满足了所有需求。

基本命令

  1. 基础命令的使用

    ls                                      # 查看当前文件夹下内容
                                            # 需要注意的是,在所有目录底下都存在两个目录,分别是【.】和【..】,分别代表当前目录,上层目录!那么如何证明它的存在呢?
        ls -l /                             # 横向显示详细等于ll
        ls -a /                             # 显示文件夹下所有
        ls -h /                             # 配合-l个性化显示文件大小
        ls -la /                            # 横向显示该文件夹下的所有以详细参数、-l:横向显示详细、-a:显示文件夹下所有
        man ls                              # Linux下的帮助指令
    pwd                                     # 查看当前所在文件夹
    cd "path"                               # 切换文件夹
                                            # 我们知道切换目录的指令是cd,那么首先得知道如何切换目录,这个得用心记呀!
        cd .                                # 当前目录
        cd ..                               # 回到上一层目录
        cd ../                              # 回到指定的上一层目录
        cd -                                # 返回前一个工作目录
        cd ~|cd                             # 进入家目录
    touch "file path"                       # 如果文件不存在就创建文件
        touch xxx.py                        # 文件存在代表触摸,用于更新时间
        touch -t'07101530' "file"           # 修改文件的时间,很多黑客就会在恶意修改文件之后再修改成之前的时间
    mkdir "name"                            # 创建文件夹
        mkdir -p "path name"                # 递归创建文件夹,mkdir默认只能在当前目录下创建
        mkdir -p a/b  c/d                   # 递归创建两组文件夹
        mkdir -p test/a,b,c,d               # 递归在指定文件夹下创建多个文件夹  
        mkdir -p test/{a,b,c,d}             # 递归在指定文件夹下创建多个文件夹
        mkdir -p a/b/c/d/e                  # 递归创建一套文件夹
    rmdir "name"                            # 删除空文件夹
    rm "file"                               # 删除指定文件
        -i                                  # 需要删除确认
        -f                                  # 强制删除
        -r                                  # 递归删除目录和内容
    clear                                   # 清屏
    echo  "alex"                            # 表示输出
        echo $PATH                          # echo命令是有打印的意思、$符号后面跟上PATH,表示输出PATH的变量
        echo "sb666" > /tmp/chaoge.txt      # 将需要的信息写入指定文件
        echo "sb666" > e.txt                # 重定向>符号用于覆盖原有文件内容
        echo "sb666" >> e.txt               # 重定向>>符号用于追加到原有文件内容后面
    which ls                                # 在哪、从哪来
    vi "file"                               # 编辑文本文件,相当于windows下的notepad++
    mv "a.py" "b.py"                        # 重命名
        mv "a" "b"                          # 移动
    stat "file"                             # 显示文件的详细信息(最近访问)Access、(最近更改)Modify、(最近改动)Change
        -L      --dereference               # 跟随链接
        -f      --file-system               # 显示文件系统状态而非文件状态
                                            # 格式化输出参数:%a 八进制权限、%A 用可读性较好的方式输出权限
        -c      --format=%a                 # 使用指定输出格式代替默认值,每用一次指定格式,
        -t      --terse                     # 使用简洁格式输出
                --help                      # 显示此帮助信息并退出
                --version                   # 显示版本信息并退出
    ctrl+alt+f[1~7]                         # 可以切换(linux有7个终端)
    tty                                     # 查看当前终端
    who am i                                # 查看当前用户正在使用的终端和登陆时间
    w                                       # 查看所有终端
    ls                                      # 查看当前目录的文件和文件夹
    ls .la                                  # 查看当前目录的文件和文件夹(包括隐藏的)
    ls -l /tmp/                             # 查看详细信息
    cat name                                # 查看文件
        cat -n xxx.py                       # 显示行号
        cat -n /tmp/*.py                    # 找出以.py结尾的所有文件
        cat -E 1.txt                        # 在每一行的结尾加上$符
        cat >>/tmp/oldboy.txt << EOF        # 追加文字到文件,追加完后使用EOF退出追加模式
    more /etc/passwd                        # more命令文本会以百分比形式查看,按下空格space是翻页、按下b键是上一页、回车键向下读取内容
    ​
    cp xxx.py /tmp/                         # 移动xxx.py到/tmp目录下
        cp xxx.py /tmp/c.py                 # 移动xxx.py并改名为c.py
        cp -r                               # 递归,复制目录以及目录的子孙后代
        cp -p                               # 复制文件,同时保持文件属性不变
        cp -a                               # 相当于-pdr
    find /tmp/ -name "o.py"                 # 再指定文件夹中查找指定文件
        find /tmp/ -type f  -name "o.py"    # name后面加文件名、type后面加参数
        -name "file"                        # 按照文件名查找文件
        -type "value"                       # 查找某一类型的文件,诸如:
        -type b                             # 块设备文件。
        -type d                             # 目录。
        -type c                             # 字符设备文件。
        -type p                             # 管道文件。
        -type l                             # 符号链接文件。
        -type f                             # 普通文件。
        -type s                             # socket文件
    cat x.py|> x.txt                        # Linux提供的管道符“|”讲两条命令隔开,管道符左边命令的输出会作为管道符右边命令的输入。
        ls /tmp|grep '.txt'                 # 找到/tmp目录下所有txt文件
        netstat -tunlp |grep nginx          # 检查nginx的端口是否存活
    grep "wuddi" /tmp/oldboy.txt            # 全面搜索正则表达式并把行打印出来
        -i                                  # 忽略大小写
        -n                                  # 输出行号
        -v                                  # 反向选择
        --color = auto                      # 给关键词部分添加颜色
    head                                    # 显示文件前几行,默认前10行
    tail                                    # 显示文件后几行,默认后10行
        head -2 /tmp/oldboy.txt             # 查看前两行
        tail -2 /tmp/oldboy.txt             # 查看后两行
        tail -f xx.log                      # 监听文件持续刷新显示
    alias a=ls                              # 给命令起别名,简单命令的书写    
    unalias a                               # 取消别名
        alias cp='cp -i'                    # 默认别名
        alias egrep='egrep --color=auto'
        alias fgrep='fgrep --color=auto'
        alias grep='grep --color=auto'
        alias l.='ls -d .* --color=auto'
        alias ll='ls -l --color=auto'
        alias ls='ls --color=auto'
        alias mv='mv -i'
        alias rm='rm -i'
        alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
    which python                            # 查找环境变量中保存过的目录的文件绝对路径
    scp e.py [email protected]:/home/      # 传输本地文件到远程地址
    scp [email protected]:/y.txt           # 复制远程文件到本地
        -r                                  # 递归复制整个目录
        -v                                  # 详细方式输出
        -q                                  # 不显示传输进度条
        -C                                  # 允许压缩
    du -h /tmp                              # 显示指定的目录或文件所占用的磁盘空间。
        -s                                  # 显示总计
        -h                                  # 以k,M,G为单位显示,可读性强
    date                                    # 显示当前系统时间
        -d    --date=string                 # 显示指定的时间,而不是当前时间
        date +"%Y-%m-%d %T"                 # 以年-月-日 时分秒 显示当前时间
    hwclock                                 # 硬件始终的查看
        hwclock -w                          # 以系统时间为基准,修改硬件时间
        hwclock -s                          # 以硬件时间为基准,修改系统时间
    cal                                     # 查看日志的意思
        -1, --one                           # 只显示当前月份(默认)
        -3, --three                         # 显示上个月、当月和下个月
        -s, --sunday                        # 周日作为一周第一天
        -m, --monday                        # 周一用为一周第一天
        -j, --julian                        # 输出儒略日
        -y, --year                          # 输出整年
        -V, --version                       # 显示版本信息并退出
        -h, --help                          # 显示此帮助并退出
    ntpdate -u ntp.aliyun.com               # 由于我们只需要用作客户端更新时间
    reboot                                  # 用于重启机器
    poweroff                                # 用于关闭系统
    chattr +a test.py                       # 给文件加锁,只能写入数据,无法删除文件
    chattr -a test.py                       # 给文件去锁,可完全控制数据
    lsattr test.py                          # 查看文件隐藏属性
  2. Linux系统命令操作语法格式,一般情况下参数和文件路径都是可选的。Linux命令,参数之间,普遍应该用一个或多个空格分割!

TOP命令

  1. TOP命令用于动态地监视进程活动与系统负载等信息

    # 第一行 (uptime):系统时间 主机运行时间 用户连接数(who) 系统1,5,15分钟的平均负载
    # 第二行:进程信息:进程总数 正在运行的进程数 睡眠的进程数 停止的进程数 僵尸进程数
    # 第三行:cpu信息
        1.5 us                              # 用户空间所占CPU百分比
        0.9 sy                              # 内核空间占用CPU百分比
        0.0 ni                              # 用户进程空间内改变过优先级的进程占用CPU百分比
        97.5 id                             # 空闲CPU百分比
        0.2 wa                              # 等待输入输出的CPU时间百分比
        0.0 hi                              # 硬件CPU中断占用百分比
        0.0 si                              # 软中断占用百分比
        0.0 st                              # 虚拟机占用百分比
    # 第四行:内存信息(与第五行的信息类似与free命令)
        8053444 total                       # 物理内存总量
        7779224 used                        # 已使用的内存总量
        274220 free                         # 空闲的内存总量(free+used=total)
        359212 buffers                      # 用作内核缓存的内存量
    # 第五行:swap信息
        8265724 total                       # 交换分区总量
        33840 used                          # 已使用的交换分区总量
        8231884 free                        # 空闲交换区总量
        4358088 cached Mem                  # 缓冲的交换区总量,内存中的内容被换出到交换区,然后又被换入到内存,但是使用过的交换区没有被覆盖,交换区的这些内容已存在于内存中的交换区的大小,相应的内存再次被换出时可不必再对交换区写入。

报错分析

  1. 我们常常会输入错一些命令导致报错,这里我们总结一下创建的报错。

    command not found                   # 未(not)找到(found)命令(command)
    No such file or directory           # 没有(No)这样的(such)文件(file)或(or)目录(directory)
  2. Linux的帮助是在命令后面加上ls --help,想看更详细的可以在命令前加上man ls

编辑器

  1. 使用一个好的编辑器可以让工作事半功倍。

vim编辑器

  1. 所有的 Unix Like 系统都会内建 vi 文书编辑器,其他的文书编辑器则不一定会存在。

  2. 但是目前我们使用比较多的是 vim 编辑器。

  3. vim 具有程序编辑的能力,可以主动的以字体颜色辨别语法的正确性,方便程序设计。

  4. 基本上 vi/vim 共分为三种模式,分别是命令模式(Command mode)输入模式(Insert mode)底线命令模式(Last line mode)

  5. 命令模式

    w(e)                                    # 移动光标到下一个单词
    b                                       # 移动到光标上一个单词
    0                                       # 移动到本行开头
    $                                       # 移动光标到本行结尾
    H                                       # 移动光标到屏幕首行
    M                                       # 移动到光标到屏幕的中间一行
    L                                       # 移动光标到屏幕的尾行
    gg                                      # 移动光标到文档的首行
    G                                       # 移动光标到文档尾行
    ctrl + f                                # 下一页
    ctrl + b                                # 上一页
    `.                                      # 移动光标到上一次的修改行
    # 查找
    /chaoge                                 # 在整篇文档中搜索chaoge字符串,向下查找
    ?chaoge                                 # 在整篇文档中搜索chaoge字符串,向上查找
    *                                       # 查找整个文档,匹配光标所在的所有单词,按下n查找下一处,N上一处
    #                                       # 查找整个文档,匹配光标所在的所有单词,按下n查找下一处,N上一处
    gd                                      # 找到光标所在单词匹配的单词,并停留在非注释的第一个匹配上%找到括号的另一半!!
    # 复制,删除,粘贴
    yy                                      # 拷贝光标所在行
    dd                                      # 删除光标所在行
    D                                       # 删除当前光标到行尾的内容
    dG                                      # 删除当前行到文档尾部的内容
    p                                       # 粘贴yy所复制的内容x 删除光标所在的字符u 撤销上一步的操作
    # 数字与命令
    3yy                                     # 拷贝光标所在的3行
    5dd                                     # 删除光标所在5行
  6. 默认是命令模式,需要输入i进入编辑模式,然后输入文本。

  7. 按下esc键,回到命令模式并输入:到底线模式。

    :q!                                     # 强制退出
    :wq!                                    # 强制写入退出:set nu 显示行号:数字  调到数字那行随时按下esc可以退出底线命令模式
    :! command                              # 暂时离开vim指令模式,执行command的结果
  8. vim按键

    移动光标的方法
    h 或 向左箭头键(←)    光标向左移动一个字符
    j 或 向下箭头键(↓)    光标向下移动一个字符
    k 或 向上箭头键(↑)    光标向上移动一个字符
    l 或 向右箭头键(→)    光标向右移动一个字符
    向下移动5行      5j
    向右移动10字符    10l
    n(space)    按下数字n,例如10,然后按下空格,光标会向右移动10个字符

SED编辑器

  1. SED是一种流编辑器,它是文本处理中非常重要的工具,能够完美的配合正则表达式使用,功能不同凡响。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用SED命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。

  2. 接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。SED主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

    sed [options] 'command' file(s)
    sed [options] -f scriptfile file(s)
    # sed [options]
        -e  <script>    --expression=<script>       # 以选项中的指定的script来处理输入的文本文件;
        -f  <script "file"> --file=<script"file">   # 以选项中指定的script文件来处理输入的文本文件;
        -h  --help                                  # 显示帮助;
        -n  --quiet ——silent                        # 仅显示script处理后的结果;
        -V  --version                               # 显示版本信息。
        -i                                          # 插入, i的后面可以接字串
    # sed "command"
        a\                                          # 在当前行下面插入文本。
        i\                                          # 在当前行上面插入文本。
        c\                                          # 把选定的行改为新的文本。
        d                                           # 删除,删除选择的行。
        D                                           # 删除模板块的第一行。
        s                                           # 替换指定字符
        h                                           # 拷贝模板块的内容到内存中的缓冲区。
        H                                           # 追加模板块的内容到内存中的缓冲区。
        g                                           # 获得内存缓冲区的内容,并替代当前模板块中的文本。
        G                                           # 获得内存缓冲区的内容,并追加到当前模板块文本的后面。
        l                                           # 列表不能打印字符的清单。
        n                                           # 读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。
        N                                           # 追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。
        p                                           # 打印模板块的行。
        P                                           #(大写) 打印模板块的第一行。
        q                                           # 退出Sed。
        b                                           # lable 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。
        r                                           # file 从file中读行。
        t                                           # label if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
        T                                           # label 错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
        w                                           # file 写并追加模板块到file末尾。  
        W                                           # file 写并追加模板块的第一行到file末尾。  
        !                                           # 表示后面的命令对所有没有被选定的行发生作用。  
        =                                           # 打印当前行号码。  
    # 把注释扩展到下一个换行符以前。  
    # sed 替换标记
        g                                           # 表示行内全面替换。  
        p                                           # 表示打印行。  
        w                                           # 表示把行写入一个文件。  
        x                                           # 表示互换模板块中的文本和缓冲区中的文本。  
        y                                           # 表示把一个字符翻译为另外的字符(但是不用于正则表达式)
        \1                                          # 子串匹配标记
        &                                           # 已匹配字符串标记
    # sed 元字符集
        ^                                           # 匹配行开始,如:/^sed/匹配所有以sed开头的行。
        $                                           # 匹配行结束,如:/sed$/匹配所有以sed结尾的行。
        .                                           # 匹配一个非换行符的任意字符,如:/s.d/匹配s后接一个任意字符,最后是d。
        *                                           # 匹配0个或多个字符,如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行。
        []                                          # 匹配一个指定范围内的字符,如/[ss]ed/匹配sed和Sed。  
        [^]                                         # 匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。
        \(..\)                                      # 匹配子串,保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。
        &                                           # 保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。
        \<                                          # 匹配单词的开始,如:/\<love/匹配包含以love开头的单词的行。
        \>                                          # 匹配单词的结束,如/love\>/匹配包含以love结尾的单词的行。
        x\{m\}                                      # 重复字符x,m次,如:/0\{5\}/匹配包含5个0的行。
        x\{m,\}                                     # 重复字符x,至少m次,如:/0\{5,\}/匹配至少有5个0的行。
        x\{m,n\}                                    # 重复字符x,至少m次,不多于n次,如:/0\{5,10\}/匹配5~10个0的行。

用户管理&权限

  1. 现代操作系统一般属于多用户的操作系统,普通用户相互之间不受影响。但是权限是有限制且用户太多的话,管理就不便。

  2. 所以系统会有一个超级用户来管理普通用户,并所在的组称为root组。“组”是具有相似权限的多个用户的集合。

  3. 这个root管理员就是所有UNIX系统中的超级用户,它拥有最高的系统所有权,能够管理系统的各项功能。因此“能力越大,责任越大”,root权限必须很好的掌握,否则一个错误的命令可能会摧毁整个系统。

  4. 在系统中有一个UID来区分用户0代表系统管理员、1~99是系统用户(Linux安装的服务程序都会创建独有的用户负责运行)、1000开始是普通用户。

  5. 不管任何系统中都会组这个概念,Linux 系统中还引入了用户组的概念。通过使用用户组号码(GID,Group IDentification),我们可以把多个用户加入到同一个组中,从而方 便为组中的用户统一规划权限或指定任务。

  6. 对用户与组的基本操作

    id root                                             # 查看自己的UID、GID、GROUP
    useradd oldboy                                      # 添加用户       
    passwd redhat                                       # 设置密码,root用户可以修改其他所有人的密码,且不需要验证
    echo "redhat"|passwd --stdin oldboy && history -c   # 非交互式设置密码
    userdel -r pyyu                                     # 删除pyyu用户及家目录
        -f                                              # 强制删除用户
        -r                                              # 删除用户以及家目录
    su - "username"                                     # su命令可以切换用户身份的需求,su命令中间的-号很重要,意味着完全切换到新的用户,即环境变量
    # group命令用于创建用户组,为了更加高效的指派系统中各个用户的权限,在工作中常常添加几个用户到一个组里面,这样可以针对一类用户安排权限。
    groupadd it_dep                                     # 将用户加入到it_dep组中
  7. sudo命令用来以其他身份来执行命令,预设的身份为root。在/etc/sudoers中设置了可执行sudo指令的用户。若其未经授权的用户使用sudo,则会发出邮件给管理员。用户使用sudo时,必须先输入密码,之后有5分钟的有效期限,超过期限则必须重新输入密码。

    visudo /etc/sudoers                                 # 用visudo编辑sudoers表可以查错,只有root可以修改。
        root    ALL=(ALL)       ALL                     # Allow root to run any commands anywhere
        chaoge  ALL=(ALL)       ALL                     # 允许chaoge在任何地方,执行任何命令
    sudo ls /root/                                      # 普通用户查看root用户的家目录
        -b                                              # 在后台执行指令;
        -h                                              # 显示帮助;
        -H                                              # 将HOME环境变量设为新身份的HOME环境变量;
        -k                                              # 结束密码的有效期限,也就是下次再执行sudo时便需要输入密码;。
        -l                                              # 列出目前用户可执行与无法执行的指令;
        -p                                              # 改变询问密码的提示符号;
        -s<shell>                                       # 执行指定的shell;
        -u<user>                                        # 以指定的用户作为新的身份。若不加上此参数,则预设以root作为新的身份;
        -v                                              # 延长密码有效期限5分钟;
        -V                                              # 显示版本信息。

权限

  1. Linux权限的目的是保护账户的资料,Linux权限主要依据三种身份来决定、文件属于哪个用户、文件属于哪个组、其他人。

  2. 权限就是对文件的增删改查的操作,有权限的就可以操作,没权限的就不可以操作。

  3. 查看权限ls -l /var/log/mysqld.log、以空格划分分别为:权限、文件连接数、属主、属组、文件大小、修改日期时间、文件名。权限有10个杠第一个代表文件类型、2到4是当前用户权限、5到7是组权限、8到10是其他用户权限。

    # 类型
        -                                               # 一般文件
        d                                               # 文件夹
        l                                               # 软连接(快捷方式)
        b                                               # 块设备,存储媒体文件为主
        c                                               # 代表键盘,鼠标等设备
    # 权限
        r                                               # 数字为4 read可读,可以用cat等命令查看
        w                                               # 数字为2 write写入,可以编辑或者删除这个文件
        x                                               # 数字为1 executable,可以执行
  4. 修改文件权限属性

    chmod [u|g|o|a][=|-|+][r|w|x] [file]                # 修改权限,1.中是身份、2.是操作、3.是文件权限(|代表或,之选其中之一、[]只做区分)
    chmod [0~7|0~7|0~7] [file]                          # 修改权限(|代表或,之选其中之一、[]只做区分)
    chown root pyyu.txt                                 # 修改属主为root
    ll pyyu.txt                                         # 查看信息
    chgrp root pyyu.txt                                 # 修改属组

设置PS1

  1. 软连接软连接也叫做符号链接,类似于windows的快捷方式,创建软链接ln -s "file" "name"

  2. PS1变量是Linux命令提示符由PS1环境变量控制

    echo $PS1                                           # 查看ps1变量[\u@\h \W]\$
        # 可以自行调整全局变量/etc/profile文件用于永久生效 PS1='[\u@\h \W\t]\$'
        \d                                              # 日期
        \H                                              # 完整主机名
        \h                                              # 主机名第一个名字
        \t                                              # 时间24小时制HHMMSS
        \T                                              # 时间12小时制
        \A                                              # 时间24小时制HHMM
        \u                                              # 当前用户账号名
        \v                                              # BASH的版本
        \w                                              # 完整工作目录
        \W                                              # 利用basename取得工作目录名
        \#                                              # 下达的第几个命令
        \$                                              # 提示字符,root为#,普通用户为$
    # PS1显示ip地址
    export PS1="[\u@\h `/sbin/ifconfig ens33 | sed -nr 's/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'` \w]\$"

解压命令

  1. 人们发明了各种各样的包,无论是双肩包,或者是装在口袋,都是为了让“文件”更方便携带。linux的文件打包工具最出名的是tar。

tar

  1. tar 命令用来压缩和解压文件。tar本身不具有压缩功能。他是调用压缩功能实现的。

    tar -cf all_pic.tar *.jpg                           # 压缩当前目录所有jpg结尾的文件
    tar -xjf xx.tar.bz2                                 # 解压缩bz2结尾的文件
        -A  --catenate                                  # 新增文件到以存在的备份文件;
        -B                                              # 设置区块大小;
        -c  --create                                    # 建立新的备份文件;
        -C <"directory">                                # 这个选项用在解压缩,若要在特定目录解压缩,可以使用这个选项。
        -d                                              # 记录文件的差别;
        -x  --extract   --get                           # 从备份文件中还原文件;
        -t  --list                                      # 列出备份文件的内容;
        -z  --gzip  --ungzip                            # 通过gzip指令处理备份文件;
        -Z  --compress  --uncompress                    # 通过compress指令处理备份文件;
        -f<"backups file">  --file=<"backups file">     # 指定备份文件;
        -v  --verbose                                   # 显示指令执行过程;
        -r                                              # 添加文件到已经压缩的文件;
        -u                                              # 添加改变了和现有的文件到已经存在的压缩文件;
        -j                                              # 支持bzip2解压文件;
        -v                                              # 显示操作过程;
        -l                                              # 文件系统边界设置;
        -k                                              # 保留原有文件不覆盖;
        -m                                              # 保留文件不被覆盖;
        -w                                              # 确认压缩文件的正确性;
        -p  --same-permissions                          # 用原来的文件权限还原文件;
        -P  --absolute-names                            # 文件名使用绝对名称,不移除文件名称前的“/”号;
        -N <"datetype"> --newer=<"datetime">            # 只将较指定日期更新的文件保存到备份文件里;
        --exclude=<"style">                             # 排除符合范本样式的文件。

gzip

  1. gzip用来压缩文件,是个使用广泛的压缩程序,被压缩的以".gz"扩展名,gzip可以压缩较大的文件,以60%~70%压缩率来节省磁盘空间。

    gzip *                                              # 压缩当前目录所有文件为.gz文件
    gzip -dv *                                          # 把上例中每个压缩的文件解压,并列出详细的信息
        -d  --decompress    ----uncompress              # 解开压缩文件;
        -f  ——force                                     # 强行压缩文件。
        -h  ——help                                      # 在线帮助;
        -l  ——list                                      # 列出压缩文件的相关信息;
        -L  ——license                                   # 显示版本与版权信息;
        -r  ——recursive                                 # 递归处理,将指定目录下的所有文件及子目录一并处理;
        -v  ——verbose                                   # 显示指令执行过程;

网络基本认识

  1. 如果电脑上找不到ifconfig哪应该是你在安装Linux时并没有安装上,如果向往下学就是用yum install net-tools -y它去下载即可。

  2. Linux的网络功能相当强悍,一时之间我们无法了解所有的网络命令,在配置服务器基础环境时,先了解下网络参数设定命令。

    ifup eth33                                          # 脚本命令,更简单的方式启动网络
    ifdown eth33                                        # 脚本命令,更简单的方式关闭网络
    ip                                                  # 符合指令,直接修改上述功能,这个ip命令是结合了ifconfig和route两个命令的功能。
        ip addr show                                    # 查看ip信息
    cat /etc/redhat-release                             # 查看系统版本信息
    uname -r                                            # 查看内核版本号
    uname -m                                            # 查看系统多少位
    uname -a                                            # 查看内核所有信息
  3. 网卡配置文件详解

    /etc/sysconfig/network                              # 网络配置文件
    /etc/sysconfig/network-scripts/ifcfg-INTERFACE_NAME # 网络接口配置文件
        DEVICE=                                         # 关联的设备名称,要与文件名的后半部“INTERFACE_NAME”保持一致; 
        BOOTPROTO={static|none|dhcp|bootp}              # 引导协议;要使用静态地址,使用static或none;dhcp表示使用DHCP服务器获取地址;
        IPADDR=                                         # IP地址
        NETMASK=                                        # 子网掩码
        GATEWAY=                                        # 设定默认网关;
        ONBOOT=                                         # 开机时是否自动激活此网络接口;
        HWADDR=                                         # 硬件地址,要与硬件中的地址保持一致;可省;
        USERCTL={yes|no}                                # 是否允许普通用户控制此接口;
        PEERDNS={yes|no}                                # 是否在BOOTPROTO为dhcp时接受由DHCP服务器指定的DNS地址;
  4. ifconfig是网络中必须要用到的,不然你是无法查看ip的除IP addr

    ifconfig                                            # 查询、设置网卡和ip等参数,其中inet代表ip地址、netmask代表子网掩码、broadcast代表广播地址
    ifconfig eth0                                       # 单独显示eth0的信息
        eth0                                            # 网卡的代号 
        lo                                              # 回环地址loopback
        inet                                            # IPv4的Ip地址
        netmask                                         # 子网掩码
        broadcast                                       # 广播地址
        RX/TX                                           # 流量发/收情况 tx是发送(transport),rx是接收(receive)
        packets                                         # 数据包数
        errors                                          # 数据包错误数
        dropped                                         # 数据包有问题被丢弃的数量
        collisions                                      # 数据包碰撞情况,数值太多代表网络状况差
  5. netstat命令用来打印Linux中网络系统的状态信息,可让你得知整个Linux系统的网络情况。

    netstat -tunlp                                      # 查看网络信息
        -t  --tcp                                       # 显示TCP传输协议的连线状况;
        -u  --udp                                       # 显示UDP传输协议的连线状况;
        -n  --numeric                                   # 直接使用ip地址,而不通过域名服务器;
        -l  --listening                                 # 显示监控中的服务器的Socket;
        -p  --programs                                  # 显示正在使用Socket的程序识别码和程序名称;-a或--all:显示所有连线中的Socket;
  6. ps 命令用于查看系统中的进程状态。

    ps                                                  # 查看系统中的进程状态
        -a                                              # 显示所有进程
        -u                                              # 用户以及其他详细信息
        -x                                              # 显示没有控制终端的进程
  7. kill命令用来删除执行中的程序或工作。kill可将指定的信息送至程序。

    ps -ef | grep vim                                   # ps查找进程
    kill 3268                                           # 用kill杀掉
        -a                                              # 当处理当前进程时,不限制命令名和进程号的对应关系;
        -l <"infonum">                                  # 若不加<信息编号>选项,则-l参数会列出全部的信息名称;
        -p                                              # 指定kill 命令只打印相关进程的进程号,而不发送任何信号;
        -s <"infoname or infonum">                      # 指定要送出的信息;
        -u                                              # 指定用户。
    # 只有第9种信号(SIGKILL)才可以无条件终止进程,其他信号进程都有权利忽略,**下面是常用的信号:**
        HUP     1                                       # 终端断线
        INT     2                                       # 中断(同 Ctrl + C)
        QUIT    3                                       # 退出(同 Ctrl + \)
        TERM   15                                       # 终止
        KILL    9                                       # 强制终止
        CONT   18                                       # 继续(与STOP相反, fg/bg命令)
        STOP   19                                       # 暂停(同 Ctrl + Z)
    # 通常来讲,复杂软件的程序会有多个进程提供服务,如果逐个去结束这些进程会比较麻烦,此时可以使用 killall 命令来批量结束某个服务程序带有的全部进程。
    killall nginx     

防火墙

SELinux功能

  1. SELinux(Security-Enhanced Linux) 是美国国家安全局(NSA)对于强制访问控制的实现,这个功能管理员又爱又恨,大多数生产环境也是关闭的做法,安全手段使用其他方法。

  2. 永久关闭方式

    # 1.修改配置文件,永久生效关闭selinux
    cp /etc/selinux/config /etc/selinux/config.bak      # 修改前备份
    # 2.用sed替换
    sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
    # 3.检查状态
    grep "SELINUX=disabled" /etc/selinux/config
  3. 临时关闭selinux(命令行修改,重启失效)

    getenforce                                          # 获取selinux状态
    # 修改selinux状态
    setenforce 
    usage:  setenforce [ Enforcing | Permissive | 1 | 0 ]
    # 数字0 表示permissive,给出警告,不会阻止,等同disabled
    # 数字1表示enforcing,表示开启

iptables防火墙

  1. 在学习阶段,关闭防火墙可以更方便的学习,在企业环境中,一般只有配置外网ip的linux服务器才会开启防火墙,但是对于高并发流量的业务服务器仍然是不能开启的,会有很大性能损失,因此需要更nb的硬件防火墙。

  2. 关闭防火墙具体操作如下

    # centos7默认已经使用firewall作为防火墙了
    # 1.关闭防火墙
    systemctl status firewalld                          # 查看防火墙状态
    systemctl stop firewalld                            # 关闭防火墙
    systemctl disable firewalld                         # 关闭防火墙开机启动systemctl is-enabled firewalld.service
    #检查防火墙是否启动

其他认识

  1. 其他一些配置的操作

    # df命令用于显示磁盘分区上的可使用的磁盘空间。默认显示单位为KB。
    df                                                  # 查看系统磁盘设备,默认是KB为单位:
        -h  --human-readable                            # 以可读性较高的方式来显示信息;
        -k  --kilobytes                                 # 指定区块大小为1024字节;
        -T  --print-type                                # 显示文件系统的类型;
        --help                                          # 显示帮助;
        --version                                       # 显示版本信息。
    tree                                                # 命令以树状图列出目录的内容。
        -a                                              # 显示所有文件和目录;
        -A                                              # 使用ASNI绘图字符显示树状图而非以ASCII字符组合;
        -C                                              # 在文件和目录清单加上色彩,便于区分各种类型;
        -d                                              # 先是目录名称而非内容;
        -D                                              # 列出文件或目录的更改时间;
        -f                                              # 在每个文件或目录之前,显示完整的相对路径名称;
        -F                                              # 在执行文件,目录,Socket,符号连接,管道名称名称,各自加上"*","/","@","|"号;
        -g                                              # 列出文件或目录的所属群组名称,没有对应的名称时,则显示群组识别码;
        -i                                              # 不以阶梯状列出文件和目录名称;
        -l                                              # <范本样式> 不显示符号范本样式的文件或目录名称;
        -l                                              # 如遇到性质为符号连接的目录,直接列出该连接所指向的原始目录;
        -n                                              # 不在文件和目录清单加上色彩;
        -N                                              # 直接列出文件和目录名称,包括控制字符;
        -p                                              # 列出权限标示;
        -P                                              # <范本样式> 只显示符合范本样式的文件和目录名称;
        -q                                              # 用“?”号取代控制字符,列出文件和目录名称;
        -s                                              # 列出文件和目录大小;
        -t                                              # 用文件和目录的更改时间排序;
        -u                                              # 列出文件或目录的拥有者名称,没有对应的名称时,则显示用户识别码;
        -x                                              # 将范围局限在现行的文件系统中,若指定目录下的某些子目录,其存放于另一个文件系统上,则将该目录予以排除在寻找范围外。
    hostnamectl set-hostname "pyyuc"                    # 设置主机名

Linux中文显示设置

  1. 此项优化为可选项,根据个人情况选择是否调整Linux系统的字符集,字符集就是一套文字符号以及编码。

  2. Linux下常用字符集有:GBK实际企业应用较少、UTF-8广泛支持,MYSQL也使用UTF-8,企业广泛使用。

    echo $LANG                                              # 查看系统当前字符集
    #检查xshell crt的字符集
    # vim /etc/profile.d/locale.sh
        export LC_CTYPE=zh_CN.UTF-8                         # 命令修改字符集
        export LC_ALL=zh_CN.UTF-8
    # vim /etc/locale.conf
        LANG=zh_CN.UTF-8
    # vim /etc/sysconfig/i18n
        LANG=zh_CN.UTF-8
    # vim /etc/environment
        LANG=zh_CN.UTF-8
        LC_ALL=zh_CN.UTF-8
  3. 英文版本

    # vim /etc/profile.d/locale.sh
        export LC_CTYPE=en_US.UTF-8
        export LC_ALL=en_US.UTF-8
    
    # vim /etc/locale.conf
        LANG=en_US.UTF-8
    
    # vim /etc/sysconfig/i18n
        LANG=en_US.UTF-8
    
    # vim /etc/environment
        LANG=en_US.UTF-8
        LC_ALL=en_US.UTF-8
  4. 乱码核心解决办法,:系统字符集utf8,xshell字符集utf8,文件字符集一致zh_CN.UTF-8。

DNS

  1. DNS(Domain Name System,域名系统),万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。

  2. 通过域名,最终得到该域名对应的IP地址的过程叫做域名解析(或主机名解析)。

  3. 查看Linux的dns,唯一配置文件cat /etc/resolv.conf,本地强制dns解析文件vi /etc/hosts,前面是ip后面是域名。

nslookup

  1. nslookup命令是常用域名查询工具,就是查DNS信息用的命令。

  2. nslookup4有两种工作模式,即“交互模式”和“非交互模式”。在“交互模式”下,用户可以向域名服务器查询各类主机、域名的信息,或者输出域名中的主机列表。而在“非交互模式”下,用户可以针对一个主机或域名仅仅获取特定的名称或所需信息。

  3. 进入交互模式,直接输入nslookup命令,不加任何参数,则直接进入交互模式,此时nslookup会连接到默认的域名服务器(即/etc/resolv.conf的第一个dns地址)。或者输入nslookup -nameserver/ip。进入非交互模式,就直接输入nslookup 域名就可以了。

  4. 解析nslookup www.oldboyedu.com

crond

  1. 有些事情是要定时完成的,我们就要用到,crond服务相关的软件包rpm -qa |grep cron,crontab命令被用来提交和管理用户的需要周期性执行的任务。

  2. 这些包在最小化安装系统时就已经安装了,并且会开机自启动crond服务,并为我们提供好编写计划任务的crontab命令。

    cat /etc/crontab									# 在/etc目录下有一个crontab文件,这个就是系统任务调度的配置文件
    crontab -e
    	*/3 * * * * /usr/sbin/ntpdate ntp1.aliyun.com  	# 每隔三分钟执行下时间同步
        -e												# 编辑该用户的计时器设置;
        -l												# 列出该用户的计时器设置;
        -r												# 删除该用户的计时器设置;
        -u<"username">									# 指定要设定计时器的用户名称。存放定时任务的文件/var/spool/cron
    *****command										# 代表,分钟(0-59)、小时(0-23)、日期(1-31)、月份(1-12)、星期(0-6,0代表星期天)、命令
    	*												# 代表所有可能的值
    	,												# 可以用逗号隔开的值指定一个列表范围,例如,“1,2,5,7,8,9”
    	-												# 可以用整数之间的中杠表示一个整数范围,例如“2-6”表示“2,3,4,5,6”
    	/												# 可以用正斜线指定时间的间隔频率,例如“0-23/2”表示每两小时执行一次。
  3. 注意:

    1. 查看计划任务的执行:tail -f /var/log/cron

    2. 写计划任务时,命令必须加上绝对路径,否则会出现这种情况:从日志中看,确实触发了计划任务的执行,但是命令却没有执行成功,比如* * * * * reboot就会出现这种情况,需要将reboot写成/usr/sbin/reboot

    3. 计划任务执行的命令 是否存在,软件是否安装

    4. 确保crontab服务运行 :systemctl status cron&ps -ef|grep crond

    5. 检测crontab是否开机启动:systemctl is-enabled crond

    6. crontab配置文件

系统服务管理命令

  1. 如果大家之前学习或者使用过RHEL6系统,应该已经习惯了service、chkconfig等命令来管理系统服务,但是在RHEL7系统中改变了systemctl来管理系统服务。

    # System V init(RHEL6)
    	service foo start										# 启动服务
        service foo restart										# 重启服务
        service foo stop										# 停止服务
        service foo reload										# 重新加载配置文件(不终止服务)
        service foo status										# 查看服务状态
        chkconfig foo on										# 开机自动启动
        chkconfig foo off										# 开机不自动启动
        chkconfig foo											# 查看特定服务是否为启动
    # System V init(RHEL7)
    	systemctl start foo.service								# 启动服务
        systemctl restart foo.service							# 重启服务
        systemctl stop foo.service								# 停止服务
        systemctl reload foo.service							# 重新加载配置文件(不终止服务)
        systemctl status foo.service							# 查看服务状态
        systemctl enable foo.service							# 开机自动启动
        systemctl disable foo.service							# 开机不自动启动
        systemctl is-enabled foo.service						# 查看特定服务是否为启动

/etc下的目录知识

  1. /etc:这个目录用来存放所有的系统管理所需要的配置文件和子目录。

    /etc/sysconfig/network-script/ifcfg-eth0					# 网卡配置文件
    /etc/sysconfig/network										# 修改机器名以及网卡,网管等配置
    /etc/resolv.conf											# linux的dns客户端配置文件,实现域名和ip的互相解析
    /etc/hosts/													# 本地dns解析文件,设定ip和域名的对应解析,开发测试最常用的临时域名解析
    /etc/profile												# 系统全局环境变量永久生效的配置文件,如PATH等
    ~/.bash_profile												# 用户的环境变量
    ~/.bashrc													# 用户的环境变量
    /usr/sbin													# 存放可执行程序的目录,大多是系统管理命令
    /usr/local													# 存放用户自编译安装软件的目录  > 等同于C:\Program files (windows)
    /proc/cpuinfo												# 关于处理器的信息,还可以top指令查看
    /proc/meminfo 												# 查看内存信息,还可以free -m

软件包管理

  1. 软件包顾名思义就是将应用程序、配置文件和数据打包的产物,所有的linux发行版都采用了某种形式的软件包系统,这使得linux软件管理和在windows下一样方便,suse、red hat、fedora等发行版都是用rpm包,Debian和Ubuntu则使用.deb格式的软件包。

RPM

  1. 软件包管理器核心功能,制作软件包.rpm,安装、卸载、升级、查询、校验。

  2. 在 RPM(红帽软件包管理器)公布之前,要想在 Linux 系统中安装软件只能采取源码包 的方式安装。早期在 Linux 系统中安装程序是一件非常困难、耗费耐心的事情。

  3. RPM 机制则为解决这些问题而设计的。RPM 有点像 Windows 系统中的控制面板,会建 立统一的数据库文件,详细记录软件信息并能够自动分析依赖关系。

  4. 相关操作

    wget https://xx.net/xx.rpm                          # 下载软件包
    rpm -i filename.rpm
        i                                               # 表示安装   
        v                                               # 显示详细过程  
        h                                               # 以进度条显示
    rpm -ivh filename.rpm                               # 安装软件的命令格式   
    rpm -Uvh filename.rpm                               # 升级软件的命令格式
    rpm -e filename.rpm                                 # 卸载软件的命令格式,需要手动解决依赖,不如 yum remove
    rpm -qpi filename.rpm                               # 查询软件描述信息的命令格式
    rpm -qpl filename.rpm                               # 列出软件文件信息的命令格式
    rpm -qf filename                                    # 查询文件属于哪个 RPM 的命令格式

yum

  1. yum命令是在Fedora和RedHat以及SUSE中基于rpm的软件包管理器,它可以使系统管理人员交互和自动化地更细与管理RPM软件包,能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软体包,无须繁琐地一次次下载、安装。

  2. 尽管 RPM 能够帮助用户查询软件相关的依赖关系,但问题还是要运维人员自己来解决, 而有些大型软件可能与数十个程序都有依赖关系,在这种情况下安装软件会是非常痛苦的。 Yum 软件仓库便是为了进一步降低软件安装难度和复杂度而设计的技术。Yum 软件仓库可以 根据用户的要求分析出所需软件包及其相关的依赖关系,然后自动从服务器下载软件包并安 装到系统。

  3. Yum 软件仓库中的 RPM 软件包可以是由红帽官方发布的,也可以是第三方发布的,当然也可以是自己编写的。

  4. yum提供了查找、安装、删除某一个、一组甚至全部软件包的命令,而且命令简洁而又好记。

    yum install yum-fastestmirror                           # 自动搜索最快镜像插件
        -h                                                  # 显示帮助信息;
        -y                                                  # 对所有的提问都回答“yes”;
        -c                                                  # 指定配置文件;
        -q                                                  # 安静模式;
        -v                                                  # 详细模式;
        -d                                                  # 设置调试等级(0-10);
        -e                                                  # 设置错误等级(0-10);
        -R                                                  # 设置yum处理一个命令的最大等待时间;
        -C                                                  # 完全从缓存中运行,而不去下载或者更新任何头文件。
  5. yum源配置,说到yum源就必须说到linux系统中特有的依赖关系问题,yum就是为了解决依赖关系而存在的。yum源就相当是一个目录项,当我们使用yum机制安装软件时,若需要安装依赖软件,则yum机制就会根据在yum源中定义好的路径查找依赖软件,并将依赖软件安装好。

  6. YUM的基本工作机制如下:

    1. 服务器端:在服务器上面存放了所有的RPM软件包,然后以相关的功能去分析每个RPM文件的依赖性关系,将这些数据记录成文件存放在服务器的某特定目录内。

    2. 客户端:如果需要安装某个软件时,先下载服务器上面记录的依赖性关系文件(可通过WWW或FTP方式),通过对服务器端下载的纪录数据进行分析,然后取得所有相关的软件,一次全部下载下来进行安装。

  7. yum源的目录ll /etc/yum.repos.d/,查看yum源文件,以repo结尾的都是yum源配置文件,BASE.repo是主文件。

  8. 配置阿里云yum源

    mkdir /repo_bak                                             # 创建备份文件夹
    cp *.repo /repo_bak/                                        # 将yum源备份到创建的文件下
    wget http://mirrors.aliyun.com/repo/Centos-7.repo           # 下载阿里云repo文件
    yum clean allyum makecache                                  # 清空yum缓存并且生成新的yum缓存
    yum install -y epel-release                                 # 安装软件扩展源
  9. yum的操作

    yum repolist all                                            # 列出所有仓库
    yum list all                                                # 列出仓库所有软件包
    yum info "appname"                                          # 查看软件包信息
    yum install "appname"                                       # 安装软件包
    yum reinstall "appname"                                     # 重新安装软件包
    yum update "appname"                                        # 升级软件包
    yum remove "appname"                                        # 移除软件包
    yum clean all                                               # 清楚所有仓库缓存
    yum check-update                                            # 检查可以更新的软件包
    yum grouplist                                               # 查看系统中已安装的软件包
    yum groupinstall "appgroup"                                 # 安装软件包组

中级阶段

python3部署

  1. 安装python前的库环境,非常重要

    yum install gcc patch libffi-devel python-devel  zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel -y
  2. 下载,解压安装源码包

    # 用它下载会慢也可以使用下面的一种
        wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz
    # 在win系统上用迅雷到https://www.python.org/downloads/release/python-362/地址下载后,在Linux上安装
        yum install lrzsz
        rz -y
    xz -d Python-3.6.7.tar.xz                               # 解压xz
    tar -xf Python-3.6.7.tar                                # 解压tar
  3. 这一步一般用来生成 Makefile,为下一步的编译做准备,你可以通过在 configure 后加上参数来对安装进行控制。

    cd /opt/Python-3.4.7                                    # 进入的是解压后的文件夹
    ./configure --prefix=/opt/python                        # 这后面的是要将解释器存储的位置
  4. 然后这两句可以一局就执行成功 make && make install 编译

  5. 设置快捷方式或加入环境变量

    # 配置软连接,快捷启动python3和pip3
        ln -s /opt/python347/bin/python3    /usr/bin/python3
        ln -s /opt/python347/bin/pip3  /usr/bin/pip3
    # 配置系统环境变量,配置PATH,加入python3的目录
        PATH=$PATH:/opt/python347/bin/
        /etc/profile # 这个文件开机后自动加载,可以实现永久设置。

虚拟环境

  1. 在使用 Python 开发的过程中,工程一多,难免会碰到不同的工程依赖不同版本的库的问题;

  2. 我们需要对于不同的工程使用不同的虚拟环境来保持开发环境以及宿主环境的清洁。

  3. virtualenv 可以在系统中建立多个不同并且相互不干扰的虚拟环境。

    # 指定清华源下载pip的包
    pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple virtualenv
    # 升级pip工具
    pip3 install --upgrade pip
  4. virtualenv的使用方式。

    ​
    pip3 install virtualenv                                 # 安装virtualenv
    mkdir Myproject|cd Myproject                            # 创建存放虚拟解释器的目录
    virtualenv --no-site-packages --python=python3  venv    # 创建独立运行环境-命名,得到独立第三方包的环境,并且指定解释器是python3
    source venv/bin/activate                                # 进入虚拟环境,此时进入虚拟环境(venv)Myproject
    (venv)Myproject: pip3 install django==1.9.8             # 安装第三方包
    # 此时pip的包都会安装到venv环境下,venv是针对Myproject创建的
    deactivate                                              # 退出venv环境
    # virtualenv原理很简单,就是把系统Python复制一份到virtualenv的环境,用命令source venv/bin/activate进入一个virtualenv环境时,virtualenv会修改相关环境变量,让命令python和pip均指向当前的virtualenv环境。

自动虚拟环境

  1. virtualenv的一个最大的缺点就是:每次开启虚拟环境之前要去虚拟环境所在目录下的 bin 目录下 source 一下 activate,这就需要我们记住每个虚拟环境所在的目录。并且还有可能你忘记了虚拟环境放在哪。。。

  2. 一种可行的解决方案是,将所有的虚拟环境目录全都集中起来,例如/opt/all_venv/,并且针对不同的目录做不同的事。

  3. 使用virtualenvwrapper管理你的虚拟环境(virtualenv),其实他就是统一管理虚拟环境的目录,并且省去了source的步骤。

    pip3 install virtualenvwrapper                          # 安装virtualenvwrapper
    # 设置Linux的环境变量,每次启动就加载virtualenvwrapper
    # 把下面两行代码添加到 ~/.bashrc文件中
    vim ~/.bashrc
        # 写入以下两行代码
        export WORKON_HOME=~/Envs                           # 设置virtualenv的统一管理目录
        export VIRTUALENVWRAPPER_VIRTUALENV_ARGS='--no-site-packages'   # 添加virtualenvwrapper的参数,生成干净隔绝的环境
        export VIRTUALENVWRAPPER_PYTHON=/opt/python347/bin/python3      # 指定python解释器
        source /opt/python34/bin/virtualenvwrapper.sh       # 执行virtualenvwrapper安装脚本
  4. 基本使用virtualenvwrapper

    mkvirtualenv my_django115                               # 创建一个虚拟环境,这会在 ~/Envs 中创建 my_django115 文件夹。
    workon my_django115                                     # 在虚拟环境上工作:激活虚拟环境my_django115
    mkvirtualenv my_django2                                 # 再创建一个新的虚拟环境
    virtualenvwrapper                                       # 提供环境名字的tab补全功能.
    workon                                                  # 可以列出所有虚拟环境,
    workon django1.15                                       # 可以在多个虚拟环境中来回切换
    deactivate                                              # 也可以手动停止虚拟环境
    rmvirtualenv my_django115                               # 删除虚拟环境,需要先退出虚拟环境
  5. 常用其他命令

    lsvirtualenv                                            # 列举所有的环境。
    cdvirtualenv                                            # 导航到当前激活的虚拟环境的目录中,比如说这样您就能够浏览它的 site-packages 。
    cdsitepackages                                          # 和上面的类似,但是是直接进入到 site-packages 目录中。
    lssitepackages                                          # 显示 site-packages 目录中的内容。完整官网介绍:https://virtualenvwrapper.readthedocs.io/en/latest/command_ref.html

确保开发环境的一致性

  1. 假设我们在本地开发环境,准备好了项目+依赖包环境

  2. 现在需要将项目上传至服务器,上线发布,那么就要保证服务器的python环境一致性。

  3. 解决方案:

    pip3 freeze > requirements.txt                          # 通过命令保证环境的一致性,导出当前python环境的包
    pip3 install -r requirements.txt                        # 上传至服务器后,在服务器下创建virtualenv,在venv中导入项目所需的模块依赖
  4. 这将会创建一个 requirements.txt 文件,其中包含了当前环境中所有包及 各自的版本的简单列表。可以使用 “pip list”在不产生requirements文件的情况下, 查看已安装包的列表。

MySQL部署

  1. MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可。开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL闭源的潜在风险,因此社区采用分支的方式来避开这个风险。MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。

  2. yum安装mariadb,Red Hat Enterprise Linux/CentOS 7.0 发行版已将默认的数据库从 MySQL 切换到 MariaDB。

  3. 安装 MariaDB

    # 安装前先用命令卸载就的版本
    ​
    rpm -qa mariadb-libs
    yum remove mariadb-libs
    ​
    vi /etc/yum.repos.d/MariaDB.repo                        # 编辑创建mariadb.repo仓库文件
        [mariadb]                                           # 添加repo仓库配置
        name = MariaDB
        baseurl = http://yum.mariadb.org/10.1/centos7-amd64
        gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
        gpgcheck=
    yum install MariaDB-server MariaDB-client -y            # 当 MariaDB 仓库地址添加好后,你可以通过下面的一行命令轻松安装 MariaDB。
    # 启动mariadb相关命令
    systemctl start mariadb                                 # 启动MariaDB
    systemctl stop mariadb                                  # 停止MariaDB
    systemctl restart mariadb                               # 重启MariaDB
    systemctl enable mariadb                                # 设置开机启动

初始化mysql

  1. 在确认 MariaDB 数据库软件程序安装完毕并成功启动后请不要立即使用。为了确保数据 库的安全性和正常运转,需要先对数据库程序进行初始化操作。这个初始化操作涉及下面 5 个 步骤。 ➢ 设置 root 管理员在数据库中的密码值(注意,该密码并非 root 管理员在系统中的密 码,这里的密码值默认应该为空,可直接按回车键)。 ➢ 设置 root 管理员在数据库中的专有密码。 ➢ 随后删除匿名账户,并使用 root 管理员从远程登录数据库,以确保数据库上运行的业 务的安全性。 ➢ 删除默认的测试数据库,取消测试数据库的一系列访问权限。 ➢ 刷新授权列表,让初始化的设定立即生效。

  2. 确保mariadb服务器启动后,执行命令初始化

    mysql_secure_installation                               # 初始化mariadb
        Set root password?                                  # 设置root用户密码?
        Remove anonymous users?                             # 删除匿名用户?
        Disallow root login remotely?                       # 禁止root远程登陆?
        Remove test database and access to it?              # 删除test数据库并取消对它的访问权限?
        Reload privilege tables now?                        # 刷新授权表,让初始化后的设定立即生效?
  3. 用户的基本操作

    set password = PASSWORD('redhat123');                   # 修改mysql密码
    # 为了数据库的安全以及和其他用户协同管理数据库,就需要创建其他数据库账户,然后分配权限,满足工作需求。
    create user yuch@'127.0.0.1' identified by 'redhat123'; # 创建新用户
    use mysql;                                              # 进入mysql数据库
    select host,user,password from user where user='yuch';  # 查看指定用户的连接、密码、用户名
    mysql -uyuchao -p -h 127.0.0.1                          # 切换普通用户yuch
  4. 数据库权限设置,权限就是“create、insert、update、delete......”

    # mysql使用grant命令对账户进行授权,grant命令常见格式如下
    grant "permissions" on "database"."tablename" to "username"@"computername"      # 对特定数据库中的特定表授权
    grant "permissions" on "database".* to "username"@"computername"                # 对特定数据库中的所有表给与授权
    grant "permissions","permissions" on *.* to "username"@"computername"           # 对所有库中的所有表给与多个授权
    grant all privileges on *.* to "username"@"computername"                        # 对所有库和所有表授权所有权限
    revoke all privileges on *.* to "username"@"computername"                       # 移除权限

配置mysql

  1. 中文编码设置,编辑mysql配置文件/etc/my.cnf,下入以下内容

    [mysqld]
    character-set-server=utf8
    collation-server=utf8_general_ci
    log-error=/var/log/mysqld.log
    [client]
    default-character-set=utf8
    [mysql]
    default-character-set=utf8
  2. 授权配置

    grant all privileges on *.* to root@'%' identified by 'password';       # 远程连接设置哦设置所有库,所有表的所有权限,赋值权限给所有ip地址的root用户
    mysql > create user 'username'@'%' identified by 'password';            # 创建用户
    flush privileges;                                                       # 刷新权限
  3. 数据库备份与恢复

    mysqldump -u root -p --all-databases > /tmp/db.dump                     # mysqldump命令用于备份数据库数据
    mysqldump -uroot -proot --databases db1 db2 >/tmp/user.sql              # 导出db1、db2两个数据库的所有数据
    drop database s11;                                                      # 进入mariadb数据库,删除一个db
    mysql -uroot -p < /tmp/db.dump                                          # 进行数据恢复,吧刚才重定向备份的数据库文件导入到mysql中

MYSQL主从复制

  1. MySQL数据库的主从复制方案,是其自带的功能,并且主从复制并不是复制磁盘上的数据库文件,而是通过binlog日志复制到需要同步的从服务器上。

  2. MySQL数据库支持单向、双向、链式级联,等不同业务场景的复制。在复制的过程中,一台服务器充当主服务器(Master),接收来自用户的内容更新,而一个或多个其他的服务器充当从服务器(slave),接收来自Master上binlog文件的日志内容,解析出SQL,重新更新到Slave,使得主从服务器数据达到一致。

  3. 在生产环境中,MySQL主从复制都是异步的复制方式,即不是严格的实时复制,但是给用户的体验都是实时的。 MySQL主从复制集群功能使得MySQL数据库支持大规模高并发读写成为可能,且有效的保护了服务器宕机的数据备份。

master主

  1. 配置主库

    systemctl status mariadb                                                # 查看数据库状态
    systemctl stop mariadb                                                  # 停mariadb
    vim /etc/my.cnf                                                         # 修改配置文件
        [mysqld]
        server-id=1                                                         # 解释:server-id服务的唯一标识(主从之间都必须不同); 
        log-bin=mysql-bin                                                   # log-bin启动二进制日志名称为mysql-bin
    systemctl start mariadb                                                 # 重启mariadb
  2. master主库添加从库账号

    create user 'chaoge'@'192.168.178.130' identified by 'redhat';          # 新建用于主从同步的用户chaoge,允许登录的从库是'192.168.178.130'
    set global validate_password_policy=0;                                  # 题外话:如果提示密码太简单不复合策略加在前面加这句
    grant replication slave on *.* to 'chaoge'@'192.168.178.130';           # 给从库账号授权,说明给chaoge从库复制的权限,在192.168.178.130机器上复制
    select user,host from mysql.user;                                       # 检查主库创建的复制账号
    show grants for chaoge@'192.168.178.130';                               # 检查授权账号的权限
    flush table with read lock;                                             # 实现对主数据库锁表只读,防止数据写入,数据复制失败
    show master status                                                      # 检查主库的状态,File是二进制日志文件名,Position 是日志开始的位置。
    mysqldump -uroot -p --all-databases > /data/all.sql                     # 锁表后,一定要单独再打开一个SSH窗口,导出数据库的所有数据,
    show master status;                                                     # 确保数据导出后,没有数据插入,完毕再查看主库状态
    unlock tables;                                                          # 导出数据完毕后,解锁主库,恢复可写;
    scp /data/all.sql [email protected]:/data/                           # 将备份导出的数据scp至Slave数据库

slave从库配置

  1. 方式一

    # 设置server-id值并关闭binlog功能参数,数据库的server-id在主从复制体系内是唯一的,Slave的server-id要与主库和其他从库不同,并且注释掉Slave的binlog参数。
    # 因此修改Slave的/etc/my.cnf,写入
        [mysqld]
        server-id=3
    systemctl restart mariadb                                           # 重启数据库
    # 检查Slava从数据库的各项参数
    show variables like 'log_bin';
    show variables like 'server_id';
    source /data/all.sql;                                               # 恢复主库Master的数据导入到Slave库,导入数据(注意sql文件的路径)
  2. 方法二

    #mysql -uroot -p  < abc.sql 
    # 配置复制的参数,Slave从库连接Master主库的配置
    change master to master_host='192.168.178.129',
    master_user='chaoge',
    master_password='redhat',
    master_log_file='mysql-bin.000001',
    master_log_pos=575;
    start slave;                                                        # 启动从库的同步开关,测试主从复制的情况
    show slave status\G;                                                # 查看复制状态
  3. 注意此处还未配置从库的只读模式,只需在slave服务器上配置/etc/my.cnf,加上以下配置,并且在slave上创建普通用户,使用普通用户主从同步即可达到只读的效果

    [mysqld]
    character-set-server=utf8
    collation-server=utf8_general_ci
    log-error=/var/log/mysqld.log
    server-id=3
    read-only=true
    [client]
    default-character-set=utf8
    [mysql]
    default-character-set=utf8

NoSQL学习与部署

  1. 存储结构与mysql这一种关系型数据库完全不同,nosql存储的是KV形式,nosql有很多产品,都有自己的api和语法,以及业务场景。

  2. Nosql和sql的区别,应用场景不同,sql支持关系复杂的数据查询,nosql反之。sql支持事务性,nosql不支持

  3. redis特性,Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件,redis是c语言编写的,支持数据持久化,是key-value类型数据库。

  4. redis优势,性能高,读取速度10万次每秒,写入速度8万次每秒,所有操作支持原子性用作缓存数据库,数据放在内存中替代某些场景下的mysql,如社交类app大型系统中,可以存储session信息,购物车订单。

  5. yum安装redis

    # 前提得配置好阿里云yum源,epel源
    yum list redis                                                      # 查看是否有redis包                       
    redisyum install redis -y                                           # 安装
    redissystemctl start redis                                          # 安装好,启动
    redis-cli                                                           # redis 客户端工具
    ping                                                                # 进入交互式环境后,执行ping,返回pong表示安装成功
  6. 源码安装redis,编译安装,大家用过yum,是相当省事好用吧,为什么还要学习源码安装?

  7. 编译安装的优势是:编译安装时可以指定扩展的module(模块),php、apache、nginx都是一样有很多第三方扩展模块,如mysql,编译安装时候,如果需要就定制存储引擎(innodb,还是MyIASM)、编译安装可以统一安装路径,linux软件约定安装目录在/opt/下面、软件仓库版本一般比较低,编译源码安装可以根据需求,安装最新的版本。

    wget http://download.redis.io/releases/redis-4.0.10.tar.gz          # 下载redis源码
    tar -zxf redis-4.0.10.tar.gz                                        # 解压缩
    cd redis-4.0.10.tar.gz                                              # 切换redis源码目录
    make|make install                                                   # 编译源文件,安装到指定目录,默认在/usr/local/bin
    # 编译好后,src/目录下有编译好的redis指令
  8. redis可执行文件

    ./redis-benchmark													# 用于进行redis性能测试的工具
    ./redis-check-dump													# 用于修复出问题的dump.rdb文件
    ./redis-cli															# redis的客户端
    ./redis-server														# redis的服务端
    ./redis-check-aof													# 用于修复出问题的AOF文件
    ./redis-sentinel													# 用于集群管理
  9. redis配置文件,redis配置文件名为redis.conf 这个文件可以自定义。

    # redis.conf核心配置项
    bind 127.0.0.1														# 绑定ip,如需要远程访问,需要填写服务器ip
    port 																# 端口,redis启动端口
    daemonize yes														# 守护进程方式运行
    dbfilename dump.rdb													# rdb数据文件
    dir /var/lib/redis/													# 数据文件存放路径
    logfile /var/log/redis/redis-server.log								# 日志文件
    slaveof 															# 主从复制
  10. 启动redis服务端,启动redis非常简单,直接./redis-server就可以启动服务端了,还可以用下面的方法指定要加载的配置文件:./redis-server,../redis.conf默认情况下,redis-server会以非daemon的方式来运行,且默认服务端口为6379。

  11. 使用redis客户端

    ./redis-cli															# 执行客户端命令即可进入
        ping															# 测试是否连接上redis,返回pong代表连接上了
        set name "chaoge"												# 用set来设置key、value
        get name														# get获取name的值

Redis数据结构

  1. redis是一种高级的key:value存储系统,其中value支持五种数据类型:字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)。

    keys *																# 查看所有key
    type key															# 查看key类型
    expire key seconds													# 过期时间
    ttl key																# 查看key过期剩余时间,-2表示key已经不存在了
    persist																# 取消key的过期时间,-1表示key存在,没有过期时间
    exists key															# 判断key存在,存在返回1,否则0
    del keys															# 删除key,可以删除多个
    dbsize																# 计算key的数量
  2. strings

    set name 'yu'														# 设置key
    get name															# 获取value
    append name ' dsb'													# 追加key的string
    mset user1 'alex' user2 'xiaopeiqi'									# 设置多个键值对
    keys *																# 找到所有key
    mget user1 user2 name												# 获取多个value
    del name															# 删除key
    incr num															# 递增+1
    decr num															# 递减1  
  3. list

    lpush duilie 'alex' 'peiqi' 'ritian'  								# 新建一个duilie,从左边放入三个元素
    rpush duilie 'chaoge'   											# 从右边插入chaoge
    lrange duilie 0 -1  												# 查看duilie所有元素
    ltrim duilie 0 2  													# 截取队列的值,从索引0取到2,删除其余的元素
    lpop 																# 删除左边的第一个
    rpop 																# 删除右边的第一个
    llen duilie  														# 查看duilie长度
    lpushx duilie2  'dsb'  												# key存在则添加 dsb元素,key不存在则不作处理
  4. sets集合类型,redis的集合,是一种无序的集合,集合中的元素没有先后顺序。

    sadd zoo  wupeiqi yuanhao  											# 添加集合,有三个元素,不加引号就当做字符串处理
    srem zoo  wupeiqi 													# 删除zoo里面的alex
    smembers zoo  														# 查看集合zoo成员
    sismember zoo wupeiqi  												# 返回改是否是zoo的成员信息,不存在返回0,存在返回1
    sdiff zoo zoo2 														# 差集
    sinter zoo zoo1														# 交集
    sunion  zoo zoo1													# 并集
  5. 有序集合都是以z开头的命令,zset的每一个成员都有一个分数与之对应,并且分数是可以重复的。有序集合的增删改由于有啦排序,执行效率就是非常快速的,即便是访问集合中间的数据也是非常高效的。

    ZADD zoo  wupeiqi yuanhao  											# 添加集合,有三个元素,不加引号就当做字符串处理
    ZREVRANGE mid_test 0 -1 withscores									# 降序
    ZRANGE mid_test 0 -1 withscores										# 升序
    ZREM mid_test xiaofneg												# 删除一个
    ZCARD mid_test														# 基数
    ZSCORE mid_test alex												# score值
    ZRANK mid_test wusir												# zrank返回有序集合中,成员的排名。默认按score,从小到大排序。
  6. 哈希数据结构,哈希结构就是 k1 -> k1 : v1 如同字典 套字典 { k1 : { k2: v2 } } ,取出v2 必须 k1,取出k2。

    hset news1   title "first news title" 								# 设置第一条新闻 news的id为1,添加数据title的值是"news title"
    hget news1  content  												# 获取news的内容
    hmget news1  title content   										# 获取多对news:1的 值
    hmset news2 title "second news title" content "second Contents2"   	# 设置第二条新闻news:2 多个field
    hkeys news1   														# 获取新闻news:1的所有key
    hvals news1   														# 获取新闻news:1的所有值
    hlen news1    														# 获取新闻news:1的长度
    hdel news1 title   													# 删除新闻news:1的title
    hexists news1 title    												# 判断新闻1中是否有title,不存在返回0,存在返回1
    hsetnx  															# 如果散列已经存在,则不设置(防止覆盖key)

Redis安全

  1. 由于发现众多同学,在使用云服务器时,安装的redis3.0+版本都关闭了protected-mode,因而都遭遇了挖矿病毒的攻击,使得服务器99%的占用率!!因此我们在使用redis时候,最好更改默认端口,并且使用redis密码登录。

  2. redis没有用户概念,redis只有密码、redis默认在工作在保护模式下。不允许远程任何用户登录的(protected-mode)。

    # redis.conf设置
        protected-mode yes												# 打开保护模式
        port 6380														# 更改默认启动端口
        requirepass xxxxxx												# 设置redis启动密码,xxxx是自定义的密码
    # 启动redis服务端
    	redis-server /opt/redis-4.0.10/redis.conf &     				# 指定配置文件启动redis,且后台启动
    # 使用密码登录redis,使用6380端口
    
    # 方法1,使用这个
    redis-cli -p 6380
        auth xxxx
    # 方法2,此方案不安全,容易暴露密码
    redis-cli -p 6380 -a xxxx
        Warning: Using a password with '-a' option on the command line interface may not be safe.
        ping
    
    # CONFIG set requirepass "xxxxxx"									# 如果没有,也可以给redis设置密码(命令方式)

Redis主从同步

  1. 原理:

    1. 从服务器向主服务器发送 SYNC 命令。

    2. 接到 SYNC 命令的主服务器会调用BGSAVE 命令,创建一个 RDB 文件,并使用缓冲区记录接下来执行的所有写命令。

    3. 当主服务器执行完 BGSAVE 命令时,它会向从服务器发送 RDB 文件,而从服务器则会接收并载入这个文件。

    4. 主服务器将缓冲区储存的所有写命令发送给从服务器执行。

  2. 在开启主从复制的时候,使用的是RDB方式的,同步主从数据的

  3. 同步开始之后,通过主库命令传播的方式,主动的复制方式实现

  4. 2.8以后实现PSYNC的机制,实现断线重连

  5. 环境准备

    mkdir /data/638{0..2}  												# 创建6380 6381 6382文件夹
    # 配置文件示例:
    vim   /data/6380/redis.conf
        port 6380
        daemonize yes
        pidfile /data/6380/redis.pid
        loglevel notice
        logfile "/data/6380/redis.log"
        dbfilename dump.rdb
        dir /data/6380
        protected-mode no
    vim   /data/6381/redis.conf
        port 6381
        daemonize yes
        pidfile /data/6381/redis.pid
        loglevel notice
        logfile "/data/6381/redis.log"
        dbfilename dump.rdb
        dir /data/6381
        protected-mode no
    vim   /data/6382/redis.conf
        port 6382
        daemonize yes
        pidfile /data/6382/redis.pid
        loglevel notice
        logfile "/data/6382/redis.log"
        dbfilename dump.rdb
        dir /data/6382
        protected-mode no
    
    # 启动三个redis实例
    redis-server /data/6380/redis.conf
    redis-server /data/6381/redis.conf
    redis-server /data/6382/redis.conf
    # 配置主从同步, 6381/6382命令行
    redis-cli -p 6381
    	SLAVEOF 127.0.0.1 6380 											# 指明主的地址
    redis-cli -p 6382
    	SLAVEOF 127.0.0.1 6380 											# 指明主的地址
    # 检查主从状态
    # 从库:
    127.0.0.1:6382> info replication
    127.0.0.1:6381> info replication
    
    # 主库:
    127.0.0.1:6380> info replication
  6. 手动进行主从故障切换

    redis-cli -p 6380
    shutdown															# 关闭主库6380
    # 既然主库挂了,我想要在6381 6382之间选一个新的主库
    # 1.关闭6381的从库身份
        redis-cli -p 6381
        info replication
        slaveof no one
    # 2.将6382设为6381的从库
        redis-cli -p 6382
        SLAVEOF no one
        SLAVEOF 127.0.0.1 6381

Redis-Sentinel

  1. Redis-Sentinel是redis官方推荐的高可用性解决方案,当用redis作master-slave的高可用时,如果master本身宕机,redis本身或者客户端都没有实现主从切换的功能。

  2. 而redis-sentinel就是一个独立运行的进程,用于监控多个master-slave集群,自动发现master宕机,进行自动切换slave > master。

  3. sentinel主要功能如下:

    1. 不时的监控redis是否良好运行,如果节点不可达就会对节点进行下线标识

    2. 如果被标识的是主节点,sentinel就会和其他的sentinel节点“协商”,如果其他节点也人为主节点不可达,就会选举一个sentinel节点来完成自动故障转义

    3. 在master-slave进行切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换

Sentinel的工作方式

  1. 每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令

  2. 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。

  3. 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。

  4. 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线

  5. 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令

  6. 当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次

  7. 若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。

  8. 若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。

  9. 主观下线和客观下线

    1. 主观下线:Subjectively Down,简称 SDOWN,指的是当前 Sentinel 实例对某个redis服务器做出的下线判断。

    2. 客观下线:Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对Master Server做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,然后开启failover.

  10. SDOWN适合于Master和Slave,只要一个 Sentinel 发现Master进入了ODOWN, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对下线的主服务器执行自动故障迁移操作。

  11. ODOWN只适用于Master,对于Slave的 Redis 实例,Sentinel 在将它们判断为下线前不需要进行协商, 所以Slave的 Sentinel 永远不会达到ODOWN。

redis主从复制背景问题

  1. Redis主从复制可将主节点数据同步给从节点,从节点此时有两个作用:

    1. 一旦主节点宕机,从节点作为主节点的备份可以随时顶上来。

    2. 扩展主节点的读能力,分担主节点读压力。

  2. 但是问题是:

    1. 一旦主节点宕机,从节点上位,那么需要人为修改所有应用方的主节点地址(改为新的master地址),还需要命令所有从节点复制新的主节点

  3. 那么这个问题,redis-sentinel就可以解决了。

Redis Sentinel架构

  1. redis的一个进程,但是不存储数据,只是监控redis。

  2. Sentinel会通过命令连接向被监视的主从服务器发送“HELLO”信息,该消息包含Sentinel的ip、端口号、ID等内容,以此来向其他Sentinel发布自己的存在。与此同时Sentinel会通过订阅连接接收其他Sentinel的“HELLO”信息,以此来发现监视同一个主服务器的其他Sentinel。

  3. Redis Sentinel故障转移

    1. 多个sentinel发现并确认master有问题后,选举出一个sentinel作为领导。

    2. 选出一个slave作为master,通知其余slave成为新的master的slave。

    3. 通知客户端主从变化,等待老的master复活成为新master的slave。

  4. redis命令整理

    # 官网地址:http://redisdoc.com/
    redis-cli info 															# 查看redis数据库信息
    redis-cli info replication 												# 查看redis的复制授权信息
    redis-cli info sentinel   												# 查看redis的哨兵信息

安装与配置

  1. 本实验是在测试环境下,考虑到学生机器较弱,因此只准备一台linux服务器用作环境!!

  2. 服务器环境,一台即可完成操作master 192.168.119.10

  3. 主节点master的redis-6379.conf

    port 6379
    daemonize yes
    logfile "6379.log"
    dbfilename "dump-6379.rdb"
    dir "/var/redis/data/"
  4. 从节点slave的redis-6380.conf

    port 6380
    daemonize yes
    logfile "6380.log"
    dbfilename "dump-6380.rdb"
    dir "/var/redis/data/" 
    slaveof 127.0.0.1 6379      // 从属主节点
  5. 从节点slave的redis-6381.conf

    port 6381
    daemonize yes
    logfile "6380.log"
    dbfilename "dump-6380.rdb"
    dir "/var/redis/data/" 
    slaveof 127.0.0.1 6379      // 从属主节点
  6. 启动redis主节点redis-server /etc/redis-6379.conf

  7. 测试redis主节点是否通信redis-cli ping

  8. 启动两slave节点

    -rw-r--r-- 1 root root 145 Nov  7 17:44 /etc/redis-6379.conf      # 这个为主,port是6379
    -rw-r--r-- 1 root root  93 Nov  7 17:42 /etc/redis-6380.conf    # 这个是从,port6380,并且得加上新的参数slaveof
    -rw-r--r-- 1 root root 115 Nov  7 17:42 /etc/redis-6381.conf      # 这个是从,port6381,并且得加上新的参数slaveof
    # redis-6380.conf slave配置文件详解,6381端口的配置文件,仅仅和6380端口不一样
    port 6380
    daemonize yes
    logfile "6379.log"
    dbfilename "dump-6379.rdb"
    dir "/var/redis/data"
    # Generated by CONFIG REWRITE
    slaveof 127.0.0.1 6379
  9. redis配置文件

    # Redis 配置文件
    
    # 当配置中需要配置内存大小时,可以使用 1k, 5GB, 4M 等类似的格式,其转换方式如下(不区分大小写)
    #
    # 1k => 1000 bytes
    # 1kb => 1024 bytes
    # 1m => 1000000 bytes
    # 1mb => 1024*1024 bytes
    # 1g => 1000000000 bytes
    # 1gb => 1024*1024*1024 bytes
    #
    # 内存配置大小写是一样的.比如 1gb 1Gb 1GB 1gB
    
    # daemonize no 默认情况下,redis不是在后台运行的,如果需要在后台运行,把该项的值更改为yes
    daemonize yes
    
    # 当redis在后台运行的时候,Redis默认会把pid文件放在/var/run/redis.pid,你可以配置到其他地址。
    # 当运行多个redis服务时,需要指定不同的pid文件和端口
    pidfile /var/run/redis.pid
    
    # 指定redis运行的端口,默认是6379
    port 6379
    
    # 指定redis只接收来自于该IP地址的请求,如果不进行设置,那么将处理所有请求,
    # 在生产环境中最好设置该项
    # bind 127.0.0.1
    
    # Specify the path for the unix socket that will be used to listen for
    # incoming connections. There is no default, so Redis will not listen
    # on a unix socket when not specified.
    #
    # unixsocket /tmp/redis.sock
    # unixsocketperm 755
    
    # 设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接
    # 0是关闭此设置
    timeout 0
    
    # 指定日志记录级别
    # Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
    # debug    记录很多信息,用于开发和测试
    # varbose    有用的信息,不像debug会记录那么多
    # notice    普通的verbose,常用于生产环境
    # warning    只有非常重要或者严重的信息会记录到日志
    loglevel debug
    
    # 配置log文件地址
    # 默认值为stdout,标准输出,若后台模式会输出到/dev/null
    #logfile stdout
    logfile /var/log/redis/redis.log
    
    # To enable logging to the system logger, just set 'syslog-enabled' to yes,
    # and optionally update the other syslog parameters to suit your needs.
    # syslog-enabled no
    
    # Specify the syslog identity.
    # syslog-ident redis
    
    # Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
    # syslog-facility local0
    
    # 可用数据库数
    # 默认值为16,默认数据库为0,数据库范围在0-(database-1)之间
    databases 16
    
    ################################ 快照 #################################
    #
    # 保存数据到磁盘,格式如下:
    #
    # save <seconds> <changes>
    #
    # 指出在多长时间内,有多少次更新操作,就将数据同步到数据文件rdb。
    # 相当于条件触发抓取快照,这个可以多个条件配合
    # 
    # 比如默认配置文件中的设置,就设置了三个条件
    #
    # save 900 1 900秒内至少有1个key被改变
    # save 300 10 300秒内至少有300个key被改变
    # save 60 10000 60秒内至少有10000个key被改变
    
    save 900 1
    save 300 10
    save 60 10000
    
    # 存储至本地数据库时(持久化到rdb文件)是否压缩数据,默认为yes
    rdbcompression yes
    
    # 本地持久化数据库文件名,默认值为dump.rdb
    dbfilename dump.rdb
    
    # 工作目录
    #
    # 数据库镜像备份的文件放置的路径。
    # 这里的路径跟文件名要分开配置是因为redis在进行备份时,先会将当前数据库的状态写入到一个临时文件中,等备份完成时,
    # 再把该该临时文件替换为上面所指定的文件,而这里的临时文件和上面所配置的备份文件都会放在这个指定的路径当中。
    # 
    # AOF文件也会存放在这个目录下面
    # 
    # 注意这里必须制定一个目录而不是文件
    dir ./
    
    ################################# 复制 #################################
    
    # 主从复制. 设置该数据库为其他数据库的从数据库. 
    # 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
    #
    # slaveof <masterip> <masterport>
    
    # 当master服务设置了密码保护时(用requirepass制定的密码)
    # slav服务连接master的密码
    # 
    # masterauth <master-password>
    
    
    # 当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:
    #
    # 1) 如果slave-serve-stale-data设置为yes(默认设置),从库会继续相应客户端的请求
    # 
    # 2) 如果slave-serve-stale-data是指为no,出去INFO和SLAVOF命令之外的任何请求都会返回一个
    # 错误"SYNC with master in progress"
    #
    slave-serve-stale-data yes
    
    # 从库会按照一个时间间隔向主库发送PINGs.可以通过repl-ping-slave-period设置这个时间间隔,默认是10秒
    #
    # repl-ping-slave-period 10
    
    # repl-timeout 设置主库批量数据传输时间或者ping回复时间间隔,默认值是60秒
    # 一定要确保repl-timeout大于repl-ping-slave-period
    # repl-timeout 60
    
    ################################## 安全 ###################################
    
    # 设置客户端连接后进行任何其他指定前需要使用的密码。
    # 警告:因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行150K次的密码尝试,这意味着你需要指定非常非常强大的密码来防止暴力破解
    #
    # requirepass foobared
    
    # 命令重命名.
    #
    # 在一个共享环境下可以重命名相对危险的命令。比如把CONFIG重名为一个不容易猜测的字符。
    #
    # 举例:
    #
    # rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
    #
    # 如果想删除一个命令,直接把它重命名为一个空字符""即可,如下:
    #
    # rename-command CONFIG ""
    
    ################################### 约束 ####################################
    
    # 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,
    # 如果设置 maxclients 0,表示不作限制。
    # 当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
    #
    # maxclients 128
    
    # 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key
    # Redis同时也会移除空的list对象
    #
    # 当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作
    # 
    # 注意:Redis新的vm机制,会把Key存放内存,Value会存放在swap区
    #
    # maxmemory的设置比较适合于把redis当作于类似memcached的缓存来使用,而不适合当做一个真实的DB。
    # 当把Redis当做一个真实的数据库使用的时候,内存使用将是一个很大的开销
    # maxmemory <bytes>
    
    # 当内存达到最大值的时候Redis会选择删除哪些数据?有五种方式可供选择
    # 
    # volatile-lru -> 利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used )
    # allkeys-lru -> 利用LRU算法移除任何key
    # volatile-random -> 移除设置过过期时间的随机key
    # allkeys->random -> remove a random key, any key 
    # volatile-ttl -> 移除即将过期的key(minor TTL)
    # noeviction -> 不移除任何可以,只是返回一个写错误
    # 
    # 注意:对于上面的策略,如果没有合适的key可以移除,当写的时候Redis会返回一个错误
    #
    # 写命令包括: set setnx setex append
    # incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
    # sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
    # zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
    # getset mset msetnx exec sort
    #
    # 默认是:
    #
    # maxmemory-policy volatile-lru
    
    # LRU 和 minimal TTL 算法都不是精准的算法,但是相对精确的算法(为了节省内存),随意你可以选择样本大小进行检测。
    # Redis默认的灰选择3个样本进行检测,你可以通过maxmemory-samples进行设置
    #
    # maxmemory-samples 3
    
    ############################## AOF ###############################
    
    
    # 默认情况下,redis会在后台异步的把数据库镜像备份到磁盘,但是该备份是非常耗时的,而且备份也不能很频繁,如果发生诸如拉闸限电、拔插头等状况,那么将造成比较大范围的数据丢失。
    # 所以redis提供了另外一种更加高效的数据库备份及灾难恢复方式。
    # 开启append only模式之后,redis会把所接收到的每一次写操作请求都追加到appendonly.aof文件中,当redis重新启动时,会从该文件恢复出之前的状态。
    # 但是这样会造成appendonly.aof文件过大,所以redis还支持了BGREWRITEAOF指令,对appendonly.aof 进行重新整理。
    # 你可以同时开启asynchronous dumps 和 AOF
    
    appendonly no
    
    # AOF文件名称 (默认: "appendonly.aof")
    # appendfilename appendonly.aof
    
    # Redis支持三种同步AOF文件的策略:
    #
    # no: 不进行同步,系统去操作 . Faster.
    # always: always表示每次有写操作都进行同步. Slow, Safest.
    # everysec: 表示对写操作进行累积,每秒同步一次. Compromise.
    #
    # 默认是"everysec",按照速度和安全折中这是最好的。
    # 如果想让Redis能更高效的运行,你也可以设置为"no",让操作系统决定什么时候去执行
    # 或者相反想让数据更安全你也可以设置为"always"
    #
    # 如果不确定就用 "everysec".
    
    # appendfsync always
    appendfsync everysec
    # appendfsync no
    
    # AOF策略设置为always或者everysec时,后台处理进程(后台保存或者AOF日志重写)会执行大量的I/O操作
    # 在某些Linux配置中会阻止过长的fsync()请求。注意现在没有任何修复,即使fsync在另外一个线程进行处理
    #
    # 为了减缓这个问题,可以设置下面这个参数no-appendfsync-on-rewrite
    #
    # This means that while another child is saving the durability of Redis is
    # the same as "appendfsync none", that in pratical terms means that it is
    # possible to lost up to 30 seconds of log in the worst scenario (with the
    # default Linux settings).
    # 
    # If you have latency problems turn this to "yes". Otherwise leave it as
    # "no" that is the safest pick from the point of view of durability.
    no-appendfsync-on-rewrite no
    
    # Automatic rewrite of the append only file.
    # AOF 自动重写
    # 当AOF文件增长到一定大小的时候Redis能够调用 BGREWRITEAOF 对日志文件进行重写 
    # 
    # 它是这样工作的:Redis会记住上次进行些日志后文件的大小(如果从开机以来还没进行过重写,那日子大小在开机的时候确定)
    #
    # 基础大小会同现在的大小进行比较。如果现在的大小比基础大小大制定的百分比,重写功能将启动
    # 同时需要指定一个最小大小用于AOF重写,这个用于阻止即使文件很小但是增长幅度很大也去重写AOF文件的情况
    # 设置 percentage 为0就关闭这个特性
    
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    
    ################################## SLOW LOG ###################################
    
    # Redis Slow Log 记录超过特定执行时间的命令。执行时间不包括I/O计算比如连接客户端,返回结果等,只是命令执行时间
    # 
    # 可以通过两个参数设置slow log:一个是告诉Redis执行超过多少时间被记录的参数slowlog-log-slower-than(微妙),
    # 另一个是slow log 的长度。当一个新命令被记录的时候最早的命令将被从队列中移除
    
    # 下面的时间以微妙微单位,因此1000000代表一分钟。
    # 注意制定一个负数将关闭慢日志,而设置为0将强制每个命令都会记录
    slowlog-log-slower-than 10000
    
    # 对日志长度没有限制,只是要注意它会消耗内存
    # 可以通过 SLOWLOG RESET 回收被慢日志消耗的内存
    slowlog-max-len 1024
    
    ################################ VM ###############################
    
    ### WARNING! Virtual Memory is deprecated in Redis 2.4
    ### The use of Virtual Memory is strongly discouraged.
    
    # Virtual Memory allows Redis to work with datasets bigger than the actual
    # amount of RAM needed to hold the whole dataset in memory.
    # In order to do so very used keys are taken in memory while the other keys
    # are swapped into a swap file, similarly to what operating systems do
    # with memory pages.
    #
    # To enable VM just set 'vm-enabled' to yes, and set the following three
    # VM parameters accordingly to your needs.
    
    vm-enabled no
    # vm-enabled yes
    
    # This is the path of the Redis swap file. As you can guess, swap files
    # can't be shared by different Redis instances, so make sure to use a swap
    # file for every redis process you are running. Redis will complain if the
    # swap file is already in use.
    #
    # The best kind of storage for the Redis swap file (that's accessed at random) 
    # is a Solid State Disk (SSD).
    #
    # *** WARNING *** if you are using a shared hosting the default of putting
    # the swap file under /tmp is not secure. Create a dir with access granted
    # only to Redis user and configure Redis to create the swap file there.
    vm-swap-file /tmp/redis.swap
    
    # vm-max-memory configures the VM to use at max the specified amount of
    # RAM. Everything that deos not fit will be swapped on disk *if* possible, that
    # is, if there is still enough contiguous space in the swap file.
    #
    # With vm-max-memory 0 the system will swap everything it can. Not a good
    # default, just specify the max amount of RAM you can in bytes, but it's
    # better to leave some margin. For instance specify an amount of RAM
    # that's more or less between 60 and 80% of your free RAM.
    vm-max-memory 0
    
    # Redis swap files is split into pages. An object can be saved using multiple
    # contiguous pages, but pages can't be shared between different objects.
    # So if your page is too big, small objects swapped out on disk will waste
    # a lot of space. If you page is too small, there is less space in the swap
    # file (assuming you configured the same number of total swap file pages).
    #
    # If you use a lot of small objects, use a page size of 64 or 32 bytes.
    # If you use a lot of big objects, use a bigger page size.
    # If unsure, use the default :)
    vm-page-size 32
    
    # Number of total memory pages in the swap file.
    # Given that the page table (a bitmap of free/used pages) is taken in memory,
    # every 8 pages on disk will consume 1 byte of RAM.
    #
    # The total swap size is vm-page-size * vm-pages
    #
    # With the default of 32-bytes memory pages and 134217728 pages Redis will
    # use a 4 GB swap file, that will use 16 MB of RAM for the page table.
    #
    # It's better to use the smallest acceptable value for your application,
    # but the default is large in order to work in most conditions.
    vm-pages 134217728
    
    # Max number of VM I/O threads running at the same time.
    # This threads are used to read/write data from/to swap file, since they
    # also encode and decode objects from disk to memory or the reverse, a bigger
    # number of threads can help with big objects even if they can't help with
    # I/O itself as the physical device may not be able to couple with many
    # reads/writes operations at the same time.
    #
    # The special value of 0 turn off threaded I/O and enables the blocking
    # Virtual Memory implementation.
    vm-max-threads 4
    
    ############################### ADVANCED CONFIG ###############################
    
    # 当hash中包含超过指定元素个数并且最大的元素没有超过临界时,
    # hash将以一种特殊的编码方式(大大减少内存使用)来存储,这里可以设置这两个临界值
    # Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,
    # 这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,
    # 当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。
    hash-max-zipmap-entries 512
    hash-max-zipmap-value 64
    
    # list数据类型多少节点以下会采用去指针的紧凑存储格式。
    # list数据类型节点值大小小于多少字节会采用紧凑存储格式。
    list-max-ziplist-entries 512
    list-max-ziplist-value 64
    
    # set数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储。
    set-max-intset-entries 512
    
    # zsort数据类型多少节点以下会采用去指针的紧凑存储格式。
    # zsort数据类型节点值大小小于多少字节会采用紧凑存储格式。
    zset-max-ziplist-entries 128
    zset-max-ziplist-value 64
    
    # Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行重新hash,可以降低内存的使用
    # 
    # 当你的使用场景中,有非常严格的实时性需要,不能够接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。
    #
    # 如果没有这么严格的实时性要求,可以设置为yes,以便能够尽可能快的释放内存
    activerehashing yes
    
    ################################## INCLUDES ###################################
    
    # 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
    
    # include /path/to/local.conf
    # include /path/to/other.conf
  10. 启动slave从节点的redis服务:redis-server /etc/redis-6380.confredis-server /etc/redis-6381.conf

  11. 验证从节点的redis服务:redis-cli -p 6380 pingredis-cli -p 6381 ping

  12. 确定主从关系

    # 在主节点上查看主从通信关系
        [root@master ~]# redis-cli  -p 6379 info replication
        # Replication
        role:master
        connected_slaves:2
        slave0:ip=192.168.119.10,port=6380,state=online,offset=407,lag=0
        slave1:ip=192.168.119.10,port=6381,state=online,offset=407,lag=0
        master_repl_offset:407
        repl_backlog_active:1
        repl_backlog_size:1048576
        repl_backlog_first_byte_offset:2
        repl_backlog_histlen:406
    # 在从节点上查看主从关系(6380、6379)
        [root@slave 192.168.119.11 ~]$redis-cli  -p 6380 info replication
        # Replication
        role:slave
        master_host:192.168.119.10
        master_port:6379
        master_link_status:up
        master_last_io_seconds_ago:3
        master_sync_in_progress:0
        slave_repl_offset:505
        slave_priority:100
        slave_read_only:1
        connected_slaves:0
        master_repl_offset:0
        repl_backlog_active:0
        repl_backlog_size:1048576
        repl_backlog_first_byte_offset:0
        repl_backlog_histlen:0
  13. 开始配置Redis Sentinel

    [root@master tmp]# ll /etc/redis-*
    -rw-r--r-- 1 root root 556 Nov  7 17:42 /etc/redis-sentinel-26379.conf
    # redis-sentinel-26379.conf配置文件写入如下信息redis-sentinel-26379.conf配置文件写入如下信息
        // Sentinel节点的端口
        port 26379  
        dir /var/redis/data/
        logfile "26379.log"
    
        // 当前Sentinel节点监控 192.168.119.10:6379 这个主节点
        // 2代表判断主节点失败至少需要2个Sentinel节点节点同意
        // mymaster是主节点的别名
        sentinel monitor mymaster 192.168.119.10 6379 2
    
        //每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30000毫秒30s且没有回复,则判定不可达
        sentinel down-after-milliseconds mymaster 30000
    
        //当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1
        sentinel parallel-syncs mymaster 1
    
        //故障转移超时时间为180000毫秒
        sentinel failover-timeout mymaster 180000
        
    redis-sentinel-26380.conf和redis-sentinel-26381.conf的配置仅仅差异是port(端口)的不同。
    # 然后启动三个sentinel哨兵
    redis-sentinel /etc/redis-sentinel-26379.conf
    redis-sentinel /etc/redis-sentinel-26380.conf
    redis-sentinel /etc/redis-sentinel-26381.conf
    
    # 此时查看哨兵是否成功通信
        [root@master ~]# redis-cli -p 26379  info sentinel
        # Sentinel
        sentinel_masters:1
        sentinel_tilt:0
        sentinel_running_scripts:0
        sentinel_scripts_queue_length:0
        sentinel_simulate_failure_flags:0
        master0:name=mymaster,status=ok,address=192.168.119.10:6379,slaves=2,sentinels=3#看到最后一条信息正确即成功了哨兵,哨兵主节点名字叫做mymaster,状态ok,监控地址是192.168.119.10:6379,有两个从节点,3个哨兵

redis高可用故障实验

  1. 大致思路

    1. 杀掉主节点的redis进程6379端口,观察从节点是否会进行新的master选举,进行切换

    2. 重新恢复旧的“master”节点,查看此时的redis身份

  2. 首先查看三个redis的进程状态:ps -ef|grep redis

  3. 检查三个节点的复制身份状态。

    # 第一个
        [root@master tmp]# redis-cli -p 6381 info replication
        # Replication
        role:slave
        master_host:127.0.0.1
        master_port:6380
    # 第二个
        [root@master tmp]# redis-cli -p 6380 info replication
        # Replication
        role:master
        connected_slaves:2
        slave0:ip=127.0.0.1,port=6381,state=online,offset=54386,lag=0
        slave1:ip=127.0.0.1,port=6379,state=online,offset=54253,lag=0
    # 第三个
        [root@master tmp]# redis-cli -p 6379 info replication
        # Replication
        role:slave
        master_host:127.0.0.1
        master_port:6380
    # 此时,干掉master!!!然后等待其他两个节点是否能自动被哨兵sentienl,切换为master节点
    ps -ef|grep 6380   		# 干掉master进程
    
    # 此时查看两个slave的状态,精髓就是查看一个参数
    master_link_down_since_seconds:13
    
    # 稍等片刻之后,发现slave节点成为master节点!!
        [root@master tmp]# redis-cli -p 6379 info replication
        # Replication
        role:master
        connected_slaves:1
        slave0:ip=127.0.0.1,port=6381,state=online,offset=41814,lag=1

Redis-Cluster配置

  1. 并发问题:redis官方生成可以达到 10万/每秒,每秒执行10万条命令,假如业务需要每秒100万的命令执行呢?

  2. 数据量太大:一台服务器内存正常是16~256G,假如你的业务需要500G内存。新浪微博作为世界上最大的redis存储,就超过1TB的数据,去哪买这么大的内存条?各大公司有自己的解决方案,推出各自的集群功能,核心思想都是将数据分片(sharding)存储在多个redis实例中,每一片就是一个redis实例。

  3. 解决方案:正确的应该是考虑分布式,加机器,把数据分到不同的位置,分摊集中式的压力,一堆机器做一件事。

  4. 客户端分片:redis3.0集群采用P2P模式,完全去中心化,将redis所有的key分成了16384个槽位,每个redis实例负责一部分slot,集群中的所有信息通过节点数据交换而更新。redis实例集群主要思想是将redis数据的key进行散列,通过hash函数特定的key会映射到指定的redis节点上。

  5. 数据分布理论:分布式数据库首要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整个数据的一个子集。

  6. 常见的分区规则有哈希分区和顺序分区。Redis Cluster采用哈希分区规则,因此接下来会讨论哈希分区规则。节点取余分区、一致性哈希分区、虚拟槽分区(redis-cluster采用的方式)。

    1. 顺序分区是在3个节点获得3分支1的任务,并且资源从小到大一次分配。

    2. 哈希分区,节点取余的方式,分三个节点1~100的数据对3取余,可以分为三类,0、1、2。

    3. 一致性哈希,客户端进行分片,哈希+顺时针取余。

  7. 虚拟槽分区

    1. Redis Cluster采用虚拟槽分区

    2. 虚拟槽分区巧妙地使用了哈希空间,使用分散度良好的哈希函数把所有的数据映射到一个固定范围内的整数集合,整数定义为槽(slot)。

    3. Redis Cluster槽的范围是0 ~ 16383。槽是集群内数据管理和迁移的基本单位。采用大范围的槽的主要目的是为了方便数据的拆分和集群的扩展,每个节点负责一定数量的槽。

搭建redis cluster

  1. 搭建集群分为几部:准备节点、节点通信、分配槽位给节点。

  2. redis-cluster集群架构:多个服务端,负责读写,彼此通信,redis指定了16384个槽。多匹马儿,负责运输数据,马儿分配16384个槽位,管理数据。ruby的脚本自动就把分配槽位这事做了

  3. 安装方式:官方提供通过ruby语言的脚本一键安装。

  4. 环境准备:通过配置,开启redis-cluster

    port 7000
    daemonize yes
    dir "/opt/redis/data"
    logfile "7000.log"
    dbfilename "dump-7000.rdb"
    cluster-enabled yes   #开启集群模式
    cluster-config-file nodes-7000.conf  #集群内部的配置文件
    cluster-require-full-coverage no  #redis cluster需要16384个slot都正常的时候才能对外提供服务,换句话说,只要任何一个slot异常那么整个cluster不对外提供服务。 因此生产环境一般为no
  5. redis支持多实例的功能,我们在单机演示集群搭建,需要6个实例,三个是主节点,三个是从节点,数量为6个节点才能保证高可用的集群。

  6. 每个节点仅仅是端口运行的不同!

    [root@yugo /opt/redis/config 17:12:30]#ls
    redis-7000.conf  redis-7002.conf  redis-7004.conf
    redis-7001.conf  redis-7003.conf  redis-7005.conf#确保每个配置文件中的端口修改!!
  7. 运行redis实例:创建6个节点的redis实例

     1855  2018-10-24 15:46:01 redis-server redis-7000.conf
     1856  2018-10-24 15:46:13 redis-server redis-7001.conf
     1857  2018-10-24 15:46:16 redis-server redis-7002.conf
     1858  2018-10-24 15:46:18 redis-server redis-7003.conf
     1859  2018-10-24 15:46:20 redis-server redis-7004.conf
     1860  2018-10-24 15:46:23 redis-server redis-7005.conf
  8. 检查日志文件:cat 7000.log

  9. 检查redis服务的端口、进程:netstat -tunlp|grep redisps -ef|grep redis

  10. 此时集群还不可用,可以通过登录redis查看

    redis-cli -p 7000
    set hello world
  11. 创建开启redis-cluster,准备ruby环境:下载、编译、安装Ruby|安装rubygem redis|安装redis-trib.rb命令。

    1. 安装ruby(这些命令可以放入一个sh脚本文件里)

      #下载ruby
      wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
      
      #安装ruby
      tar -xvf ruby-2.3.1.tar.gz
      ./configure --prefix=/opt/ruby/
      make && make install
      #准备一个ruby命令#准备一个gem软件包管理命令
      #拷贝ruby命令到path下/usr/local/ruby
      cp /opt/ruby/bin/ruby /usr/local/cp bin/gem /usr/local/bin
    2. 安装ruby gem 包管理工具

      wget http://rubygems.org/downloads/redis-3.3.0.gem
      
      gem install -l redis-3.3.0.gem
      #查看gem有哪些包
      gem list -- check redis gem
    3. 安装redis-trib.rb命令:cp /opt/redis/src/redis-trib.rb /usr/local/bin/

  12. 一键开启redis-cluster集群

    #每个主节点,有一个从节点,代表--replicas 1
    redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
    #集群自动分配主从关系  7000、7001、7002为 7003、7004、7005 主动关系
  13. 查看集群状态

    redis-cli -p 7000 cluster info  
    redis-cli -p 7000 cluster nodes  #等同于查看nodes-7000.conf文件节点信息
    集群主节点状态
    redis-cli -p 7000 cluster nodes | grep master
    集群从节点状态
    redis-cli -p 7000 cluster nodes | grep slave
  14. 安装完毕后,检查集群状态:redis-cli -p 7000 cluster info

  15. 测试写入集群数据,登录集群必须使用redis-cli -c -p 7000必须加上-c参数

    127.0.0.1:7000> set name chao     
    -> Redirected to slot [5798] located at 127.0.0.1:7001       
    OK
    127.0.0.1:7001> exit
    [root@yugo /opt/redis/src 18:46:07]#redis-cli -c -p 7000
    127.0.0.1:7000> ping
    PONG
    127.0.0.1:7000> keys *
    (empty list or set)
    127.0.0.1:7000> get name
    -> Redirected to slot [5798] located at 127.0.0.1:7001
    "chao"

高级阶段

Web服务基础

  1. 用户访问网站的基本流程:我们每天都会用web客户端上网,浏览器就是一个web客户端,例如谷歌浏览器,以及火狐浏览器等。

    1. 老男孩教育某python总监,讲了一天课感觉很累,下了班躺床上打开他的macbook pro,双击浏览器,输入www.pornhub.com网址后,系统首先会查找本地的DNS缓存以及hosts文件信息,确定是否存在www.pornhub.com域名对应的ip解析记录,如果有就直接获取ip进行访问服务器,第一次请求时,dns缓存是没有解析记录的,hosts文件多数是开发临时测试用

    2. 如果本地dns缓存和hosts文件都没有域名解析记录,系统就会把某python总监访问的网址解析请求发送给客户端设置的DNS服务器去解析,也叫做Local DNS,如果LDNS服务器的本地缓存有对应的解析记录就会直接返回给客户端IP地址,如果没有LDNS就会继续请求其他的DNS服务器

    3. LDNS继续从DNS系统的"."(根)开始请求www.pornhub.com域名的解析,并且根据每个层级的DNS服务器系统进行系列的查找,最终在DNS网络上找到www.pornhub.com域名对应的授权DNS服务器。这个授权DNS服务器就是企业(个人)购买域名时用于管理域名解析的服务器,服务器上有对应的域名(IP)解析。

    4. 此时授权的DNS服务器就会把www.pornhub.com对应的IP解析记录,例如(1.1.1.1)发送给LDNS

    5. 此时LDNS会把解析记录发给浏览器,并且缓存域名和IP的解析记录,便于下一次更快的返回请求

    6. 浏览器获得ip,请求对应的服务器,网站服务器接收到客户端的请求开始响应处理,将内容返回给浏览器,然后某python总监拿出了一盒清风牌抽纸。。。。

HTTP协议

  1. Http协议,全称是HyperText Tansfer Protocol,中文叫超文本传输协议,是互联网最常见的协议。Http最重要的是www(World Wide Web)服务,也叫web服务器,中文叫“万维网”。web服务端口默认是80,另外一个加密的www服务应用https默认端口是443,主要用于支付,网银相关业务

  2. 版本

    1. http协议诞生以来有若干个版本,主要是http/1.0 http/1.1

    2. http/1.0规定浏览器和服务器只能保持短暂的连接,浏览器的每次请求都需要和服务器建立一个TCP连接,服务器完成请求后即断开TCP连接,服务器不跟踪每个链接,也不记录请求

    3. http/1.1是对HTTP的缺陷进行重点修复,从可扩展性,缓存,带宽优化,持久连接,host头,错误通知等访问改进。

    4. http/1.1支持长连接,增加了更多的请求头和响应头信息,例如配置请求头的Connection的值为keep-alive,表示请求结果返回后保持连接

  3. Http请求方法:在HTTP通信中,每个请求报文都包含一个方法,以告诉web服务器端需要执行哪些操作,这些动作被称为HTTP的请求方法

    1    GET     # 请求指定的页面信息,并返回实体主体。
    2    HEAD    # 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
    3    POST    # 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
    4    PUT     # 从客户端向服务器传送的数据取代指定的文档的内容。
    5    DELETE  # 请求服务器删除指定的页面。
    6    CONNECT # HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
    7    OPTIONS # 允许客户端查看服务器的性能。
    8    TRACE   # 回显服务器收到的请求,主要用于测试或诊断。
  4. HTTP状态码,HTTp状态码表示web服务器响应http请求状态的数字代码

    常见状态码以及作用是
    1**    信息,服务器收到请求,需要请求者继续执行操作
    2**    成功,操作被成功接收并处理
    3**    重定向,需要进一步的操作以完成请求
    4**    客户端错误,请求包含语法错误或无法完成请求
    5**    服务器错误,服务器在处理请求的过程中发生了错误
  5. HTTP状态码的命令查看

    curl -I www.oldboyedu.com
    Server: OES
    Date: Sun, 12 Aug 2018 04:18:24 GMT
    Content-Type: text/html
    Content-Length: 152
    Connection: keep-alive
    Location: https://www.oldboyedu.com/

Http报文

  1. HTTP请求由请求行,请求头部,空行,请求报文主体几个部分组成

  2. HTTP报文:它是HTTP应用程序之间发送的数据块。这些数据块以一些文本形式的元信息开头,这些信息描述了报文的内容及含义,后面跟着可选的数据部分。这些报文都是在客户端、服务器和代理之间流动。

    请求报文的格式:
        起始行: <method> <request-URL> <version>
        头部:   <headers>
        主体:   <entity-body>
  3. 请求行:请求报文第一行,表示客户端想要什么,由请求方法 url 协议版本   组成。

  4. 请求头部:请求头由 关键字 : 值 组成,通过客户端把请求相关信息告诉服务器。

  5. 空行:请求头信息之后是一个空行,发送回车和换行符,通知web服务器以下没有请求头信息了。

  6. 请求报文主体

     POST / HTTP/1.1
     Host: www.example.com
     User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
     Gecko/20050225 Firefox/1.0.1
     Content-Type: application/x-www-form-urlencoded
     Content-Length: 40
     Connection: Keep-Alive
    
     sex=man&name=Professional 
  7. 请求体中包含了要发送给web服务器的数据信息,请问报文主体不用于get方法,而是用于post方法。post方法适用于客户端填写表单的场合。

HTTP响应报文

  1. HTTP 响应与 HTTP 请求相似,HTTP响应也由3个部分构成,分别是:状态行、响应头(Response Header)、响应正文。

  2. 状态行由协议版本、数字形式的状态代码、及相应的状态描述,各元素之间以空格分隔。

  3. 状态行,用来说明服务器响应客户端的状况,一般分为协议版本号,数字状态码,状态情况。

    常见响应头信息
    Connection: Keep-Alive
    Content-Encoding: gzip
    Content-Type: text/html;charset=utf-8
    Date: Mon, 13 Aug 2018 06:06:54 GMT
    Expires: Mon, 13 Aug 2018 06:06:54 GMT
  4. 空白行,通知客户端空行以下没有头部信息了。响应报文主体,主要包含了返回给客户端的数据,可以是文本,二进制(图片,视频)。

URl介绍

  1. url中文叫“统一资源标识符”,是一个用于标识某一互联网资源名称的字符串,在世界范围内标识定位某一个唯一信息资源。

  2. url主要用在各种www客户端和服务器程序上,url可以用一种统一的格式来描述各种信息资源,包括文件,服务器地址和目录等

  3. url组成协议 \\\\主机ip或域名\主机资源具体地址

静态网页资源

  1. 在网页设计中,纯HTMl格式的网页(包含图片,视频,JS,CSS等样式)通常被称作“静态网页”。

  2. 静态网页是相对于动态网页而言的,是指没有后台数据库,不包含程序,不可交互的网页。

  3. 开发人员写了什么,显示就是什么,一旦编写完成,就不会有任何改变。静态网页一般适用于更新较少的展示型网页,例如(酒水,家具,水果等宣传页),是很多中小网站的展示方式。

  4. 静态网页重要特性

    1. 每个页面有一个固定的url地址,url地址不含有问号"?"或"&"等符号

    2. 网页一经发布到服务器,网页内容是保存在服务器文件系统上的,每个网页都是独立的一个文件

    3. 网页内容固定不变,容易被搜索引擎收录(优点)

    4. 网页没有数据库支撑,在网站制作和维护上工作量很大(缺点)

    5. 网页的交互性很差,缺少程序的功能实现(缺点)

    6. 客户端解析网址时,由于不需要读取数据库,因此服务器端可以接受更高的并发访问。请求到来时,直接从磁盘上返回数据。(优点)

  5. 有关高并发架构思想:在高并发,高访问量的场景下做架构优化时,比较关键的就是把动态网页转化成静态网页,而不是直接请求数据库和动态服务器,并且可以吧静态内容推到缓存中,这样就提升用户体验,节约服务器压力成本。

动态网页资源

  1. 动态网页是和静态网页相对而言的,动态网页的url后缀一般是.asp .aspx .php .js .cgi 并且动态网页都有标志性的符号"? &",后端都有数据库的支持。

  2. 动态网页资源特点:

    1. 网页以数据库技术为支撑,大大降低网站维护的工作量。

    2. 动态网页技术的网站可以实现更多的功能,如用户注册,用户登录,投票,用户管理,博客管理等。

    3. 动态网页不是独立存在服务器上的网页文件,用户请求动态程序时,服务器解析程序并且可能读取数据库返回一个完整的网页内容。

    4. 搜索引擎(爬虫)一般不会抓取网址中的“?”后面的内容,因此企业都会做伪静态技术页面。

网站流量术语

  1. 网站统计一般以数值较大的IP,PV统计,比较好看

  2. IP:IP即Internet Protocol,这里是指独立ip数,不同的ip地址的计算机访问网站时被计算的总次数。独立ip数是网站流量的一个重要指标。一般相同ip地址的客户端访问网站页面一天内只会被计算一次。

  3. PV:pv(Page View)即是页面浏览量,不管客户端是不是相同,也不管ip是否相同,用户只要访问网站页面就会被计算PV,一次计算一个PV。pv的度量方法就是客户端从浏览器发出一个web请求(request),服务器接收请求返回一个页面给客户端,这样就产生一个pv。pv是衡量网站被访问的一个标准,但并不准确有多少人访问了网站。

  4. UV:UV即unique visitor,同一个客户端(pc或移动端)访问网站被计算为一个访客。一天内相同的客户端访问同一个网站只计一次uv,uv是以cookie等技术为统计依据,实际统计存在误差。一台计算机可能有多人使用,因此uv也不是最准确的。

  5. 并发数:并发数指系统同时能处理的请求数量,也反应了系统的负载能力。

  6. 响应时间:响应时间是指执行一个请求从开始到最后收到响应数据所花费的总体时间。

  7. QPS:Query Per Second每秒查询数,服务器在一秒内处理了多少个请求,显然数字越大代表服务器的负载越高,处理能力越强。

Web服务软件

  1. 互联网主流web服务软件:Apache、IIS、Nginx、Tengine、Tomcat、Lighthttpd。

  2. 主流web服务软件说明:Apache,中小型 web服务器的老大哥、Nginx ,大型网址web服务,其分支Tengine也在飞速发展、Lighthttpd nginx流行前的一款web软件。

  3. 提供动态服务的软件:php(fastcgi) 大中小的公司都会使用,动态网页语言php程序的解析容器,常配合apache解析动态程序、tomcat,中小企业动态web服务,互联网java容器主流、IIS 微软下的web服务软件。

nginx部署

  1. nginx是一个开源的,支持高性能,高并发的www服务和代理服务软件。它是一个俄罗斯人lgor sysoev开发的,作者将源代码开源出来供全球使用。

  2. nginx比它大哥apache性能改进许多,nginx占用的系统资源更少,支持更高的并发连接,有更高的访问效率。

  3. nginx不但是一个优秀的web服务软件,还可以作为反向代理,负载均衡,以及缓存服务使用。安装更为简单,方便,灵活。nginx可以说是非常nb了。

网站服务

  1. 想必我们大多数人都是通过访问网站而开始接触互联网的吧。我们平时访问的网站服务 就是 Web 网络服务,一般是指允许用户通过浏览器访问到互联网中各种资源的服务。

  2. Web 网络服务是一种被动访问的服务程序,即只有接收到互联网中其他主机发出的 请求后才会响应,最终用于提供服务程序的 Web 服务器会通过 HTTP(超文本传输协议)或 HTTPS(安全超文本传输协议)把请求的内容传送给用户。

  3. 目前能够提供 Web 网络服务的程序有 IIS、Nginx 和 Apache 等。其中,IIS(Internet Information Services,互联网信息服务)是 Windows 系统中默认的 Web 服务程序。

  4. 2004 年 10 月 4 日,为俄罗斯知名门户站点而开发的 Web 服务程序 Nginx 横空出世。 Nginx 程序作为一款轻量级的网站服务软件,因其稳定性和丰富的功能而快速占领服务器市 场,但 Nginx 最被认可的还当是系统资源消耗低且并发能力强,因此得到了国内诸如新浪、 网易、腾讯等门户站的青睐。

  5. web服务器和web框架的关系

    1. web服务器(nginx):接收HTTP请求(例如www.pythonav.cn/xiaocang.jpg)并返回数据

    2. web框架(django,flask):开发web应用程序,处理接收到的数据

  6. 面试回答nginx技巧:支持高并发,能支持几万并发连接;资源消耗少,在3万并发连接下开启10个nginx线程消耗的内存不到200M;可以做http反向代理和负载均衡;支持异步网络i/o事件模型epoll。

  7. Tengine是由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。

安装

  1. gcc 安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境,如果没有 gcc 环境,则需要安装:yum install gcc-c++

  2. PCRE(Perl Compatible Regular Expressions) 是一个Perl库,包括 perl 兼容的正则表达式库。nginx 的 http 模块使用 pcre 来解析正则表达式,所以需要在 linux 上安装 pcre 库,pcre-devel 是使用 pcre 开发的一个二次开发库。nginx也需要此库。命令:yum install -y pcre pcre-devel

  3. zlib 库提供了很多种压缩和解压缩的方式, nginx 使用 zlib 对 http 包的内容进行 gzip ,所以需要在 Centos 上安装 zlib 库yum install -y zlib zlib-devel

  4. OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及 SSL 协议,并提供丰富的应用程序供测试或其它目的使用。

  5. nginx 不仅支持 http 协议,还支持 https(即在ssl协议上传输http),所以需要在 Centos 安装 OpenSSL 库。

  6. 下载

    # 下载依赖	
    	yum install gcc patch libffi-devel python-devel  zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel openssl openssl-devel -y
    wget -c https://nginx.org/download/nginx-1.12.0.tar.gz				# 下载源码包
    tar -zxvf nginx-1.12.0.tar.gz										# 解压缩源码
    # 配置,编译安装  开启nginx状态监测功能
    	./configure --prefix=/opt/nginx1-12/ --with-http_ssl_module --with-http_stub_status_module 
    	make && make install 
    4.启动nginx,进入sbin目录,找到nginx启动命令
    cd sbin
    ./nginx 															# 启动
    ./nginx -s stop 													# 关闭
    ./nginx -s reload 													# 重新加载
  7. 安装完成后检测服务

    netstat -tunlp |grep 80
    curl -I 127.0.0.1
    # 如果访问不了,检查selinux,iptables
  8. 部署一个web站点

    1. nginx默认站点是Nginx目录下的html文件夹,这里可以从nginx.conf中查到

      location /{
                  root   html;  							# 这里是默认的站点html文件夹,也就是 /opt/nginx1-12/html/文件夹下的内容
                  index  index.html index.htm; 			# 站点首页文件名是index.html
              }
    2. 如果要部署网站业务数据,只需要把开发好的程序全放到/opt/nginx1-12/html/目录下即可。

    3. 因此只需要通过域名/资源,即可访问http://www.pyyuc.cn/man.jpg

  9. Nginx的目录结构:conf 存放nginx所有配置文件的目录,主要nginx.conf、html 存放nginx默认站点的目录,如index.html、error.html等、logs 存放nginx默认日志的目录,如error.log access.log、sbin 存放nginx主命令的目录,sbin/nginx。

Nginx主配置文件解析

  1. Nginx主配置文件/etc/nginx/nginx.conf是一个纯文本类型的文件,整个配置文件是以区块的形式组织的。一般,每个区块以一对大括号{}来表示开始与结束。

    ######Nginx配置文件nginx.conf中文详解#####
    user www www;											# 定义Nginx运行的用户和用户组
    worker_processes 8;										# #nginx进程数,建议设置为等于CPU总核心数。
    error_log /usr/local/nginx/logs/error.log info;			# 全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
    pid /usr/local/nginx/logs/nginx.pid;					# 进程pid文件
    # 指定进程可以打开的最大描述符:数目
    # 工作模式与连接数上限
    # 这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致。
    # 现在在linux 2.6内核下开启文件打开数为65535,worker_rlimit_nofile就相应应该填写65535。
    # 这是因为nginx调度时分配请求到进程并不是那么的均衡,所以假如填写10240,总并发量达到3-4万时就有进程可能超过10240了,这时会返回502错误。
    worker_rlimit_nofile 65535;
    events
    {
        # 参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型
        # 是Linux 2.6以上版本内核中的高性能网络I/O模型,linux建议epoll,如果跑在FreeBSD上面,就用kqueue模型。
        # 补充说明:
        # 与apache相类,nginx针对不同的操作系统,有不同的事件模型
        # A)标准事件模型
        # Select、poll属于标准事件模型,如果当前系统不存在更有效的方法,nginx会选择select或poll
        # B)高效事件模型
        # Kqueue:使用于FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X.使用双处理器的MacOS X系统使用kqueue可能会造成内核崩溃。
        # Epoll:使用于Linux内核2.6版本及以后的系统。
        # /dev/poll:使用于Solaris 7 11/99+,HP/UX 11.22+ (eventport),IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+。
        # Eventport:使用于Solaris 10。 为了防止出现内核崩溃的问题, 有必要安装安全补丁。
        use epoll;
    
        # 单个进程最大连接数(最大连接数=连接数*进程数)
        # 根据硬件调整,和前面工作进程配合起来用,尽量大,但是别把cpu跑到100%就行。每个进程允许的最多连接数,理论上每台nginx服务器的最大连接数为。
        worker_connections 65535;
    
        # keepalive超时时间。
        keepalive_timeout 60;
    
        # 客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。
        # 分页大小可以用命令getconf PAGESIZE 取得。
        # [root@web001 ~]# getconf PAGESIZE
        # 4096
        # 但也有client_header_buffer_size超过4k的情况,但是client_header_buffer_size该值必须设置为“系统分页大小”的整倍数。
        client_header_buffer_size 4k;
    
        # 默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。
        open_file_cache max=65535 inactive=60s;
    
        # 这个是指多长时间检查一次缓存的有效信息。
        # 语法:open_file_cache_valid time 默认值:open_file_cache_valid 60 使用字段:http, server, location 这个指令指定了何时需要检查open_file_cache中缓存项目的有效信息.
        open_file_cache_valid 80s;
    
        # open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive时间内一次没被使用,它将被移除。
        # 语法:open_file_cache_min_uses number 默认值:open_file_cache_min_uses 1 使用字段:http, server, location  这个指令指定了在open_file_cache指令无效的参数中一定的时间范围内可以使用的最小文件数,如果使用更大的值,文件描述符在cache中总是打开状态.
        open_file_cache_min_uses 1;
        
        # 语法:open_file_cache_errors on | off 默认值:open_file_cache_errors off 使用字段:http, server, location 这个指令指定是否在搜索一个文件是记录cache错误.
        open_file_cache_errors on;
    }
     
     
     
    # 设定http服务器,利用它的反向代理功能提供负载均衡支持
    http
    {
        # 文件扩展名与文件类型映射表
        include mime.types;
    
        # 默认文件类型
        default_type application/octet-stream;
    
        # 默认编码
        # charset utf-8;
    
        # 服务器名字的hash表大小
        # 保存服务器名字的hash表是由指令server_names_hash_max_size 和server_names_hash_bucket_size所控制的。参数hash bucket size总是等于hash表的大小,并且是一路处理器缓存大小的倍数。在减少了在内存中的存取次数后,使在处理器中加速查找hash表键值成为可能。如果hash bucket size等于一路处理器缓存的大小,那么在查找键的时候,最坏的情况下在内存中查找的次数为2。第一次是确定存储单元的地址,第二次是在存储单元中查找键 值。因此,如果Nginx给出需要增大hash max size 或 hash bucket size的提示,那么首要的是增大前一个参数的大小.
        server_names_hash_bucket_size 128;
        # 客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求的头部大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。
        client_header_buffer_size 32k;
        # 客户请求头缓冲大小。nginx默认会用client_header_buffer_size这个buffer来读取header值,如果header过大,它会使用large_client_header_buffers来读取。
        large_client_header_buffers 4 64k;
        # 设定通过nginx上传文件的大小
        client_max_body_size 8m;
        # 开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
        # sendfile指令指定 nginx 是否调用sendfile 函数(zero copy 方式)来输出文件,对于普通应用,必须设为on。如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络IO处理速度,降低系统uptime。
        sendfile on;
        # 开启目录列表访问,合适下载服务器,默认关闭。
        autoindex on;
        # 此选项允许或禁止使用socke的TCP_CORK的选项,此选项仅在使用sendfile的时候使用
        tcp_nopush on;
        tcp_nodelay on;
        # 长连接超时时间,单位是秒
        keepalive_timeout 120;
        # FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
        fastcgi_buffer_size 64k;
        fastcgi_buffers 4 64k;
        fastcgi_busy_buffers_size 128k;
        fastcgi_temp_file_write_size 128k;
    
        # gzip模块设置
        gzip on; # 开启gzip压缩输出
        gzip_min_length 1k;    								# 最小压缩文件大小
        gzip_buffers 4 16k;    								# 压缩缓冲区
        gzip_http_version 1.0;    							# 压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
        gzip_comp_level 2;    								# 压缩等级
        gzip_types text/plain application/x-javascript text/css application/xml;    # 压缩类型,默认就已经包含textml,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
        gzip_vary on;
    
        # 开启限制IP连接数的时候需要使用
        # limit_zone crawler $binary_remote_addr 10m;
    
    
    
        # 负载均衡配置
        upstream jh.w3cschool.cn {
         
            # upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
            server 192.168.80.121:80 weight=3;
            server 192.168.80.122:80 weight=2;
            server 192.168.80.123:80 weight=3;
    
            # nginx的upstream目前支持4种方式的分配
            # 1、轮询(默认)
            # 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
            # 2、weight
            # 指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
            # 例如:
            # upstream bakend {
            #    server 192.168.0.14 weight=10;
            #    server 192.168.0.15 weight=10;
            #}
            #2、ip_hash
            #每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
            #例如:
            #upstream bakend {
            #    ip_hash;
            #    server 192.168.0.14:88;
            #    server 192.168.0.15:80;
            #}
            #3、fair(第三方)
            #按后端服务器的响应时间来分配请求,响应时间短的优先分配。
            #upstream backend {
            #    server server1;
            #    server server2;
            #    fair;
            #}
            #4、url_hash(第三方)
            #按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
            #例:在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
            #upstream backend {
            #    server squid1:3128;
            #    server squid2:3128;
            #    hash $request_uri;
            #    hash_method crc32;
            #}
    
            #tips:
            #upstream bakend{#定义负载均衡设备的Ip及设备状态}{
            #    ip_hash;
            #    server 127.0.0.1:9090 down;
            #    server 127.0.0.1:8080 weight=2;
            #    server 127.0.0.1:6060;
            #    server 127.0.0.1:7070 backup;
            #}
            #在需要使用负载均衡的server中增加 proxy_pass http://bakend/;
    
            #每个设备的状态设置为:
            #1.down表示单前的server暂时不参与负载
            #2.weight为weight越大,负载的权重就越大。
            #3.max_fails:允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream模块定义的错误
            #4.fail_timeout:max_fails次失败后,暂停的时间。
            #5.backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
    
            #nginx支持同时设置多组的负载均衡,用来给不用的server来使用。
            #client_body_in_file_only设置为On 可以讲client post过来的数据记录到文件中用来做debug
            #client_body_temp_path设置记录文件的目录 可以设置最多3层目录
            #location对URL进行匹配.可以进行重定向或者进行新的代理 负载均衡
        }
         
         
         
        #虚拟主机的配置
        server
        {
            #监听端口
            listen 80;
    
            #域名可以有多个,用空格隔开
            server_name www.w3cschool.cn w3cschool.cn;
            index index.html index.htm index.php;
            root /data/www/w3cschool;
    
            #对******进行负载均衡
            location ~ .*.(php|php5)?$
            {
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index index.php;
                include fastcgi.conf;
            }
             
            #图片缓存时间设置
            location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
            {
                expires 10d;
            }
             
            #JS和CSS缓存时间设置
            location ~ .*.(js|css)?$
            {
                expires 1h;
            }
             
            #日志格式设定
            #$remote_addr与$http_x_forwarded_for用以记录客户端的ip地址;
            #$remote_user:用来记录客户端用户名称;
            #$time_local: 用来记录访问时间与时区;
            #$request: 用来记录请求的url与http协议;
            #$status: 用来记录请求状态;成功是200,
            #$body_bytes_sent :记录发送给客户端文件主体内容大小;
            #$http_referer:用来记录从那个页面链接访问过来的;
            #$http_user_agent:记录客户浏览器的相关信息;
            #通常web服务器放在反向代理的后面,这样就不能获取到客户的IP地址了,通过$remote_add拿到的IP地址是反向代理服务器的iP地址。反向代理服务器在转发请求的http头信息中,可以增加x_forwarded_for信息,用以记录原有客户端的IP地址和原来客户端的请求的服务器地址。
            log_format access '$remote_addr - $remote_user [$time_local] "$request" '
            '$status $body_bytes_sent "$http_referer" '
            '"$http_user_agent" $http_x_forwarded_for';
             
            #定义本虚拟主机的访问日志
            access_log  /usr/local/nginx/logs/host.access.log  main;
            access_log  /usr/local/nginx/logs/host.access.404.log  log404;
             
            #对 "/" 启用反向代理
            location / {
                proxy_pass http://127.0.0.1:88;
                proxy_redirect off;
                proxy_set_header X-Real-IP $remote_addr;
                 
                #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                 
                #以下是一些反向代理的配置,可选。
                proxy_set_header Host $host;
    
                #允许客户端请求的最大单文件字节数
                client_max_body_size 10m;
    
                #缓冲区代理缓冲用户端请求的最大字节数,
                #如果把它设置为比较大的数值,例如256k,那么,无论使用firefox还是IE浏览器,来提交任意小于256k的图片,都很正常。如果注释该指令,使用默认的client_body_buffer_size设置,也就是操作系统页面大小的两倍,8k或者16k,问题就出现了。
                #无论使用firefox4.0还是IE8.0,提交一个比较大,200k左右的图片,都返回500 Internal Server Error错误
                client_body_buffer_size 128k;
    
                #表示使nginx阻止HTTP应答代码为400或者更高的应答。
                proxy_intercept_errors on;
    
                #后端服务器连接的超时时间_发起握手等候响应超时时间
                #nginx跟后端服务器连接超时时间(代理连接超时)
                proxy_connect_timeout 90;
    
                #后端服务器数据回传时间(代理发送超时)
                #后端服务器数据回传时间_就是在规定时间之内后端服务器必须传完所有的数据
                proxy_send_timeout 90;
    
                #连接成功后,后端服务器响应时间(代理接收超时)
                #连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间)
                proxy_read_timeout 90;
    
                #设置代理服务器(nginx)保存用户头信息的缓冲区大小
                #设置从被代理服务器读取的第一部分应答的缓冲区大小,通常情况下这部分应答中包含一个小的应答头,默认情况下这个值的大小为指令proxy_buffers中指定的一个缓冲区的大小,不过可以将其设置为更小
                proxy_buffer_size 4k;
    
                #proxy_buffers缓冲区,网页平均在32k以下的设置
                #设置用于读取应答(来自被代理服务器)的缓冲区数目和大小,默认情况也为分页大小,根据操作系统的不同可能是4k或者8k
                proxy_buffers 4 32k;
    
                #高负荷下缓冲大小(proxy_buffers*2)
                proxy_busy_buffers_size 64k;
    
                #设置在写入proxy_temp_path时数据的大小,预防一个工作进程在传递文件时阻塞太长
                #设定缓存文件夹大小,大于这个值,将从upstream服务器传
                proxy_temp_file_write_size 64k;
            }
             
             
            #设定查看Nginx状态的地址
            location /NginxStatus {
                stub_status on;
                access_log on;
                auth_basic "NginxStatus";
                auth_basic_user_file confpasswd;
                #htpasswd文件的内容可以用apache提供的htpasswd工具来产生。
            }
             
            #本地动静分离反向代理配置
            #所有jsp的页面均交由tomcat或resin处理
            location ~ .(jsp|jspx|do)?$ {
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://127.0.0.1:8080;
            }
             
            #所有静态文件由nginx直接读取不经过tomcat或resin
            location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|
            pdf|xls|mp3|wma)$
            {
                expires 15d; 
            }
             
            location ~ .*.(js|css)?$
            {
                expires 1h;
            }
        }
    }
    ######Nginx配置文件nginx.conf中文详解#####
  2. CoreModule核心模块

    user www;                       #Nginx进程所使用的用户
    worker_processes 1;             #Nginx运行的work进程数量(建议与CPU数量一致或auto)
    error_log /log/nginx/error.log  #Nginx错误日志存放路径
    pid /var/run/nginx.pid          #Nginx服务运行后产生的pid进程号
  3. events事件模块

    events {            
        worker_connections  # 每个worker进程支持的最大连接数
        use epool;          # 事件驱动模型, epoll默认
    }
  4. http内核模块

    //公共的配置定义在http{}
    http {  //http层开始
    ...    
        //使用Server配置网站, 每个Server{}代表一个网站(简称虚拟主机)
        'server' {
            listen       80;        //监听端口, 默认80
            server_name  localhost; //提供服务的域名或主机名
            access_log host.access.log  //访问日志
            //控制网站访问路径
            'location' / {
                root   /usr/share/nginx/html;   //存放网站代码路径
                index  index.html index.htm;    //服务器返回的默认页面文件
            }
            //指定错误代码, 统一定义错误页面, 错误代码重定向到新的Locaiton
            error_page   500 502 503 504  /50x.html;
        }
        ...
        //第二个虚拟主机配置
        'server' {
        ...
        }
        
        include /etc/nginx/conf.d/*.conf;  //包含/etc/nginx/conf.d/目录下所有以.conf结尾的文件
    
    }   //http层结束

Nginx虚拟主机

  1. 如果每台linux服务器只运行了一个小网站,那么人气低,流量小的草根站长需要承担高额的服务器租赁费,也造成了硬件资源浪费。

  2. 虚拟主机就是将一台服务器分割成多个“虚拟服务器”,每个站点使用各自的硬盘空间,由于省资源,省钱,众多网站都使用虚拟主机来部署网站。

  3. 虚拟主机的概念就是在web服务里的一个独立的网站站点,这个站点对应独立的域名(IP),具有独立的程序和资源目录,可以独立的对外提供服务。

  4. 这个独立的站点配置是在nginx.conf中使用server{}代码块标签来表示一个虚拟主机。

  5. Nginx支持多个server{}标签,即支持多个虚拟主机站点。

  6. 虚拟主机类型:基于域名的虚拟主机,通过不同的域名区分不同的虚拟主机,是企业应用最广的虚拟主机。基于端口的虚拟主机通过不同的端口来区分不同的虚拟主机,一般用作企业内部网站,不对外直接提供服务的后台,例如www.pythonav.cn:9000基于IP的虚拟主机通过不同的IP区分不同的虚拟主机,此类比较少见,一般业务需要多IP的常见都会在负载均衡中绑定VIP。

  7. Nginx状态信息(status)配置

    Nginx状态信息(status)配置及信息详解
        nginx与php-fpm一样内建了一个状态页,对于想了解nginx的状态以及监控nginx非常有帮助。为了后续的zabbix监控,我们需要先了解一下nginx的状态页。
    
    Nginx状态信息(status)介绍
        Nginx软件在编译时又一个with-http_stub_status_module模块,这个模块功能是记录Nginx的基本访问状态信息,让使用者了解Nginx的工作状态。要想使用状态模块,在编译时必须增加--with-http_stub_status_module参数。
  8. 监测你的nginx是否安装了status模块

    [root@master conf]# /opt/nginx/sbin/nginx -V
    nginx version: nginx/1.12.0
    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
    configure arguments: --prefix=/opt/nginx/ --with-http_stub_status_module
  9. 启动status状态功能,修改配置文件

    #在访问ip/status的时候,进入状态功能        location /status {        #开启nginx状态功能
                 stub_status on;
    }   
  10. 平滑重启nginx./sbin/nginx -s reload

  11. 通过ab压测命令检测yum -y install httpd-tools

    1. -n requests #执行的请求数,即一共发起多少请求。

    2. -c concurrency #请求并发数。

    3. -k #启用HTTP KeepAlive功能,即在一个HTTP会话中执行多个请求。

    4. ab -kc 1000 -n 100000 http://192.168.119.10/

  12. 检查nginx语法重新加载nginx../sbin/nginx -t

  13. 平滑重启nginx../sbin/nginx -s reload

  14. 检查nginx端口,进程,访问pyyuc虚拟站点

    netstat -tunlp|grep nginx
    ps -ef|grep nginx
    
    # 我这里是有dns解析,没有的话则需要/etc/hosts解析
    # 成功配置了pyyuc虚拟主机站点
    curl www.pyyuc.cn
    <meta charset=utf8>我是pyyuc站点

Nginx其他

配置多个域名的虚拟主机

  1. 其实就是新增一个server{}虚拟主机

    egrep -v '#|^$' /opt/nginx1-12/conf/nginx.conf
    worker_processes  1;
    events {
        worker_connections  1024;
    }
    http {
        include       mime.types;
        default_type  application/octet-stream;
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
        access_log  logs/access.log  main;
        sendfile        on;
        keepalive_timeout  65;
        server {
            listen       80;
            server_name  www.pyyuc.cn;
            location /{
                root   html/pyyuc;
                index  index.html index.htm;
            }
    }
        server {
            listen       80;
            server_name  www.pythonav.cn;
            location /{
                root   html/pythonav;
                index  index.html index.htm;
            }
    }
        }
  2. 创建pythonav虚拟主机站点的目录和文件

    mkdir -p /opt/nginx1-12/html/pythonav
    echo "<meta charset=utf8>我是pythonav,未成年禁止入内"> /opt/nginx1-12/html/pythonav/index.html
    ./sbin/nginx -t
        nginx: the configuration file /opt/nginx1-12/conf/nginx.conf syntax is ok
        nginx: configuration file /opt/nginx1-12/conf/nginx.conf test is successful
    ./sbin/nginx -s reload

nginx访问日志(access_log)

  1. 日志功能对每个用户访问网站的日志信息记录到指定的日志文件里,开发运维人员可以分析用户的浏览器行为,此功能由ngx_http_log_module模块负责,官网地址是:http://nginx.org/en/docs/http/ngx_http_log_module.html

  2. 控制日志的参数

    log_format    记录日志的格式,可定义多种格式
    accsss_log    指定日志文件的路径以及格式
    
      log_format main '$remote_addr - $remote_user [$time_local] "$request" '
      '$status $body_bytes_sent "$http_referer" '
      '"$http_user_agent" "$http_x_forwarded_for"';
  3. 对应参数解析

    $remote_addr    记录客户端ip
    $remote_user    远程用户,没有就是 “-”
    $time_local    对应[14/Aug/2018:18:46:52 +0800]
    $request     对应请求信息"GET /favicon.ico HTTP/1.1"
    $status      状态码
    $body_bytes_sent  571字节 请求体的大小
    $http_referer  对应“-”  由于是直接输入浏览器就是 -
    $http_user_agent  客户端身份信息
    $http_x_forwarded_for  记录客户端的来源真实ip 97.64.34.118
  4. 日志效果如下

    66.102.6.6 - - [14/Aug/2018:18:46:52 +0800] "GET /favicon.ico HTTP/1.1" 404 571 "-"
    
     "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36 Google Favicon" "97.64.34.118"
  5. nginx.conf默认配置

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  logs/access.log  main;
  6. 日志格式配置定义:log_format是日志关键字参数,不能变,main是日志格式指定的标签,记录日志时通过main标签选择指定的格式。

  7. nginx限制网站来源IP访问,如果哪天发现你的nginx很慢,或者检查access.log时候,有一个some body疯狂请求你的nginx server,那么可以禁止这个IP访问。

    限制ip或ip段访问禁止访问/av/底下的资源
    location /av {
    deny 122.71.240.254;
    #alias /opt/nginx1-12/html/av;
    allow 10.1.1.0/16;  
    }

Nginx错误页面优化

  1. 在网站运行过程中,可能因为页面不存在等原因,导致网站无法正常响应请求,此时web服务会返回系统的错误码,但是默认的错误页面很不友好。

  2. 因此我们可以将404,403等页面的错误信息重定向到网站首页或者其他指定的页面,提升用户访问体验。

    server {
            listen       80;
            server_name  www.pythonav.cn;
            root html/pythonav;
            location /{
                index  index.html index.htm;
            }      #在pythonav路径下的40x.html错误页面
            error_page 400 403 404 405 /40x.html;
            }
  3. 40x.html

    <img style='width:100%;height:100%;' src=https://pic1.zhimg.com/80/v2-77a9281a2bebc7a2ea5e02577af266a8_hd.png>
  4. 此时访问www.pythonav.cn/asdasd错误页面已经优化了

Nginx代理

  1. 正向代理,也就是传说中的代理,他的工作原理就像一个跳板(VPN),简单的说:我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器呢,他能访问那个我不能访问的网站,于是我先连上代理服务器,告诉他我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我。

  2. 反向代理,对于客户端而言,代理服务器就像是原始服务器。

  3. nginx实现负载均衡的组件

ngx_http_proxy_module    proxy代理模块,用于把请求抛给服务器节点或者upstream服务器池

实现一个简单的反向代理

  1. 机器准备,两台服务器

    master  192.168.11.63  主负载
    slave   192.168.11.64  web1
  2. 主负载均衡节点的配置文件nginx.conf

    worker_processes  1;
    error_log  logs/error.log;
    pid        logs/nginx.pid;
    events {
        worker_connections  1024;
    }
    http {
        include       mime.types;
        default_type  application/octet-stream;
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
        access_log  logs/access.log  main;
        sendfile        on;
        keepalive_timeout  65;
            upstream slave_pools{
        server 192.168.11.64:80 weight=1;
    }
        server {
            listen       80;
            server_name  localhost;
            location / {
            proxy_pass  http://slave_pools;
                root   html;
                index  index.html index.htm;
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
    }
  3. 检查语法并启动nginx

    [root@master 192.168.11.63 /opt/nginx1-12]$/opt/nginx1-12/sbin/nginx -t
    nginx: the configuration file /opt/nginx1-12/conf/nginx.conf syntax is ok
    nginx: configuration file /opt/nginx1-12/conf/nginx.conf test is successful
    #启动nginx
    [root@master 192.168.11.63 /opt/nginx1-12]$/opt/nginx1-12/sbin/nginx
    #检查端口
    [root@master 192.168.11.63 /opt/nginx1-12]$netstat -tunlp|grep nginx
    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      8921/nginx: master
  4. 此时访问master的服务器192.168.11.63:80地址,已经会将请求转发给slave的80端口,除了页面效果的展示以外,还可以通过log(access.log)查看代理效果

nginx语法之location详解

  1. Location语法优先级排列

    匹配符 匹配规则 优先级
    =    精确匹配    1
    ^~    以某个字符串开头    2
    ~    区分大小写的正则匹配    3
    ~*    不区分大小写的正则匹配    4
    !~    区分大小写不匹配的正则    5
    !~*    不区分大小写不匹配的正则    6
    /    通用匹配,任何请求都会匹配到    7
  2. nginx.conf配置文件实例

    server {
        listen 80;
        server_name pythonav.cn;
    
        #优先级1,精确匹配,根路径
        location =/ {
            return 400;
        }
    
        #优先级2,以某个字符串开头,以av开头的,优先匹配这里,区分大小写
        location ^~ /av {
           root /data/av/;
        }
    
        #优先级3,区分大小写的正则匹配,匹配/media*****路径
        location ~ /media {
              alias /data/static/;
        }
    
        #优先级4 ,不区分大小写的正则匹配,所有的****.jpg|gif|png 都走这里
        location ~* .*\.(jpg|gif|png|js|css)$ {
           root  /data/av/;
            }
    
        #优先7,通用匹配
        location / {
            return 403;
        }
    }
  3. nginx语法之root和alias区别实战

    nginx指定文件路径有root和alias两种方法
    区别在方法和作用域:
    
    方法:
    
    root
    语法  root  路径;
    默认值 root   html;
    配置块  http{}   server {}   location{}
    
    alias
    语法: alias  路径
    配置块  location{}
    
    
    root和alias区别在nginx如何解释location后面的url,这会使得两者分别以不同的方式讲请求映射到服务器文件上
    
    root参数是root路径+location位置
    
    root实例:
    
        location ^~ /av {
            root /data/av;   注意这里可有可无结尾的   /
        }
    请求url是pythonav.cn/av/index.html时
    web服务器会返回服务器上的/data/av/av/index.html
    
    root实例2:
    location ~* .*\.(jpg|gif|png|js|css)$ {
           root  /data/av/;
    }
    
    请求url是pythonav.cn/girl.gif时
    web服务器会返回服务器上的/data/static/girl.gif
    
    
    
    
    alias实例:
    alias参数是使用alias路径替换location路径
    alias是一个目录的别名
    注意alias必须有 "/"  结束!
    alias只能位于location块中
    
    
    请求url是pythonav.cn/av/index.html时
    web服务器会返回服务器上的/data/static/index.html
    
    location ^~ /av {
        alias /data/static/;
    }

Keepalived高可用软件

  1. 什么是keepalived:Keepalived是一个用C语言编写的路由软件。该项目的主要目标是为Linux系统和基于Linux的基础架构提供简单而强大的负载均衡和高可用性设施。 还可以作为其他服务(nginx,mysql)的高可用软件keepalived主要通过vrrp协议实现高可用功能。vrrp叫(virtual router redundancy protocol)虚拟路由器冗余协议,目的为了解决单点故障问题,他可以保证个别节点宕机时。整个网络可以不间断的运行。

  2. 高可用故障切换原理

    1. 在keepalived工作时,主master节点会不断的向备节点发送心跳消息,告诉备节点自己还活着,当master节点故障时,就无法发送心跳消息,备节点就无法检测到来自master的心跳了,于是调用自身的接管程序,接管master节点的ip资源以及服务,当master主节点恢复时,备backup节点又会释放接管的ip资源和服务,回复到原本的备节点角色。

  3. 硬件环境准备

    实验环境应该最好是4台虚拟机,环境有限因此用2台机器
    master
    slave
  4. centos系统和nginx代理环境

docker入门

  1. Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护。

  2. Docker 使用 Google 公司推出的 Go 语言 进行开发实现。

  3. docker是linux容器的一种封装,提供简单易用的容器使用接口。它是最流行的Linux容器解决方案。

  4. docker的接口相当简单,用户可以方便的创建、销毁容器。

  5. docker将应用程序与程序的依赖,打包在一个文件里面。运行这个文件就会生成一个虚拟容器。

  6. 程序运行在虚拟容器里,如同在真实物理机上运行一样,有了docker,就不用担心环境问题了。

  7. ocke用场景:web应用的自动化打包和发布,自动化测试和持续集成、发布,在服务型环境中部署和调整数据库或其他应用。

  8. 但是虚拟化也是有局限性的,每一个虚拟机都是一个完整的操作系统,要分配系统资源,虚拟机多道一定程度时,操作系统本身资源也就消耗殆尽,或者说必须扩容

  9. docker与虚拟机的区别:

    特性 容器 虚拟机
    启动 秒级 分钟级
    硬盘使用 一般为 MB 一般为 GB
    性能 接近原生
    系统支持量 单机支持上千个容器 一般几十个
  10. 环境配置的难题:让开发人员最头疼的麻烦事之一就是环境配置了,每台计算机的环境都不相同,应该如何确保自己的程序换一台机器能运行起来呢?

  11. 用户必须确保的是:操作系统的相同、各种平台库和组件的安装、例如python依赖包,环境变量等。

  12. 解决方案,虚拟机

    1. 虚拟机也可以制作模板,基于模板创建虚拟机,保证环境问题一致。虚拟机(virtual machine)就是带环境安装的一种解决方案。它可以在一种操作系统里面运行另一种操作系统,比如在 Windows 系统里面运行 Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。

    2. 虽然用户可以通过虚拟机还原软件的原始环境。但是,这个方案有几个缺点。

    3. 资源占用多:虚拟机会独占一部分内存和硬盘空间。它运行的时候,其他程序就不能使用这些资源了。哪怕虚拟机里面的应用程序,真正使用的内存只有 1MB,虚拟机依然需要几百 MB 的内存才能运行。

    4. 冗余步骤多:虚拟机是完整的操作系统,一些系统级别的操作步骤,往往无法跳过,比如用户登录。

    5. 启动慢:启动操作系统需要多久,启动虚拟机就需要多久。可能要等几分钟,应用程序才能真正运行。

  13. 解决方案,Linux容器

    1. 现在:自从用上docker容器后,可以实现开发、测试和生产环境的统一化和标准化。

    2. 镜像作为标准的交付件,可在开发、测试和生产环境上以容器来运行,最终实现三套环境上的应用以及运行所依赖内容的完全一致。

    3. 由于虚拟机的诸多问题,Linux发展出了另一种虚拟化技术:Linux容器(Linux Containers,缩写LXC)。

    4. Linux容器不是模拟一个完整的操作系统,而是对进程进行隔离。在正常进程的外面套了一个保护层,对于容器里面进程来说,它接触的资源都是虚拟的,从而实现和底层系统的隔离。

    5. 启动快:容器里面的应用,直接就是底层系统的一个进程,而不是虚拟机内部的进程。所以,启动容器相当于启动本机的一个进程,而不是启动一个操作系统,速度就快很多。

    6. 资源占用少:容器只占用需要的资源,不占用那些没有用到的资源;虚拟机由于是完整的操作系统,不可避免要占用所有资源。另外,多个容器可以共享资源,虚拟机都是独享资源。

    7. 体积小:容器只要包含用到的组件即可,而虚拟机是整个操作系统的打包,所以容器文件比虚拟机文件要小很多。

  14. docker容器的优势

    1. 更高效的利用系统资源:由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统 资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传 统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运 行更多数量的应用。

    2. 更快速的启动时间:传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接 运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启 动时间。大大的节约了开发、测试、部署的时间。

    3. 一致的运行环境:开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环 境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内 核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 “这段代码 在我机器上没问题啊” 这类问题。

    4. 持续交付和部署:对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意 地方正常运行。

    5. 使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员 可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系 统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) 系统进行自动部署。而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环 境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。

    6. 更轻松的迁移:由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在 很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运 行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一 个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。

  15. docker三大概念:镜像 image、容器 container、仓库 repositorydocker整个生命周期就是这三个概念。

    1. docker镜像,Docker镜像就是一个只读的模板。镜像可以用来创建Docker容器。Docker提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。

    2. image的分层存储,因为镜像包含完整的root文件系统,体积是非常庞大的,因此docker在设计时按照Union FS的技术,将其设计为分层存储的架构。镜像不是ISO那种完整的打包文件,镜像只是一个虚拟的概念,他不是一个完整的文件,而是由一组文件组成,或者多组文件系统联合组成。

    3. docker容器(container),image和container的关系,就像面向对象程序设计中的 类和实例一样,镜像是静态的定义(class),容器是镜像运行时的实体(object)。

      1. Docker利用容器来运行应用。容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。

      2. 每个容器都是相互隔离的,保证安全的平台。可以把容器看做是一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

      3. 注意:镜像是只读的,容器在启动的时候创建一层可写层作为最上层。

    4. docker仓库(repository)

      1. 仓库是集中存放镜像文件的场所。有时候把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。

      2. 仓库分为公开仓库(Public)和私有仓库(Private)两种形式。

      3. 最大的公开仓库是Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括Docker Pool等,可以提供大陆用户更稳定快读的访问。

      4. 当用户创建了自己的镜像之后就可以使用push命令将它上传到公有或者私有仓库,这样下载在另外一台机器上使用这个镜像时候,只需需要从仓库上pull下来就可以了。

      5. 注意:Docker仓库的概念跟Git类似,注册服务器可以理解为GitHub这样的托管服务。

  16. docker Registry

    1. Docker Registry 公开服务是开放给用户使用、允许用户管理镜像的 Registry 服 务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务 供用户管理私有镜像。

    2. 最常使用的 Registry 公开服务是官方的 Docker Hub,这也是默认的 Registry,并 拥有大量的高质量的官方镜像。除此以外,还有 CoreOS 的 Quay.io,CoreOS 相 关的镜像存储在这里;Google 的 Google Container Registry,Kubernetes 的镜像 使用的就是这个服务。

    3. 由于某些原因,在国内访问这些服务可能会比较慢。国内的一些云服务商提供了针 对 Docker Hub 的镜像服务(Registry Mirror),这些镜像服务被称为加速器。常见 的有 阿里云加速器、DaoCloud 加速器、灵雀云加速器等。使用加速器会直接从国内的地址下载 Docker Hub 的镜像,比直接从官方网站下载速度会提高很多。在后 面的章节中会有进一步如何配置加速器的讲解。

    4. 国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 时速云镜像仓 库、网易云镜像服务、DaoCloud 镜像市场、阿里云镜像库等。

安装docker

  1. 安装步骤

    1.卸载旧版本
    sudo yum remove docker \
                      docker-client \
                      docker-client-latest \
                      docker-common \
                      docker-latest \
                      docker-latest-logrotate \
                      docker-logrotate \
                      docker-selinux \
                      docker-engine-selinux \
                      docker-engine
    
    2.设置存储库
    sudo yum install -y yum-utils \
      device-mapper-persistent-data \
      lvm2
    
    sudo yum-config-manager \
        --add-repo \
        https://download.docker.com/linux/centos/docker-ce.repo
    
    3.安装docker社区版
    sudo yum install docker-ce
    4.启动关闭docker
    systemctl start docker
  2. docker版本:Docker 是一个开源的商业产品,有两个版本:社区版(Community Edition,缩写为 CE)和企业版(Enterprise Edition,缩写为 EE)。企业版包含了一些收费服务,个人开发者一般用不到。本文的介绍都针对社区版。

  3. 系统环境准备:docker最低支持centos7且在64位平台上,内核版本在3.10以上uname -r

  4. Docker镜像加速器

    https://www.daocloud.io/mirror#accelerator-doc
    #一条命令加速
    curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://95822026.m.daocloud.io

使用docker

  1. docker基础命令注释

    [root@docker ~]# docker --help
    
    Usage:
    docker [OPTIONS] COMMAND [arg...]
    
           docker daemon [ --help | ... ]
    
           docker [ --help | -v | --version ]
    
    A
    self-sufficient runtime for containers.
    
    Options:
    
      --config=~/.docker              Location of client config files  #客户端配置文件的位置
    
      -D, --debug=false               Enable debug mode  #启用Debug调试模式
    
      -H, --host=[]                   Daemon socket(s) to connect to  #守护进程的套接字(Socket)连接
    
      -h, --help=false                Print usage  #打印使用
    
      -l, --log-level=info            Set the logging level  #设置日志级别
    
      --tls=false                     Use TLS; implied by--tlsverify  #
    
      --tlscacert=~/.docker/ca.pem    Trust certs signed only by this CA  #信任证书签名CA
    
      --tlscert=~/.docker/cert.pem    Path to TLS certificate file  #TLS证书文件路径
    
      --tlskey=~/.docker/key.pem      Path to TLS key file  #TLS密钥文件路径
    
      --tlsverify=false               Use TLS and verify the remote  #使用TLS验证远程
    
      -v, --version=false             Print version information and quit  #打印版本信息并退出
    
    Commands:
    
        attach    Attach to a running container  #当前shell下attach连接指定运行镜像
    
        build     Build an image from a Dockerfile  #通过Dockerfile定制镜像
    
        commit    Create a new image from a container's changes  #提交当前容器为新的镜像
    
        cp    Copy files/folders from a container to a HOSTDIR or to STDOUT  #从容器中拷贝指定文件或者目录到宿主机中
    
        create    Create a new container  #创建一个新的容器,同run 但不启动容器
    
        diff    Inspect changes on a container's filesystem  #查看docker容器变化
    
        events    Get real time events from the server#从docker服务获取容器实时事件
    
        exec    Run a command in a running container#在已存在的容器上运行命令
    
        export    Export a container's filesystem as a tar archive  #导出容器的内容流作为一个tar归档文件(对应import)
    
        history    Show the history of an image  #展示一个镜像形成历史
    
        images    List images  #列出系统当前镜像
    
        import    Import the contents from a tarball to create a filesystem image  #从tar包中的内容创建一个新的文件系统映像(对应export)
    
        info    Display system-wide information  #显示系统相关信息
    
        inspect    Return low-level information on a container or image  #查看容器详细信息
    
        kill    Kill a running container  #kill指定docker容器
    
        load    Load an image from a tar archive or STDIN  #从一个tar包中加载一个镜像(对应save)
    
        login    Register or log in to a Docker registry#注册或者登陆一个docker源服务器
    
        logout    Log out from a Docker registry  #从当前Docker registry退出
    
        logs    Fetch the logs of a container  #输出当前容器日志信息
    
        pause    Pause all processes within a container#暂停容器
    
        port    List port mappings or a specific mapping for the CONTAINER  #查看映射端口对应的容器内部源端口
    
        ps    List containers  #列出容器列表
    
        pull    Pull an image or a repository from a registry  #从docker镜像源服务器拉取指定镜像或者库镜像
    
        push    Push an image or a repository to a registry  #推送指定镜像或者库镜像至docker源服务器
    
        rename    Rename a container  #重命名容器
    
        restart    Restart a running container  #重启运行的容器
    
        rm    Remove one or more containers  #移除一个或者多个容器
    
        rmi    Remove one or more images  #移除一个或多个镜像(无容器使用该镜像才可以删除,否则需要删除相关容器才可以继续或者-f强制删除)
    
        run    Run a command in a new container  #创建一个新的容器并运行一个命令
    
        save    Save an image(s) to a tar archive#保存一个镜像为一个tar包(对应load)
    
        search    Search the Docker Hub for images  #在docker
    hub中搜索镜像
    
        start    Start one or more stopped containers#启动容器
    
        stats    Display a live stream of container(s) resource usage statistics  #统计容器使用资源
    
        stop    Stop a running container  #停止容器
    
        tag         Tag an image into a repository  #给源中镜像打标签
    
        top       Display the running processes of a container #查看容器中运行的进程信息
    
        unpause    Unpause all processes within a container  #取消暂停容器
    
        version    Show the Docker version information#查看容器版本号
    
        wait         Block until a container stops, then print its exit code  #截取容器停止时的退出状态值
    
     
    
    Run 'docker COMMAND --help' for more information on a command.  #运行docker命令在帮助可以获取更多信息
  2. 使用docker镜像:从仓库获取镜像,管理本地主机的镜像。

    1. 获取镜像

      1. 从docker registry获取镜像的命令是docker pull。命令格式是:docker pull [选项][docker registry地址] 仓库名:标签

      2. docker register地址:地址的格式一般是 域名:端口,默认地址是docker hub,仓库名:仓库名是两段格式,用户名/软件名,如果不写用户,默认docker hub用户名是library,也就是官方镜像。

    2. 镜像文件

      1. docker是把应用程序和其依赖打包在image文件里面,只有通过这个镜像文件才能生成docker容器。一个image文件可以生成多个容器实例。image文件是通用,可以共享的,为了节省时间,我们尽量。

      2. 列出服务器所有镜像文件:列出所有的image文件docker image ls,删除image文件docker image rm [imagename]

    3. 搜索docker镜像:docker search centos ,搜索所有centos的docker镜像。

    4. 获取docker镜像:可以使用docker pull命令来从仓库获取所需要的镜像。下面的例子将从Docker Hub仓库下载一个Centos操作系统的镜像。docker pull centos ,获取centos镜像。docker run -it centos /bin/bash ,完成后可以使用该镜像创建一个容器。

    5. 查看docker镜像:镜像的ID唯一标识了镜像,如果ID相同,说明是同一镜像。TAG信息来区分不同发行版本,如果不指定具体标记,默认使用latest标记信息。docker images,查看docker镜像。

    6. 删除Docker镜像:如果要移除本地的镜像,可以使用docker rmi命令(在删除镜像之前先用docker rm删除依赖于这个镜像的所有容器)。注意docker rm 命令是移除容器。docker rmi imageID,删除docker镜像。

    7. 导出docker镜像:如果要导出镜像到本地文件,可以使用docker save命令。docker save centos > /opt/centos.tar.gz,导出docker镜像至本地。

    8. 导入docker镜像:可以使用docker load从本地文件中导入到本地docker镜像库docker load < /opt/centos.tar.gz,导入本地镜像到docker镜像库。

  3. 启动docker容器的方式:启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(stopped)的容器重新启动。因为Docker的容器实在太轻量级了,很多时候用户都是随时删除和新创建容器。

    1. 新建容器并且启动

      所需要的命令主要为docker run
      
      例如,下面的命令输出一个hehe,之后终止容器。
      
      [root@docker ~]# docker run centos /bin/echo "hehe"  #这跟在本地直接执行 /bin/echo'hehe' 
      
      hehe
      
      [root@docker ~]# docker run --name mydocker -it centos /bin/bash#启动一个bash终端,允许用户进行交互。
      
      [root@1c6c3f38ea07 /]# pwd
      
      /
      [root@1c6c3f38ea07 /]# ls
      
      anaconda-post.log  bindev  etc  homelib  lib64  lost+foundmedia  mnt  optproc  root  runsbin  srv  systmp  usr  var
      
      --name:给容器定义一个名称
      
      -i:则让容器的标准输入保持打开。
      
      -t:让Docker分配一个伪终端,并绑定到容器的标准输入上
      
      /bin/bash:执行一个命令
  4. 当利用docker run来创建容器时,Docker在后台运行的标准操作包括

    1. 检查本地是否存在指定的镜像,不存在就从公有仓库下载、利用镜像创建并启动一个容器、分配一个文件系统,并在只读的镜像层外面挂在一层可读写层、从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去、从地址池配置一个ip地址给容器、执行用户指定的应用程序、执行完毕后容器被终止。

  5. docker与"hello docker",hello world是程序员启蒙语言,我们通过最简单的image文件“hello-world”,来感受一下docker。

    docker pull hello-world											# 获取镜像 hello-world
    docker images													# 检查镜像
    # 运行image文件,可以用容器id
    docker run hello-world											# 检查docker容器进程docker ps#检查所有运行过的容器docker ps -a
  6. 运行一个ubuntu容器 :咱们要在cenots7操作系统下,以docker下载一个ubuntu image文件,然后以image启动容器。

    [root@oldboy_python ~ 11:52:22]#docker pull ubuntu:14.04#如图,乌班图的镜像下载,是下载每一层的文件Trying to pull repository docker.io/library/ubuntu ... 
    14.04: Pulling from docker.io/library/ubuntu
    8284e13a281d: Pull complete 
    26e1916a9297: Pull complete 
    4102fc66d4ab: Pull complete 
    1cf2b01777b2: Pull complete 
    7f7a2d5e04ed: Pull complete 
    Digest: sha256:4851d1986c90c60f3b19009824c417c4a0426e9cf38ecfeb28598457cefe3f56
    Status: Downloaded newer image for docker.io/ubuntu:14.04
    1. 下载过程可以看出镜像是由多层存储构成的。下载也是一层一层,并非单一的文件。

    2. 下载过程中给出每一层的前12位ID。下载结束后会给出sha246的文件一致性校验值。

  7. 运行这个乌班图容器!

    [root@oldboy_python ~ 12:18:53]#docker run -it --rm ubuntu:14.04 bash#此时会进入交互式的shell界面,即可以使用乌班图操作系统
    root@3efbb2749d7c:/# cat /etc/os-release  
    NAME="Ubuntu"
    VERSION="14.04.5 LTS, Trusty Tahr"
    ID=ubuntu
    ID_LIKE=debian
    PRETTY_NAME="Ubuntu 14.04.5 LTS"
    VERSION_ID="14.04"
    HOME_URL="http://www.ubuntu.com/"
    SUPPORT_URL="http://help.ubuntu.com/"
    BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"#使用exit退出容器exit
    
    docker run就是运行容器的命令。
    参数
     -it : -i 是交互式操作,-t是终端
     -rm  :   容器退出后将其删除。也可以不指定参数,手动docker rm,使用-rm可以避免浪费空间。 ubuntu:14.04   这指的是镜像文件 bash   :  指定用交互式的shell,因此需要bash命令

Docker与CentOS

  1. docker允许在容器内运行应用程序,使用docker run命令来在容器内运行应用程序。

    # 加速docker镜像下载
    curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://95822026.m.daocloud.io
    
    docker pull docker.io/centos
        Using default tag: latest
        Trying to pull repository docker.io/library/centos ...
        latest: Pulling from docker.io/library/centos
        256b176beaff: Pull complete
        Digest: sha256:fc2476ccae2a5186313f2d1dadb4a969d6d2d4c6b23fa98b6c7b0a1faad67685
        Status: Downloaded newer image for docker.io/centos:latest
  2. 运行一个交互式的容器

    docker run -it centos /bin/bash#此时进入docker容器
    	cat /etc/redhat-release
    	
    参数解析:
    - **-t:**在新容器内指定一个伪终端或终端。
    - **-i:**允许你对容器内的标准输入 (STDIN) 进行交互。
    
    此时就进入了centos系统
    可以查看系统相关信息,内核版本信息
    cat /proc/versionls /
    
    此时想要退出容器,使用exit命令
  3. 后台模式启动docker

    1. -d参数:后台运行容器,返回容器IDdocker run -d centos /bin/sh -c "while true;do echo hello centos; sleep 1;done"

    2. 查看容器内的标准输出docker logs c02

    3. 停止容器docker stop c02

    4. 启动容器docker start c02和删除容器docker rm c02

    5. Docker镜像常用命令

      docker images 						# 列出所有本级镜像
      docker pull centos 					# 获取新的centos镜像
      docker search nginx 				# 搜索nginx镜像
    6. 构建镜像,通过commit修改镜像,编写dockerfile。

  4. 进入容器

    1. 使用-d参数时,容器启动后会进入后台。某些时候需要进入容器进行操作,有很多种方法,包括使用docker attach命令或nsenter工具等。

      docker  exec -it 					# 容器id
      docker attach 						# 容器id
  5. 提交创建自定义的镜像(docker container commit)

    1.我们进入交互式的centos容器中,发现没有vim命令
    	docker run -it centos
    2.在当前容器中,安装一个vim
    	yum install -y vim
    3.安装好vim之后,exit退出容器
    	exit
    4.查看刚才安装好vim的容器记录
    	docker container ls -a
    5.提交这个容器,创建新的image
    	docker commit 059fdea031ba chaoyu/centos-vim
    6.查看镜像文件
        [root@master /home]docker images
        REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
        chaoyu/centos-vim   latest              fd2685ae25fe        5 minutes ago       348MB
  6. 外部访问容器

    1. 容器中可以运行网络应用,但是要让外部也可以访问这些应用,可以通过-p或-P参数指定端口映射。-P 参数会随机映射端口到容器开放的网络端口docker run -d -P training/webapp python app.py

    2. 查映射的端口,宿主机ip:32768 映射容器的5000端口docker ps -l

    3. 查看容器日志信息,不间断显示logdocker logs -f cfd

    4. 也可以通过-p参数指定映射端口,指定服务器的9000端口,映射到容器内的5000端口docker run -d -p 9000:5000 training/webapp python app.py

    5. 查看指定容器的端口映射docker port c0b

    6. 查看容器内的进程docker top c0b

  7. 利用dockerfile定制镜像

    1. 镜像是容器的基础,每次执行docker run的时候都会指定哪个镜像作为容器运行的基础。我们之前的例子都是使用来自docker hub的镜像,直接使用这些镜像只能满足一定的需求,当镜像无法满足我们的需求时,就得自定制这些镜像。

    2. 镜像的定制就是定制每一层所添加的配置、文件。如果可以吧每一层修改、安装、构建、操作的命令都写入到一个脚本,用脚本来构建、定制镜像,这个脚本就是dockerfile。

    3. Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令 构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

      FROM scratch #制作base image 基础镜像,尽量使用官方的image作为base image
      FROM centos #使用base image
      FROM ubuntu:14.04 #带有tag的base image
      
      LABEL version=“1.0” #容器元信息,帮助信息,Metadata,类似于代码注释
      LABEL maintainer=“[email protected]"
      
      #对于复杂的RUN命令,避免无用的分层,多条命令用反斜线换行,合成一条命令!
      RUN yum update && yum install -y vim \
          Python-dev #反斜线换行
      RUN /bin/bash -c "source $HOME/.bashrc;echo $HOME”
      
      WORKDIR /root #相当于linux的cd命令,改变目录,尽量使用绝对路径!!!不要用RUN cd
      WORKDIR /test #如果没有就自动创建
      WORKDIR demo #再进入demo文件夹
      RUN pwd     #打印结果应该是/test/demo
      
      ADD and COPY 
      ADD hello /  #把本地文件添加到镜像中,吧本地的hello可执行文件拷贝到镜像的/目录
      ADD test.tar.gz /  #添加到根目录并解压
      
      WORKDIR /root
      ADD hello test/  #进入/root/ 添加hello可执行命令到test目录下,也就是/root/test/hello 一个绝对路径
      COPY hello test/  #等同于上述ADD效果
      
      ADD与COPY
         - 优先使用COPY命令
          -ADD除了COPY功能还有解压功能
      添加远程文件/目录使用curl或wget
      
      ENV #环境变量,尽可能使用ENV增加可维护性
      ENV MYSQL_VERSION 5.6 #设置一个mysql常量
      RUN yum install -y mysql-server=“${MYSQL_VERSION}” 
      ------这里需要稍微理解一下了-------中级知识---先不讲
      VOLUME and EXPOSE 
      存储和网络
      
      RUN and CMD and ENTRYPOINT
      RUN:执行命令并创建新的Image Layer
      CMD:设置容器启动后默认执行的命令和参数
      ENTRYPOINT:设置容器启动时运行的命令
      
      Shell格式和Exec格式
      RUN yum install -y vim
      CMD echo ”hello docker”
      ENTRYPOINT echo “hello docker”
      
      Exec格式
      RUN [“apt-get”,”install”,”-y”,”vim”]
      CMD [“/bin/echo”,”hello docker”]
      ENTRYPOINT [“/bin/echo”,”hello docker”]
      
      
      通过shell格式去运行命令,会读取$name指令,而exec格式是仅仅的执行一个命令,而不是shell指令
      cat Dockerfile
          FROM centos
          ENV name Docker
          ENTRYPOINT [“/bin/echo”,”hello $name”]#这个仅仅是执行echo命令,读取不了shell变量
          ENTRYPOINT  [“/bin/bash”,”-c”,”echo hello $name"]
      
      CMD
      容器启动时默认执行的命令
      如果docker run指定了其他命令(docker run -it [image] /bin/bash ),CMD命令被忽略
      如果定义多个CMD,只有最后一个执行
      
      ENTRYPOINT
      让容器以应用程序或服务形式运行
      不会被忽略,一定会执行
      最佳实践:写一个shell脚本作为entrypoint
      COPY docker-entrypoint.sh /usr/local/bin
      ENTRYPOINT [“docker-entrypoint.sh]
      EXPOSE 27017
      CMD [“mongod”]
      
      [root@master home]# more Dockerfile
      FROm centos
      ENV name Docker
      #CMD ["/bin/bash","-c","echo hello $name"]
      ENTRYPOINT ["/bin/bash","-c","echo hello $name”]
  8. 发布docker image到仓库

    1. docker hub公有镜像发布

      1.docker提供了一个类似于github的仓库dockerhub,
      网址https://hub.docker.com/需要注册使用
      2.注册docker id后,在linux中登录dockerhub
      docker login注意要保证image的tag是账户名,如果镜像名字不对,需要改一下tagdocker tag chaoyu/centos-vim yuchao163/centos-vim语法是:  docker tag   仓库名   yuchao163/仓库名
      3.推送docker image到dockerhub
      docker push yuchao163/centps-cmd-exec:latest
      4.在dockerhub中检查镜像
      https://hub.docker.com/
      5.删除本地镜像,测试下载pull 镜像文件
      docker pull yuchao163/centos-entrypoint-exec
    2. 私有仓库:但是这种镜像仓库是公开的,其他人也是可以下载,并不安全,因此还可以使用docker registry官方提供的私有仓库。

      1.官方提供的私有仓库docker registry用法
      https://yeasy.gitbooks.io/docker_practice/repository/registry.html
      2.一条命令下载registry镜像并且启动私有仓库容器
      私有仓库会被创建在容器的/var/lib/registry下,因此通过-v参数将镜像文件存储到本地的/opt/data/registry下
      端口映射容器中的5000端口到宿主机的5000端口
      docker run -d \
          -p 5000:5000 \
          -v /opt/data/registry:/var/lib/registry \
          registry
      3.检查启动的registry容器
      docker ps
      4.测试连接容器
      telnet 192.168.119.10 5000
      5.修改镜像tag,以docker registry的地址端口开头
      docker tag hello-world:latest 192.168.119.10:5000/hello-world:latest
      6.查看docker镜像,找到registry的镜像
      docker images
      7.Docker 默认不允许非 HTTPS 方式推送镜像。我们可以通过 Docker 的配置选项来取消这个限制,这里必须写正确json数据
      [root@master /]# cat /etc/docker/daemon.json
      {"registry-mirrors": ["http://95822026.m.daocloud.io"],
      "insecure-registries":["192.168.119.10:5000"]
      }
      写入到docker服务中,写入到[Service]配置块中,加载此配置文件
      [root@master home]# grep 'EnvironmentFile=/etc/docker/daemon.json' /lib/systemd/system/docker.service
      EnvironmentFile=-/etc/docker/daemon.json
      8.修改了docker配置文件,重新加载docker
      systemctl daemon-reload
      9.重启docker
      systemctl restart docker
      10.重启了docker,刚才的registry容器进程挂掉了,因此重新启动它
      docker run --privileged=true -d -p 5000:5000 -v /opt/data/registry:/var/lib/registry registry
      --privileged=true  docker容器的安全机制:设置特权级运行的容器
      11.推送本地镜像
      docker push 192.168.119.10:5000/hello-world
      12.由于docker registry没有web节目,但是提供了API数据
      官网教程:https://docs.docker.com/registry/spec/api/#listing-repositories
      
      curl http://192.168.119.10:5000/v2/_catalog
      或者浏览器访问http://192.168.119.10:5000/v2/_catalog13.删除本地镜像,从私有仓库中下载docker pull 192.168.119.10:5000/hello-world
  9. 打包flask程序与dockerfile

    1. 超哥构建好的镜像,只要丢给武沛奇,说“小沛奇,拿去用吧,这个镜像你直接docker run就能用了,不需要你管环境问题了,有没有很崇拜我”,沛奇说,“超哥真牛逼”

      确保app.py和dockerfile在同一个目录!
      1.准备好app.py的flask程序
      [root@master home]# cat app.py#coding:utf8
      from flask import Flask
      app=Flask(__name__)
      @app.route('/')
      def hello():
          return "hello docker"
      if __name__=="__main__":
          app.run(host='0.0.0.0',port=8080)
      [root@master home]# ls
      app.py  Dockerfile
      
      2.编写dockerfile
      FROM centos
      COPY CentOS-Base.repo /etc/yum.repos.d/
      COPY epel.repo /etc/yum.repos.d/
      RUN yum clean all
      RUN yum install python-setuptools -y
      RUN easy_install flask
      COPY s16-flask.py /opt/
      WORKDIR /opt
      EXPOSE 8080
      CMD ["python","s16-flask.py"]
      
      3.构建镜像image
      docker build -t yuchao163/flask-hello-docker .
      
      4.查看创建好的images
      docker image ls
      
      5.启动此flask-hello-docker容器,映射一个端口供外部访问
      docker run -d -p 8080:8080 yuchao163/flask-hello-docker
      
      6.检查运行的容器
      docker container ls
  10. docker跑一个selenium脚本

    1. 运行完整流程

      [root@chaogelinux tmp]# pip3 list |grep selenium
      selenium        3.141.0
      [root@chaogelinux tmp]# cat baidu.py
      from selenium import webdriver
      chrome_options = webdriver.ChromeOptions()
      chrome_options.add_argument('--headless')   #不需要可视化界面,linux无图形化
      chrome_options.add_argument('--no-sandbox')  #以最高权限运行
      driver = webdriver.Chrome(executable_path='/tmp/chromedriver', options=chrome_options)  #找到webdriver浏览器驱动
      driver.get("http://www.baidu.com")
      print(driver.title)
      driver.close()
      
      \#获取浏览器驱动
      wget http://npm.taobao.org/mirrors/chromedriver/71.0.3578.33/chromedriver_linux64.zip
      
      [root@chaogelinux tmp]# python3 baidu.py
    2. 使用容器

      1.准备好一个装好selenium的镜像,并且是执行baidu.py功能的,准备好Dockerfile
      [root@chaogelinux selenium_docker]# cat Dockerfile
      FROM python:3.7
      RUN echo 'nameserver 119.29.29.29' >> /etc/resolv.conf
      RUN pip3 install -i https://pypi.douban.com/simple selenium
      ADD baidu.py /opt/
      WORKDIR /opt/
      CMD ['python3','/opt/baidu.py']
      
      2.构建镜像
      
      [root@chaogelinux selenium_docker]# docker build -t se_python .   
      
      3.如果构建失败,网速问题,则
      
      vim /etc/sysctl.conf  #添加,修改代码
      
      net.ipv4.ip_forward=1
      
      systemctl restart network
      
      检查sysctl net.ipv4.ip_forward4.检查镜像
      [root@chaogelinux selenium_docker]# docker images
      REPOSITORY TAG IMAGE ID CREATED SIZE
      se_python latest 2b9508d00eb9 6 minutes ago 926 MB
  11. docker网络

    1. Docker 允许通过外部访问容器或容器互联的方式来提供网络服务。端口映射允许外部访问容器、--link 容器互联、容器桥接网络。

      1.通过--link容器通信,给test2添加一个hosts解析记录
      docker run -d --name test2 --link test1 busybox /bin/sh -c "while true;do sleep 3600;done"
      test2可以ping通test1,反之不可以
    2. 但是--link是不推荐使用的,而是更强大的自定义docker网络链接容器

      1.新建一个docker网络
      docker network create -d bridge my-net
      -d 参数指定 Docker 网络类型,有 bridge overlay
      
      2.连接容器
      运行一个容器并连接到新建的 my-net 网络
      
      $ docker run -it --rm --name busybox1 --network my-net busybox sh
      打开新的终端,再运行一个容器并加入到 my-net 网络
      
      $ docker run -it --rm --name busybox2 --network my-net busybox sh
      再打开一个新的终端查看容器信息
      
      $ docker container ls
      
      CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
      b47060aca56b        busybox             "sh"                11 minutes ago      Up 11 minutes                           busybox2
      8720575823ec        busybox             "sh"                16 minutes ago      Up 16 minutes                           busybox1
      下面通过 ping 来证明 busybox1 容器和 busybox2 容器建立了互联关系。
      
      在 busybox1 容器输入以下命令
      
      / # ping busybox2
      PING busybox2 (172.19.0.3): 56 data bytes
      64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.072 ms
      64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.118 ms
      用 ping 来测试连接 busybox2 容器,它会解析成 172.19.0.3。
      
      同理在 busybox2 容器执行 ping busybox1,也会成功连接到。
      
      / # ping busybox1
      PING busybox1 (172.19.0.2): 56 data bytes
      64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.064 ms
      64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.143 ms
      这样,busybox1 容器和 busybox2 容器建立了互联关系。
  12. 外部访问容器

    1. 容器中可以运行网络应用,但是要让外部也可以访问这些应用,可以通过-p或-P参数指定端口映射。

      -P 参数会随机映射端口到容器开放的网络端口
      [root@oldboy_python ~ 16:31:37]#docker run -d -P training/webapp python app.py
    2. 检查映射的端口

      #宿主机ip:32768 映射容器的5000端口[root@oldboy_python ~ 16:34:02]#docker ps -l
      CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
      cfd632821d7a        training/webapp     "python app.py"     21 seconds ago      Up 20 seconds       0.0.0.0:32768->5000/tcp   brave_fermi
    3. 查看容器日志信息

      #不间断显示log
      docker logs -f cfd
    4. 也可以通过-p参数指定映射端口

      #指定服务器的9000端口,映射到容器内的5000端口[root@oldboy_python ~ 16:46:13]#docker run -d -p 9000:5000 training/webapp python app.py
      c0b5a6278d0f4f2e9b9eba8680451111d8b911b61de0c37ea64cb337aefb854e
  13. 查看指定容器的端口映射

    docker port c0b
    5000/tcp -> 0.0.0.0:9000
  14. 查看容器内的进程

    [root@oldboy_python ~ 16:49:05]#docker top c0b
    UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
    root                3926                3912                0                   16:46               ?                   00:00:00            python app.py

Ubuntu安装

  1. 乌班图操作系统下载地址:http://releases.ubuntu.com/18.04/ubuntu-18.04.1-desktop-amd64.iso

  2. 准备好vmware虚拟机,下载ubuntu后打开vmware并创建虚拟机。版本选择16.2后客户端类型选择Linux,版本选择Ubuntu64一直下一步即可。

  3. 安装pycharm

    1. pycharm之linux版本下载地址:https://download.jetbrains.8686c.com/python/pycharm-community-2018.2.4.tar.gz

    2. 解压缩pycharm:yuchao@ubuntu:/tmp$ tar zxvf pycharm-professional-2018.2.4.tar.gz

    3. 解压缩后进入文件夹:cd /tmp/pycharm-2018.2.4/bin

    4. 执行脚本,启动pycharmsource pycharm.sh

    5. 配置桌面快捷启动pycharm

      1. 在桌面创建一个文本文件,名为Pycharm.desktop

      2. 在文件中添加内容

        [Desktop Entry]
        Version=1.0
        Type=Application
        Name=Pycharm
        Icon=/home/yuchao/Downloads/pycharm-professional-2018.2.4/pycharm-2018.2.4/bin/pycharm.png
        Exec=/home/yuchao/Downloads/pycharm-professional-2018.2.4/pycharm-2018.2.4/bin/pycharm.sh
        MimeType=application/x-py
        Name[en_US]=pycharm
      3. 修改属性中选中Permissions后,勾选Allow executing file as pycharm。

Shell编程实战

  1. 为什么要学习Shell编程,Shell脚本语言是实现Linux/Unix系统管理及自动化运维所必须的重要工具,Linux系统的底层以及基础应用软件的核心大都涉及Shell脚本的内容。一个合格的Linux系统管理员都必须熟练编写Shell脚本语言,从而提升运维人员的工作效率,减少不必要的重复性工作。

  2. 学习Shell所需的基础知识

    1. 熟练使用VIm编辑器,熟悉SSH终端等配置

      1. 在Linux下开发shell脚本用的最多的就是vim编辑器,熟练使用vim可以使得shell脚本开发事半功倍!

    2. 有一定的Linux命令基础,熟练掌握80个命令以上

      1. shell和其他脚本语言不同,如python,Shell缺少可以直接使用的外部函数库,因此Linux系统的命令就可以当做Shell的函数库!

    3. 熟悉常见Linux服务部署,优化,分析与排错

      1. 学习Shell直接的目的是在工作中对系统以及服务进行自动化管理,因此如果不熟悉服务操作,使用shell也就没有意义了

  3. 什么是Shell

    1. Shell存在于操作系统的最外层,负责与用户直接对话,把用户的输入解释给操作系统,处理操作系统的输出结果,然后反馈给用户。

    2. Shell是一个命令解释器,它的作用是解释并执行用户输入的命令和程序等,用户每输入一条命令,Shell解释器就执行一条,存在一种交互的方式。

    3. 从开机准备输入用户名和密码,到登录成功,所有的操作都是Shell解释并执行的。

  4. 什么是Shell脚本

    1. 当命令或者程序语句不是在命令行中执行,而是通过一个程序文件来执行时,这个程序就称作Shell脚本。

    2. 一个简单的Shell脚本

      1. 清除/var/log下的messages日志文件

      2. 把所有命令放入一个文件,堆积起来后就是一个脚本文件!注意文件的可执行权限,与用户身份

        # 清除脚本日志
        cd /var/log
        cat /dev/null > messages
        echo "Logs cleaned up . done"
  5. Shell脚本语言的种类

    1. Shell脚本语言是弱类型语言(无须定义变量的类型即可使用),在Linux中有两大Shell,一是Bourne shell,二是C shell我们需要知道的就是标准的Bourne Again shell(bash)所取代。

    2. 语言选择:Shell脚本语言优势在于处理系统底层的业务,基于linux命令处理也是最快的,常用语开发自动化安装,监控报警,软件启动等脚本。

  6. 第一个Shell脚本与hello world

    1. 脚本开头:一个规范的脚本文件会在第一行指出由哪个程序来执行脚本的内容,必须位于第一行!!!如果你不加默认也会交给bash解释,良好的编程习惯,最好加上开头解释器语言标识#!/bin/bash#!/usr/bin/env python

  7. 执行Shell脚本的方式

    bash 脚本名
    sh    脚本名
    此方法是脚本没有可执行权限时,或者文件头没指定解释器时用的方法path/scriptName./scriptName 此方法需要脚本有可执行权限,chmod +x scriptNamesource scriptName. scriptName加载并执行脚本文件中的命令和语句
    
    [root@oldboy_python /tmp 11:10:08]#sh test.sh
    chaoge nb
    [root@oldboy_python /tmp 11:10:18]#cat test.sh
    #!/bin/bash
    echo 'chaoge nb'
    [root@oldboy_python /tmp 11:10:21]#. test.sh
    chaoge nb
    [root@oldboy_python /tmp 11:10:33]#source  test.sh
    chaoge nb#添加可执行权限给test.shchmod +x test.sh./test.sh

变量

  1. 环境变量一般指的是export内置命令导出的变量,用于定义SHell的运行环境。

  2. Shell通过环境变量来确定命令提示符,也就是超哥前面说的PS1变量

  3. 环境变量可以在命令行中设置和创建,但是用户退出命令行时变量值就会丢失,因此可以写入/etc/profile文件中,每次用户登录时,变量都会被初始化!

  4. 环境变量名字均大写,用env查看

  5. 设置登录的提示/etc/motd

  6. 定义变量,变量定义的注意点:变量名和等号之间不能有空格、命名只能用英文字母,数字,下划线,首个字符不能用数字、不能用标点符号、不能用关键字。

    name='chaoge'
    echo $name
    echo ${name} #帮助解释器识别变量的边界
    #变量重新赋值
    name='chaogenb'
  7. 设置只读变量

    readonly name
    name='chaogenb3'
    -bash: name: 只读变量
  8. 删除变量unset name

  9. 变量类型:局部变量 在脚本或命令中定义,仅在当前shell有效、环境变量 所有的程序,shell程序都能访问环境变量、shell变量 特殊变量 既有环境变量 又有局部变量。

字符串

  1. 字符串可以用单引号,也可以双引号,也可以没引号

    addr='shahe'
    echo $addr
    shahe
  2. 单引号的任何字符串都会原样输出,单引号字符串中的变量无效、单引号字符串不能出现单一的单引号,转义符也不可用,可用作字符串拼接、双引号里可以用变量,双引号可以有转义符。

    addr='changpingshahe'
    name='yuchao'
    message="Hello,${name},Your addr is \"${addr}\" "
    echo $message
    Hello,yuchao,Your addr is "changpingshahe"
  3. 获取字符串长度

    str='abc'
    echo ${#str}
    3
  4. 左闭又开规则

    str='I am chaoge,hello world!'
    #取出0和10索引的字符
    echo ${str:0:11}
    I am chaoge
  5. 查找字符索引

    str='I am chaoge,hello world!'
    echo `expr index "$str" e`
    11

saltstack高效运维

  1. 概述

    1. saltstack是由thomas Hatch于2011年创建的一个开源项目,设计初衷是为了实现一个快速的远程执行系统。

    2. 系统管理员日常会进行大量的重复性操作,例如安装软件,修改配置文件,创建用户,批量执行命令等等。如果主机数量庞大,单靠人工维护实在让人难以忍受。

    3. 早期运维人员会根据自己的生产环境来写特定脚本完成大量重复性工作,这些脚本复杂且难以维护。系统管理员面临的问题主要是1、系统配置管理,2、远程执行命令,因此诞生了很多开源软件,系统维护方面有fabric、puppet、chef、ansible、saltstack等,这些软件擅长维护系统状态或方便的对大量主机进行批量的命令执行。

    4. salt灵活性强大,可以进行大规模部署,也能进行小规模的系统部署。salt的设计架构适用于任意数量的服务器,从少量本地网络系统到跨越数个数据中心,拓扑架构都是c/s模型,配置简单。

    5. 不管是几台、几百台、几千台服务器,都可以使用salt在一个中心节点上进行管控,灵活定位任意服务器子集来运行命令。 

    6. Salt是python编写的,支持用户通过python自定义功能模块,也提供了大量的python API接口,用户可以根据需要进行简单快速的扩展。

  2. saltstack的运行方式,Local 本地运行,交付管理、Master/Minion <<< 常用方式 、Salt SSH 不需要客户端。

  3. salt部署基本架构

    1. 在安装salt之前,先理解salt架构中各个角色,主要区分是salt-master和salt-minion,顾名思义master是中心控制系统,minion是被管理的客户端。

    2. salt架构中的一种就是master > minion。在远程执行系统中,salt用python通过函数调用完成任务。

  4. 运行salt依赖包:python、zeromq、pyzmp、pycrypto、msgpack-python、yaml、jinja2。解决依赖包最简单的办法就是用安装包管理器,yum工具

  5. 服务器环境准备

    服务器环境 centos7(master) centos7(master)
    ip地址 192.168.178.131 192.168.178.132
    身份 master slave
    软件包 salt-master salt-minion
  6. 修改虚拟机ip地址为静态地址,并且确保可上网

    1. master网卡配置

      TYPE="Ethernet"
      PROXY_METHOD="none"
      BROWSER_ONLY="no"
      BOOTPROTO="static"
      DEFROUTE="yes"
      IPV4_FAILURE_FATAL="no"
      IPV6INIT="yes"
      IPV6_AUTOCONF="yes"
      IPV6_DEFROUTE="yes"
      IPV6_FAILURE_FATAL="no"
      IPV6_ADDR_GEN_MODE="stable-privacy"
      NAME="ens33"
      UUID="7d4f9ede-810f-4976-a01b-250b845c99cc"
      DEVICE="ens33"
      ONBOOT="yes"
      IPADDR=192.168.11.131
      NETMASK=255.255.255.0
      GATEWAY=192.168.11.1
      DNS1=119.29.29.29
    2. slave网卡配置

      TYPE="Ethernet"
      PROXY_METHOD="none"
      BROWSER_ONLY="no"
      BOOTPROTO="static"
      DEFROUTE="yes"
      IPV4_FAILURE_FATAL="no"
      IPV6INIT="yes"
      IPV6_AUTOCONF="yes"
      IPV6_DEFROUTE="yes"
      IPV6_FAILURE_FATAL="no"
      IPV6_ADDR_GEN_MODE="stable-privacy"
      NAME="ens33"
      UUID="f9fc5929-8594-466e-a041-34caee8c1e32"
      DEVICE="ens33"
      ONBOOT="yes"
      IPADDR=192.168.11.132
      NETMASK=255.255.255.0
      GATEWAY=192.168.11.1
      DNS1=119.29.29.29
    3. dns配置文件

      # Generated by NetworkManager
      nameserver 119.29.29.29
    4. /etc/hosts

      127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
      ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
      192.168.11.132  slave
      192.168.11.131  master
  7. 关闭服务器安全策略

    关闭firewalld
    systemctl disable firewalld
    systemctl stop firewalld
    
    关闭iptables
    iptables -F
    
    关闭selinux
  8. 安装saltstack

    1. salt软件包需要epel源的支持,那么下载

    2. EPEL的全称叫 Extra Packages for Enterprise Linux 。EPEL是由 Fedora 社区打造,为 RHEL 及衍生发行版如 CentOS、Scientific Linux 等提供高质量软件包的项目。装上了 EPEL之后,就相当于添加了一个第三方源。

      wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
      wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
      yum clean all #清空缓存
      yum makecache #生成yum缓存
    3. 安装好epel源就可以开始安装salt了

      查看salt包yum list salt安装salt-master
      yum install salt-master -y
      安装salt-minion
      yum install salt-minion -y
  9. salt端口,安装好salt之后开始配置,salt-master默认监听两个端口:

    4505   publish_port 提供远程命令发送功能
    4506   ret_port     提供认证,文件服务,结果收集等功能
    确保客户端可以通信服务器的此2个端口,保证防火墙允许端口通过。因此在测试环境直接关闭防火墙。
  10. 配置文件

    salt-master的配置文件是/etc/salt/master
    salt-minion的配置文件是/etc/salt/minion
    配置文件中包含了大量可调整的参数,这些参数控制master和minion各个方面
    1. 配置salt-master

      # salt运行的用户,影响到salt的执行权限
      user: root
      
      #s alt的运行线程,开的线程越多一般处理的速度越快,但一般不要超过CPU的个数
      worker_threads: 10
      
      # master的管理端口
      publish_port : 4505
      
      # master跟minion的通讯端口,用于文件服务,认证,接受返回结果等
      ret_port : 4506
      
      # 如果这个master运行的salt-syndic连接到了一个更高层级的master,那么这个参数需要配置成连接到的这个高层级master的监听端口
      syndic_master_port : 4506
      
      # 指定pid文件位置
      pidfile: /var/run/salt-master.pid
    2. 超哥的salt-master文件

      [root@master ~]# grep -v ^# /etc/salt/master|grep -v ^$
      interface: 0.0.0.0  #绑定到本地的0.0.0.0地址
      publish_port: 4505  #管理端口,命令发送
      user: root      #运行salt进程的用户
      worker_threads: 5  #salt运行线程数,线程越多处理速度越快,不要超过cpu个数
      ret_port: 4506  #执行结果返回端口
      pidfile: /var/run/salt-master.pid #pid文件位置
      log_file: /var/log/salt/master  #日志文件地址#自动接收minion的keyauto_accept: False
    3. 认识

      # minion的识别ID,可以是IP,域名,或是可以通过DNS解析的字符串
      id: slave
       
      # salt运行的用户权限
      user: root
       
      # master的识别ID,可以是IP,域名,或是可以通过DNS解析的字符串
      master : master
       
      # master通信端口
      master_port: 4506
       
      # 备份模式,minion是本地备份,当进行文件管理时的文件备份模式
      backup_mode: minion
       
      # 执行salt-call时候的输出方式
      output: nested
       
      # minion等待master接受认证的时间
      acceptance_wait_time: 10
       
      # 失败重连次数,0表示无限次,非零会不断尝试到设置值后停止尝试
      acceptance_wait_time_max: 0
       
      # 重新认证延迟时间,可以避免因为master的key改变导致minion需要重新认证的syn风暴
      random_reauth_delay: 60
       
      # 日志文件位置
      log_file: /var/logs/salt_minion.log
    4. 超哥的satl-minion文件

      [root@slave ~]# grep -v ^# /etc/salt/minion|grep -v ^$
      master: master
      master_port: 4506
      user: root
      id: slave
      acceptance_wait_time: 10
      log_file: /var/log/salt/minion
  11. 启动salt-master和salt-minion

    systemctl start salt-minion
    systemctl start salt-master#检查salt状态systemctl status salt-minionsystemctl status salt-master
  12. 在master上接收minion秘钥

    1. 在minion启动后连接master会请求master为其签发证书,等待证书签发完成后,master可以信任minion,并且minion和master之间的通信是加密的。

    2. 在salt-master执行

    3. salt-key命令用于管理mionion秘钥

      [root@master ~]# salt-key -L
      Accepted Keys:
      Denied Keys:
      Unaccepted Keys:
      slave    #此时已经出现slave
      Rejected Keys:
    4. 此时slave已经出现在unaccepted keys中,说明minion已经和master联系,并且master已经获取了minion的公钥,等待下一步指令。

  13. 检查master和minion的秘钥匹配

    1. 在master上执行salt-key -f slave

    2. 然后可以在minion上获取minion的秘钥salt-call --local key.finger

    3. 因此可确认秘钥匹配,在master上接收秘钥salt-key -a slave

    4. 确认接收秘钥后,检验minion秘钥是否被接收salt-key -L

  14. salt-key

    1. 只有Master接受了Minion Key后,才能进行管理。具体的认证命令为salt-key常用的有如下命令。

      [root@linux-node1 ~]# salt-key -L
      Accepted Keys:  #已经接受的key
      Denied Keys:    #拒绝的key
      Unaccepted Keys:#未加入的key
      Rejected Keys:#吊销的key
      
      #常用参数
      -L  #查看KEY状态
      -A  #允许所有
      -D  #删除所有
      -a  #认证指定的key
      -d  #删除指定的key
      -r  #注销掉指定key(该状态为未被认证)
      
      #在master端/etc/salt/master配置
      auto_accept: True   #如果对Minion信任,可以配置master自动接受请求
    2. salt-key的使用

      #列出当前所有的key
      [root@salt0-master ~]# salt-key 
      Accepted Keys:
      salt1-minion.example.com
      salt2-minion.example.com
      salt3-minion.example.com
      salt4-minion.example.com
      Denied Keys:
      Unaccepted Keys:
      Rejected Keys:
      
      #添加指定minion的key
      [root@salt0-master ~]# salt-key  -a salt1-minion.example.com -y
      #添加所有minion的key
      [root@salt0-master ~]# salt-key  -A  -y
      
      #删除指定的key
      [root@salt0-master ~]# salt-key -d salt1-minion.example.com -y
      #删除所有的key
      [root@salt0-master ~]# salt-key -D -y
  15. 日常命令参数

    1. 首先知道master和minion都安装了什么文件,然后才知道怎么操作

    2. master端rpm -ql salt-master

      /etc/salt/master      # salt master主配置文件
      /usr/bin/salt           #salt master 核心操作命令
      /usr/bin/salt-cp       #salt 文件传输命令
      /usr/bin/salt-key    #salt证书管理
      /usr/bin/salt-master    #salt master 服务命令
      /usr/bin/salt-run          #salt master runner命令
    3. slave端

      [root@slave  ~]$rpm -ql salt-minion
      /etc/salt/minion     #minion配置文件
      /usr/bin/salt-call    #拉取命令
      /usr/bin/salt-minion   #minion服务命令
      /usr/lib/systemd/system/salt-minion.service   #minion启动脚本
  16. 第一条salt命令

    1. salt '*' test.ping,salt 是一个命令 # * 表示目标主机, 在这里代表所有目标主机 # test.ping是salt远程执行的一个模块下面的方法。

    2. 这是条很简单的探测minion主机存活命令,也是远程执行命令,我们通过master发送消息给"*"所有的minion,并且告诉他们运行salt内置的命令(也是python模块中的一个函数),返回true表示slave机器监控存活。

    3. test模块实际上还有许多其他的函数salt '*' sys.list_functions test

    4. 测试下test.echosalt '*' test.echo 'chaoge nb666'

    5. test.fib生成斐波那契数列,菲波那切数列定义是第0项是0,第1项是1,数列从第3项开始,每一项等于前两项之和。salt '*' test.fib 50

    6. 小结:此前在机器上安装了salt minion和salt master,进行了最简单的连接,然后master接受了minion的秘钥,运行了第一条test.ping命令

  17. salt命令组成结构

    1. 在命令行输入的命令都是执行模块,等到命令写入到文件中,就叫做状态模块。salt --help,即可查看salt帮助。

    2. 完整的五部分命令--summary参数显示salt命令的概要salt --summary '*' cmd.run 'hostname'

    3. 列出所有salt的sys模块salt 'slave' sys.list_modules

    4. 远程执行命令模块,cmd是超级模块,所有shell命令都能执行。

      salt 'slave' cmd.run 'ps -ef|grep python'
    5. 远程安装nginx

      #在minion上安装nginx
      [root@master 192.168.11.72 ~]$salt 'slave' pkg.install "nginx"
      #卸载minion上的nginx
      [root@master 192.168.11.72 ~]$salt 'slave' pkg.remove "nginx"
      #检查pkg包的版本
      [root@master 192.168.11.72 ~]$salt 'slave' pkg.version "nginx"
    6. 远程管理服务模块,管理服务是系统管理员的重要任务,通过salt管理minion服务会很简单,使用service模块。

      salt 'slave' service.start "nginx"
      salt 'slave' service.status "nginx"
      salt 'slave' service.stop "nginx"
  18. 与标准的Linux命令一样,salt的命令一样用法,--out控制salt命令结果输出的格式。

    1. JSON

      [root@master 192.168.199.155 ~]$salt --out=json '*' cmd.run_all 'hostname'
      {
          "slave": {
              "pid": 2268,
              "retcode": 0,
              "stderr": "",
              "stdout": "slave"
          }
      }
    2. YAML

      [root@master 192.168.199.155 ~]$salt --out=yaml '*' cmd.run_all 'hostname'
      slave:
        pid: 2289
        retcode: 0
        stderr: ''
        stdout: slave
  19. YAML讲解

    在学习saltstack过程中,第一要点就是States编写技巧,简称SLS文件。这个文件遵循YAML语法。初学者看这玩意很容易懵逼,来,超哥拯救你学习YAML语法
    json xml yaml 数据序列化格式
    yaml容易被解析,应用于配置文件
    
    salt的配置文件是yaml配置文件,不能用tab
    saltstack,k8s,ansible都用的yaml格式配置文件
    
    
    语法规则
        大小写敏感
        使用缩进表示层级关系   
        缩进时禁止tab键,只能空格
        缩进的空格数不重要,相同层级的元素左侧对其即可
        # 表示注释行
    yaml支持的数据结构
        对象: 键值对,也称作映射 mapping 哈希hashes 字典 dict    冒号表示 key: value   key冒号后必须有
        数组: 一组按次序排列的值,又称为序列sequence 列表list     短横线  - list1
        纯量: 单个不可再分的值
    
    对象:键值对
    yaml
        first_key:
          second_key:second_value
    
    python
        {
            'first_key':{
                'second_key':'second_value',
            }
        }
    
    YAML是YAML Ain't Markup Language的首字母缩写,YAML的语法简单,
    结构体通过空格展示
    项目使用 '-' 代表
    键值对通过 ':' 分割
    YAML语法遵循固定的缩进风格,表示数据层级结构关系,saltstack需要每个缩进级别由2个空格组成,禁止用tabs!!!
    
    Python中的字典是简单的键值对,go语言中称作哈希表map
    字典的key通过冒号分割
    
    key在YAML中表现形式是一个冒号结果的字符串
    my_key: my_value
    转化到python语法中,上述命令为
    {'my_key':'my_value'}
    
    value还可以通过缩进和key关联,四个空格!!
    my_key:
        my_value 
    转化为python语法同样的
    {'my_key':'my_value'}
    
    YAML语法中字典是可以嵌套的
    one_dict_key:
        two_dict_key:value_dict
    转化为python语法
    {
      'one_dict_key':{
        'two_dict_key':'value_dict'
      }
    }
    
    短横杠
    YAML语法表示列表,使用一个横杠加一个空格
    多个项使用同样的缩进级别作为同一个列表的部分
    - list_value_one
    - list_value_two
    - list_value_three列表可以作为一个键值对的value,例如一次性要安装多个软件my_dict:  - l1  - l2  - l3转化为python代码理解就是
    {
      'my_dict':['l1','l2',;l3]
    }
  20. 目标定位字符串

    1. 之前的salt命令我们都是使用 salt '*'控制所有minion,并且我们只有一个“slave”,但是生产环境的服务器很可能是成千上百的minion,因此需要灵活地定位所需的服务器并且执行远程命令。

    2. 全局匹配salt '*' test.ping

    3. Linux通配符

      Linux通配符
      *               代表任意字符,或空字符串
      ?               代表一个字符,不可以为空
      [a-z] [0-9]     代表任何一个小写字母
      
      [root@master 192.168.11.72 ~]$salt 'slav?' test.ping
      slave:
          True
      
      [root@master 192.168.11.72 ~]$salt '[a-z]lave' test.ping
      slave:
          True            salt海支持python的re正则表达式
  21. state模块定义主机状态

    1. 之前执行的远程命令,都是一个过程式的,类似一段shell或者python脚本执行,执行一次触发一次相同的功能。

    2. 那么大量的minion上运行远程命令就必须使用salt提供的“状态管理”了,状态是对minion的一种描述和定义,运维不需要关心部署是如何完成的,只需要描述minion需要达到什么状态。

    3. 接下来通过state模块部署nginx

    4. master端

      vim /etc/salt/master #打开注释,写入以下,必须严格遵循语法,空格
      file_roots:
        base:
          - /srv/salt/base
       dev:
         - /srv/salt/dev
       test:
         - /srv/salt/test
       prod:
         - / srv/salt/prod
      \#此步骤在master和minion都需要执行,都需要文件夹,和nginx.sls文件
      [root@master ~]$mkdir -p /srv/salt/{base,dev,test,prod}
      
      [root@slave  ~]$mkdir -p /srv/salt/{base,dev,test,prod}
      
      #这个nginx.sls状态文件,在master和minion上都得有[root@master /srv/salt/base]$cat nginx.sls
      nginx-install:
        pkg.installed:
          - name: nginx
      
      nginx-service:
        service.running:
          - name: nginx
          - enable: True
    5. 解释下nginx.sls描述文件sls配置文件都遵循YAML语言描述,第一条命令使用了pkg.install安装命令,相对于运行了yum install,而此时state模块会判断nginx是否安装了,如果没有安装就进行安装,安装了就什么都不做。状态描述都会遵循这个原则,只有检测到真实状态和所需状态不一就会执行此功能,这种性质叫做幂等性。

    6. 此时用state模块部署nginx软件,通过我们编写的nginx.sls描述性配置文件,命令行调用state模块的sls函数。

      #启动命令,此时slave已经安装且存活了nginx,进行状态管理
      [root@master  /srv/salt/base]$salt 'slave' state.sls nginx
    7. 可以去slave测试关闭nginx,删除nginx,重新执行命令,一样可以安装启动nginx,通过master检查slave的nginx状态。

      [root@master 192.168.199.155 /srv/salt/base]$salt 'slave' cmd.run 'ps -ef|grep nginx'
      slave:
          root       8543      1  0 Sep14 ?        00:00:00 nginx: master process /usr/sbin/nginx
          nginx      8544   8543  0 Sep14 ?        00:00:00 nginx: worker process
          root       8592   8591  0 00:03 ?        00:00:00 /bin/sh -c ps -ef|grep nginx
          root       8594   8592  0 00:03 ?        00:00:00 /bin/sh -c ps -ef|grep nginx
  22. Salt采集静态信息之Grains

    1. 如果你入职了,你的老板让你收集公司300台服务器的相关硬件信息,你是一台台登录呢?还是选择用salt收集呢?又或者用python的salt-api写脚本呢

    2. Grains 是saltstack组件中非常重要之一,在配置部署时候回经常使用,Grains记录minion的静态信息,比如常用属性,CPU、内存、磁盘、网络信息等。

    3. Minions的Grains信息是Minion启动时采集汇报给Master的Grains是以 key value形式存储的数据库,可以看做Host的元数据(metadata)Grains保存着收集到的客户端的详细信息如果slave机器数据变化,grains就过期了

    4. 在生产环境中需要自定义Grains,可以通过

    5. Minion配置文件

    6. Grains相关模块定义

    7. Python脚本定义salt 'slave' sys.doc grains#查看grains的命令用法

    8. Grains人为是描述minion本身固有的静态属性数据,列出主机所有Grains数据

      [root@master 192.168.11.72 ~]$salt 'slave' grains.items
      slave:
      \----------
      SSDs:
      biosreleasedate:
      05/19/2017
      biosversion:
      6.00  
      
      信息过长,已经省略
      
      salt 'slave' grains.ls #列出所有grains方法
    9. 检索某些数据

      [root@master 192.168.11.72 ~]$salt 'slave' grains.item os id host
      slave:
          ----------
          host:
              slave
          id:
              slave
          os:
              CentOS
    10. 利用Grains静态信息定位主机,超哥以前公司有100+的redhat操作系统,80+的centos,在不知道salt之前很是懵逼。。

      两种写法:salt '*' grains.item key1 key2 key3salt '*' -G#定位Cenots的机器[root@master 192.168.11.72 ~]$salt -G 'os:CentOS' test.ping
      slave:
          True#定位操作系统系统是7系列的机器
      [root@master 192.168.11.72 ~]$salt -G 'osrelease:7*' test.ping
      slave:
      True
      
      \#找出ip地址
      
      salt '*' grains.item fqdn_ip4
    11. 因此用grains.items列出所有的数据匹配主机,以及根据单一信息定位数据,Grains还可以自定义来满足不同的需求。

  23. 自定义设置Grains数据

    1. 设置数据salt 'slave' grains.setval cpu_num 8和查询数据salt 'slave' grains.item cpu_num

    2. 在master端设置Grains静态数据,原理会将此数据添加到minion服务器的配置文件的/etc/salt/grains

    3. 对于复杂的数据结构,可以添加灵活的JSON语法

      [root@master 192.168.11.72 ~]$salt 'slave' grains.setval cpu_info '["Intel","Xeon","10"]'
      slave:
          ----------
          cpu_info:
              - Intel
              - Xeon
              - 10
      [root@master 192.168.11.72 ~]$salt 'slave' grains.item cpu_info
      slave:
          ----------
          cpu_info:
              - Intel
              - Xeon
              - 10
    4. 此时可以检查minion服务器上的grains文件

      [root@slave 192.168.11.71 ~]$cat /etc/salt/grains
      cpu_info:
      - Intel
      - Xeon
      - '10'
      cpu_num: 8
    5. 因此Grains数据写入配置文件后,重启salt-minion服务,数据也不会丢失;想要删除可以通过grains.delval命令删除,或者去minion的配置文件删除配置一样完成操作(或者删除文件)。

      1.方法一,清空值
      [root@master 192.168.11.72 ~]$salt 'slave' grains.delval cpu_info
      slave:
          None
      [root@master 192.168.11.72 ~]$salt 'slave' grains.delval cpu_num
      slave:
          None2.方法二 删除minion的grains配置文件,重启服务
          
      [root@slave 192.168.11.71 ~]$rm -rf /etc/salt/grains
      [root@slave 192.168.11.71 ~]$!sys
      systemctl restart salt-minion

数据管理中心之Pillar组件

  1. Pillar也是saltstack组件中非常重要的组件之一,称作数据管理中心,经常配合states在大规模的配置管理中使用。

  2. Pillar是动态的,存储在master端,提供和给minion端

  3. Pillar在SaltStack中主要的作用是存储和定义配置管理中需要的一些数据,比如软件版本号,用户账号密码等,保证敏感数据不被其他minion看到

  4. 存储格式与Grains类似,都是YAML格式

  5. 在master配置文件中有一段Pillar settings选项专门定义Pillar的参数

    cat /etc/salt/master  #此配置代表pillar的工作根目录,在/srv/pillar下,然后可以新建sls文件
    #pillar_roots:
    #  base:
    #    - /srv/pillar
  6. 默认pillar的工作目录在/srv/pillar目录下,执行如下代码

    mkdir -p /srv/pillar
    #指定环境,标记,引用packages.sls和services.sls
    vim /srv/pillar/top.sls
    base:
      '*':
          - packages
          - services
    vim /srv/pillar/packages.sls
    nginx:
        packages-name: nginx
        version: 1.12.2
    
    vim /srv/pillar/packages.sls
    nginx:
        port: 80
        user: root
  7. 检查我们设置的pillar值

    [root@master 192.168.199.155 /srv/pillar]$salt '*' pillar.item nginx
    slave:
        ----------
        nginx:
            ----------
            packages-name:
                nginx
            port:
                80
            user:
                root
            version:
                1.12.2
  8. Pillar与Grains对比

    pillar与Grains对比
    
    类型     数据采集方式   应用场景                   定义位置
    Grains   静态         minion启动时收集  数据查询  目标选择  配置管理   minion
    Pillar   动态         master进行自定义  目标选择  配置管理  敏感数据   master

Python API调用SaltStack

  1. SaltStack本身提供salt(usr/bin/salt)来交互管理,但是去服务器上敲命令肯定不是一个长远之计,这时候python就体现了nb的功能。

  2. Python API就是给Python提供的API使用,需要在SaltStack master上运行

    [root@master  ~]$python
    Python 2.7.5 (default, Jul 13 2018, 13:06:57)
    [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import salt.client
    >>> local = salt.client.LocalClient()  #<salt.client.LocalClient object at 0x7f886dbdd850>
    >>> local.cmd('*','cmd.run',['hostname'])#向所有minion发送命令
    {'slave': 'slave'}
  3. 通过API获取saltstack的配置文件

    1. 获取master配置文件

      >>> import salt.config #导入salt配置模块
      >>> m_opts=salt.config.client_config('/etc/salt/master') #读取salt配置文件,得到一个字典数据
    2. 获取minion配置文件

      Python 2.7.5 (default, Jul 13 2018, 13:06:57)
      [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
      Type "help", "copyright", "credits" or "license" for more information.
      >>> import salt.client
      >>> salt.config.minion_config('/etc/salt/minion') #读取minion配置文件,得到字典数据,通过字典方法可以查看信息
  4. Python API介绍

    /usr/bin/salt默认使用的接口是LocalClient,该接口只能在salt master上使用
    [root@master  ~]$python
    Python 2.7.5 (default, Jul 13 2018, 13:06:57)
    [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import salt.client
    >>> local = salt.client.LocalClient()  #<salt.client.LocalClient object at 0x7f886dbdd850>
    >>> local.cmd('*','cmd.run',['hostname'])#向所有minion发送命令
    {'slave': 'slave'}
    1. 逐条返回结果,local.cmd_iter()

      >>> ret=local.cmd_iter('*','test.ping')
      >>> ret
      <generator object cmd_iter at 0x7f886d455c80>
      >>> for i in ret:
      ...     print i
      ...
      {'slave': {'retcode': 0, 'ret': True}}
    2. 菲波那切数列

      >>> local.cmd('*','test.fib',[10])
      {'slave': [[0, 1, 1, 2, 3, 5, 8], 2.1457672119140625e-06]}
    3. 检查minion服务器信息

      >>> local.cmd('*','cmd.run',['hostname'])
      {'slave': 'slave'}
      >>> local.cmd('*','cmd.run',['ifconfig'])
      >>> local.cmd('*','cmd.run',['crontab -l'])
      >>> local.cmd('*','cmd.run',['df -h'])
    4. 启停minion的服务,如nginx

      >>> local.cmd('*','service.stop',['nginx'])
      {'slave': True}
      >>> local.cmd('*','service.status',['nginx'])
      {'slave': False}
      >>> local.cmd('*','service.start',['nginx'])
      {'slave': True}

热门相关:斗神战帝   薄先生,情不由己   寂静王冠   豪门闪婚:帝少的神秘冷妻   仗剑高歌