项目实战集

ping命令

Linux ping 命令用于检测主机。

执行 ping 指令会使用 ICMP 传输协议,发出要求回应的信息,若远端主机的网络功能没有问题,就会回应该信息,因而得知该主机运作正常。

-d 使用Socket的SO_DEBUG功能。
-c <完成次数> 设置完成要求回应的次数。
-f 极限检测。
-i<间隔秒数> 指定收发信息的间隔时间。
-I<网络界面> 使用指定的网络接口送出数据包。
-l<前置载入> 设置在送出要求信息之前,先行发出的数据包。
-n 只输出数值。
-p<范本样式> 设置填满数据包的范本样式。
-q 不显示指令执行过程,开头和结尾的相关信息除外。
-r 忽略普通的Routing Table,直接将数据包送到远端主机上。
-R 记录路由过程。
-s<数据包大小> 设置数据包的大小。
-t<存活数值> 设置存活数值TTL的大小。
-v 详细显示指令的执行过程。
-w <deadline> 在 deadline 秒后退出。

服务器状态检测脚本

使用for循环判断主机是否存活:

#!/bin/bash

ip_list="192.168.1.1 127.0.0.1 0.0.0.0"

for ip in $ip_list
do
        for count in {1..3};do
                ping -c1 -w1 $ip &>/dev/null
                if [ $? -eq 0 ];then
                        echo "[成功] $ip 通讯正常"
                        break
                fi
        done
        if [ $count -eq 3 ];then
                echo "[失败] $ip 通讯失败"
        fi
done

使用while循环判断主机是否存活:

#!/bin/bash

#ip_list="192.168.1.1 127.0.0.1 0.0.0.0"

while read ip
do
        count=1
        while [ $count -le 3 ];do
                ping -c1 -w1 $ip &>/dev/null
                if [ $? -eq 0 ];then
                        echo "[成功] $ip 通讯正常"
                        break
                fi
                count=$(($count+1))
        done
        if [ $count -eq 4 ];then
                echo "[失败] $ip 通讯失败"
        fi
done <ip.txt

xargs命令

xargs是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。

xargs可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。

常用选项

-d <定界符>:指定输入项的定界符,默认为换行符。
-I <占位符>:指定替代字符串,用于替换命令中的参数位置。
-n <数量>:指定每次执行的参数数量。
-t:显示实际执行的命令。
-p:提示用户确认是否执行命令

通过cat命令理解xargs用法

  • 原始文件

    root@sh:~# cat file.txt
    file1
    file2
    file3
  • 通过管道符号讲标准输出转换为标准输入传递给cat

    root@sh:~# cat file.txt|cat
    file1
    file2
    file3
  • 通过管道符号和xargs将标准输出转换为参数传递给cat

    root@sh:~# cat file.txt|xargs cat
    cat: file1: 无法访问: 没有那个文件或目录 (No such file or directory)
    cat: file2: 无法访问: 没有那个文件或目录 (No such file or directory)
    cat: file3: 无法访问: 没有那个文件或目录 (No such file or directory)

常见用法

  1. 查找并打包日志

    find . -name "*.log" |xargs tar -cvzf log.tar.gz
  2. 对日志文件进行文字查找

    find . -name "*.log" |xargs grep -n "error"
  3. 批量创建目录

    find  /var/log -maxdepth 1 -type d |xargs -I {} mkdir .{}

uniq命令

Linux uniq命令用于检查及删除文本文件中重复出现的行列,一般与 sort 命令结合使用。

uniq命令可检查文本文件中重复出现的行列。

-c或--count 在每列旁边显示该行重复出现的次数。
-d或--repeated 仅显示重复出现的行列。
-f<栏位>或--skip-fields=<栏位> 忽略比较指定的栏位。
-s<字符位置>或--skip-chars=<字符位置> 忽略比较指定的字符。
-u或--unique 仅显示出一次的行列。
-w<字符位置>或--check-chars=<字符位置> 指定要比较的字符。
--help 显示帮助。
--version 显示版本信息。
[输入文件] 指定已排序好的文本文件。如果不指定此项,则从标准读取数据;
[输出文件] 指定输出的文件。如果不指定此选项,则将内容显示到标准输出设备(显示终端)

文本文件包含以下内容:

Copy code
apple
banana
apple
orange
orange
apple

使用uniq -c命令来统计重复行的次数:

$ uniq -c data.txt
      1 apple
      1 banana
      2 apple
      2 orange
      1 apple

输出的每一行都包含两部分:重复行的次数和该行的内容。在上面的示例中,第一行的apple只出现了一次,第二行的banana只出现了一次,第三行的apple出现了两次,以此类推。

Nginx日志参数

变量名称 变量描述 举例说明
$remote_addr 客户端地址 113.140.15.90
$remote_user 客户端用户名称
$time_local 访问时间和时区 18/Jul/2012:17:00:01 +0800
$request 请求的URI和HTTP协议 “GET /pa/img/home/logo-alipay-t.png HTTP:/1.1″
$http_host 请求地址,即浏览器中你输入的地址(IP或域名) img.alipay.com10.253.70.103
$status HTTP请求状态 200
$upstream_status upstream状态 200
$body_bytes_sent 发送给客户端文件内容大小 547
$http_referer 跳转来源 https://cashier.alip/ay.com…/”
$http_user_agent 用户终端代理 “Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SV1; GTB7.0; .NET4.0C;
$ssl_protocol SSL协议版本 TLSv1
$ssl_cipher 交换数据中的算法 RC4-SHA
$upstream_addr 后台upstream的地址,即真正提供服务的主机地址 10.228.35.247:80
$request_time 整个请求的总时间 0.205
$upstream_response_time 请求过程中,upstream响应时间 0.002
  • 将以下内容保存到access.log文件中作为练习的日志文件:

    192.168.1.1 - - [18/Jul/2023:10:15:32 +0800] "GET /index.html HTTP/1.1" 200 2326 "https://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    192.168.1.2 - - [18/Jul/2023:10:15:35 +0800] "GET /about.html HTTP/1.1" 200 1452 "https://example.com/index.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    192.168.1.3 - - [18/Jul/2023:10:15:40 +0800] "GET /contact.html HTTP/1.1" 404 196 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15"
    192.168.1.1 - - [18/Jul/2023:10:16:02 +0800] "GET /products.html HTTP/1.1" 200 3201 "https://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    192.168.1.4 - - [18/Jul/2023:10:16:10 +0800] "GET /api/data HTTP/1.1" 200 512 "https://example.com/products.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    192.168.1.2 - - [18/Jul/2023:10:16:15 +0800] "GET /favicon.ico HTTP/1.1" 200 4286 "https://example.com/about.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    192.168.1.5 - - [18/Jul/2023:10:16:20 +0800] "GET /admin/login HTTP/1.1" 403 1024 "-" "Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36"
    192.168.1.3 - - [18/Jul/2023:10:16:25 +0800] "POST /submit-form HTTP/1.1" 302 0 "https://example.com/contact.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15"
    192.168.1.1 - - [18/Jul/2023:10:16:30 +0800] "GET /style.css HTTP/1.1" 200 1234 "https://example.com/index.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    192.168.1.6 - - [18/Jul/2023:10:16:35 +0800] "GET /script.js HTTP/1.1" 200 876 "https://example.com/products.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    192.168.1.2 - - [18/Jul/2023:10:16:40 +0800] "GET /images/logo.png HTTP/1.1" 200 5432 "https://example.com/about.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    192.168.1.4 - - [18/Jul/2023:10:16:45 +0800] "GET /api/user HTTP/1.1" 401 256 "https://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    192.168.1.5 - - [18/Jul/2023:10:16:50 +0800] "GET /robots.txt HTTP/1.1" 200 123 "-" "Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36"
    192.168.1.1 - - [18/Jul/2023:10:17:00 +0800] "GET /index.html HTTP/1.1" 200 2326 "https://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    192.168.1.7 - - [18/Jul/2023:10:17:05 +0800] "GET /404.html HTTP/1.1" 404 196 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"
  • 统计访问量最高的IP(sort + uniq)

    cat access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -10
    ​​解析​​:
    awk '{print $1}':提取日志中的IP($remote_addr)
    sort:排序,使相同IP相邻
    uniq -c:统计每个IP出现的次数
    sort -nr:按访问量降序排序
    head -10:显示前10个
  • 查找HTTP状态码分布(awk + sort + uniq)

    cat access.log | awk '{print $9}' | sort | uniq -c | sort -nr
    ​​解析​​:
    awk '{print $9}':提取$status(HTTP状态码)
    sort | uniq -c:统计各状态码出现次数
    sort -nr:按频率排序
  • 统计最频繁访问的URL(awk + sort + uniq)

    cat access.log | awk '{print $7}' | sort | uniq -c | sort -nr | head -20
    ​​解析​​:
    awk '{print $7}':提取$request中的URL
    sort | uniq -c:统计URL访问次数
    head -20:显示前20个热门URL
  • 查找耗时最长的请求(sort + xargs)​​

    cat access.log | sort -k10 -nr | head -5 | awk '{print "URL:", $7, "Time:", $10}'
    ​​解析​​:
    sort -k10 -nr:按$request_time(第10列)降序排序
    head -5:显示最慢的5个请求
    awk:格式化输出URL和耗时
  • 批量查找包含404错误的日志文件(xargs + grep)

    find /var/log/nginx/ -name "*.log" | xargs grep -n " 404 "

多机部署MySQL

实验环境搭建

  1. 本项目通过docker搭建实验环境,首先需要在centos7虚拟机中安装docker
    运行以下命令安装Docker

    # 安装依赖
    sudo yum install -y yum-utils device-mapper-persistent-data lvm2
    # 设置阿里镜像源
    sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    # 安装最新版本docker
    sudo yum install -y docker-ce
    # 启动docker
    sudo systemctl start docker
    sudo systemctl enable docker
    # 查看docker状态
    sudo systemctl status docker
  2. 获取并导入镜像

    • 镜像压缩包下载

    • 使用WinSCP传入虚拟机

    • 导入镜像

      # 导入镜像
      docker load -i openssh.tar
  3. 通过镜像linuxserver/openssh-server创建多个主机

    1. 创建主机1,默认ssh端口号2222,主机名设置为host1,外部ssh端口号2221

      sudo docker run -d --name host1\
       -e PASSWORD_ACCESS=true \
       -e USER_PASSWORD=password \
       -e USER_NAME=demo \
       -p 2221:2222 linuxserver/openssh-server:latest
    2. 创建主机2,默认ssh端口号2222,主机名设置为host2,外部ssh端口号2222

      sudo docker run -d --name host2 \
       -e PASSWORD_ACCESS=true \
       -e USER_PASSWORD=password \
       -e USER_NAME=demo \
       -p 2222:2222 linuxserver/openssh-server:latest
    3. 创建主机3,默认ssh端口号2222,主机名设置为host3,外部ssh端口号2223

      sudo docker run -d --name host3 \
       -e PASSWORD_ACCESS=true \
       -e USER_PASSWORD=password \
       -e USER_NAME=demo \
       -p 2223:2222 linuxserver/openssh-server:latest
  4. 通过sudo docker ps查看容器信息

  5. 容器常用命令

    ## 查看当前运行的容器状态
    sudo docker ps
    
    ## 停止容器
    sudo docker stop 容器名
    
    ## 删除容器
    sudo docker rm 容器名
    
    ## 进入正在运行的容器
    sudo docker exec -it 容器名 /bin/bash
    
    ##从容器中退出
    exit或者使用快捷键CTRL + p 然后CTRL + q
  6. 通过telnet localhost 2221验证centos和容器之间的网络

  7. 通过ssh -p 2221 demo@localhost验证ssh服务,使用用户名demo和密码password登录容器,在容器内使用exit断开ssh连接。

推送公钥到各个主机

  • ssh密钥登录原理

    我们一般使用 PuTTY 等 SSH 客户端来远程管理 Linux 服务器。但是,一般的密码方式登录,容易有密码被暴力破解的问题。所以,一般我们会将 SSH 的端口设置为默认的 22 以外的端口,或者禁用 root 账户登录。其实,有一个更好的办法来保证安全,而且让你可以放心地用 root 账户从远程登录——那就是通过密钥方式登录。

    密钥形式登录的原理是:利用密钥生成器制作一对密钥——一只公钥和一只私钥。将公钥添加到服务器的某个账户上,然后在客户端利用私钥即可完成认证并登录。

  1. ssh-keygen制作密钥对
  2. ls ~/.ssh查看密钥文件
  3. ssh-copy-id -p 2221 demo@localhost 推送公钥到目标主机
  4. ssh -p 2221 demo@localhost验证密钥登录

批量推送公钥

  1. centos虚拟机安装expect工具

    sudo yum install expect

    expect 是一个用于自动化交互式命令行工具的工具集,它可以用于编写脚本来处理需要与外部程序进行交互的场景。以下是 expect 常用的命令和用法:

    1. spawn:启动一个新的进程并与其进行交互。

      spawn ssh user@hostname

      上述命令将启动一个 SSH 连接,并与远程主机进行交互。

    2. expect:匹配预期的输出或交互,并执行相应的操作。

      expect "password:"
      send "mypassword\r"

      上述命令会等待输出中出现 “password:”,然后发送密码。

    3. send:向进程发送字符串。

      send "ls\r"

      上述命令会发送 “ls” 命令给进程。

  2. 批量推送公钥脚本

    #!/bin/bash
    
    port_list="2221 2223"
    password="password"
    
    for i in $port_list
    do
            /usr/bin/expect -c "
                    spawn ssh-copy-id -p $i demo@localhost
                    expect {
                    \"*connecting\" { send \"yes\r\"; exp_continue } }
                    expect {
                    \"*password\" { send \"$password\r\"; exp_continue } }
                    expect eof
                    "
    done
    

多机部署MySQL脚本

#!/bin/bash

port_list="2221 2222 2223"
password="password"

for i in $port_list
do
        ping -c1 -w1 -p $i localhost
        if [ $? -eq 0 ];then
                /usr/bin/expect -c "
                spawn ssh -p $i demo@localhost \"sudo apk add mysql mysql-client\"      
                expect {
                \"*password\" { send \"$password\r\";exp_continue}}
                expect eof
                "
        fi
done