Linux常见零碎问题汇总


这里主要记录在日常使用 Linux 时,遇到的一些零碎问题。不易写成独立文章,所以统一记录于此。

Linux常见零碎问题汇总


1. Ubuntu 发行版的支持时间

这里就是单纯记录下对应版本的官方支持时间,方便后续自己查看!

Linux常见零碎问题汇总 - Ubuntu发行版的支持时间

Linux常见零碎问题汇总 - Ubuntu发行版的支持时间


2. Postgres 版本的支持时间

这里就是单纯记录下对应版本的官方支持时间,方便后续自己查看!

Linux常见零碎问题汇总 - Postgres版本的支持时间


3. 机器宕机问题排除思路

简单记录一下系统宕机之后,主要排除思路和纪要!

  • [1] 服务器资源不足导致
    • 是否内存(OOM)/CPU/磁盘爆满导致服务器重启
    • 排除系统日志 /var/log/messages/var/log/dmesg
# 系统信息
服务器类型: cat /etc/redhat-release
操作系统版本: cat /etc/issue
内核版本: uname -a
Docker版本: docker --version

# 主要排除日志
/var/log/messages (系统启动后的信息和错误日志)
/var/log/dmesg    (系统日志守护进程的日志文件)
/var/log/boot.log (守护进程启动和停止相关的日志消息)
/var/log/kern.log (发行版中的日志文件)

# 次要排除日志
/var/log/secure  (与安全相关的日志信息)
/var/log/cron    (与定时任务相关的日志信息)
/var/log/maillog (与邮件任务相关的日志信息)
/var/log/spooler (与UUCP和news设备相关的日志信息)

# 用户登录日志
/var/log/wtmp (永久记录每个用户登录/注销及系统的启动/停机的事件)
/var/run/utmp (记录当前正在登录系统的用户信息)
/var/log/btmp (记录失败的登录尝试信息)
  • [2] 服务器硬件问题导致
    • 是否因为系统硬件原因导致服务器重启
    • 查看是否有硬件告警并收集硬件信息,报告厂商协助排查
# 基本信息收集
$ uptime     (查看系统运行时间/用户数/负载)
$ last       (查看最近系统重启的信息)
$ df -h      (查看各分区使用情况)
$ free -m    (查看内存使用量和交换区使用量)
$ nvidia-smi (查看驱动版本/硬件等相关信息)
  • [3] 触发服务器系统 Bug 导致
    • 是否触发系统 Bug 并生成 dump 文件
    • 检查是否是系统内核 Bug 导致,所以得看 kdump 在系统崩溃保留的信息
# 查看kdump日志(发生故障)
/var/crash/生产一个主机+故障时间目录
产生两个vmcore和vmcore-dmesg.txt文件

4. 显卡无法显示排除步骤

记录在显卡无法显示的时候,正确的排除方式和步骤!

  • 如果使用 nvidia-smi 命令没有看到正常的显卡和驱动信息,不管什么报错,先看下是否显卡正常挂载了,然后再处理和搜索解决方法。
# 查询显卡是否正常挂载
$ lspci -k | grep -e "VGA"
18:00.0 VGA compatible controller: NVIDIA Corporation Device

# 显示显卡型号
$ nvidia-smi -L
  • 然后根据安装 *.run 的时候提示的错误信息进行排除,并且建议安装新版本的驱动(因为其向后兼容)。
# 安装驱动
# 日志文件: /var/log/nvidia-installer.log
$ sudo sh NVIDIA-Linux-x86_64-$DRIVER_VERSION.run

# 安装驱动时关闭X服务: -no-x-check
# 安装驱动时禁用nouveau: -no-nouveau-check
# 只安装驱动文件不安装OpenGL文件: -no-opengl-files
  • 这里记录下,常见的相关报错信息,以及对应处理办法。
# 问题一
# 尝试卸载之后重启安装
# 没试过 https://hellozhaozheng.github.io/z_post/%E5%85%B6%E4%BB%96-Ubuntu%E7%B3%BB%E7%BB%9F%E4%B8%8B%E5%AE%89%E8%A3%85NVIDIA%E9%A9%B1%E5%8A%A8/
Unable to load the kernel module 'nvidia.ko'.
Please see the log entries 'Kernel module load error' and 'Kernel messages' at the end of the file 'xxx'

# 问题二
# 报错提示没有对应驱动匹配的显卡,就需要看下是否显卡正常挂载了
You do not appear to have an nvidia gpu supported by the 460.80 NVIDIA Linux graphics driver installed in this system.

# 问题三
# 提示没有找到显卡驱动,考虑是否驱动正常运行
NVIDIA-SMI has failed because it could not communicate with the NVIDIA driver.
Make sure that the latest NVIDIA driver is installed and running.

# 问题四
# 没试过 https://blog.csdn.net/qq_34361099/article/details/108052465
Unable to determine the device handle for GPU 0000:05:00.0: Unknown Error

# 问题五
# 查看kernel-devel和kernel-headers信息与当前os内核是否一致
be sure you have the 'kernel-source' or 'kernel-devel' RPM installed

5. RPO 和 RTO 的区别

故障发生时,需要了解两个指标!

  • RPO
    • Recovery Point Objective
    • 数据恢复点目标
    • 主要指的是业务系统所能容忍的数据丢失量
  • RTO
    • Recovery Time Objective
    • 恢复时间目标
    • 从灾难发生到业务系统恢复服务功能所需要的最短时间周期

6. 私有 CA 的创建流程

简单介绍私有 CA 证书以及签名的整体流程

为了 Nginx 在公网上搭建加密数据通道,首先可以使用 mTLS 技术进行双向的 TLS 验证,然后自己做 CA 给自己签发证书,然后搭建 Nginx 服务完成。

类型 名称 用途
CA ca.key CA 的私钥
Server ca.crt CA 的公钥(证书)
Server server.key 服务器端私钥
Server server.crt 服务器端公钥
Server server.csr 服务器端请求(部署不需要用到)
Client client.key 客户端的私钥
Client client.crt 客户端的公钥
Client client.csr 客户端的请求(部署不需要用到)
  • [1] 生成 CA 的私钥 Key - 妥善保管 - ca.key
    • 对于 CA 的私钥 Key 最好给一个密码保护
    • 每次使用这个 CA 签发证书的时候都需要输入密码
# genrsa: 生成RSA私钥
# -des3: 生成的Key使用des3进行加密;如果不加这个参数就不会提示让你输入密码
# 4096: 生成Key的长度;
$ sudo openssl genrsa -des3 -out ca.key 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
.............................++++...............++++
e is 65537 (0x010001)
Enter pass phrase for ca.key:<passphrase>
Verifying - Enter pass phrase for ca.key:<passphrase>
  • [2] 生成 CA 的公钥 Key - 证书 - ca.crt
    • 会询问你一些信息,比如地区,组织名字之类的
# req: 创建证书请求
# -new: 产生新的证书
# -x509: 直接使用x509产生新的自签名证书
# -days 365: 证书1年之后过期,省略表示永不过期
# key: 创建公共证书的私钥,会被提示输入私钥的密码
# -out: 生成的证书
$ sudo openssl req -new -x509 -days 365 -key ca.key -out ca.crt
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:CertAuth
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:
  • [3] 申请服务器端证书 - server.csr
    • 我们有了一对 CA 证书,ca.keyca.crt 两个文件
# 服务器端依旧创建一个私钥Key(不用保护了)
$ sudo openssl genrsa -out server.key 4096

# 不是直接生成证书,而是生成一个证书请求(这个.csr的文件就是请求签名)
# Organization Name: 不能和CA的一样
# Common Name: 必须要写一个,可以写一个不存在的域名,否则证书无法使用
$ sudo openssl req -new -key server.key -out server.csr
  • [4] 服务器端证书签名 - server.crt
    • 用我们的 CA 给这个服务器端证书签名
# x509: 公有证书的标准格式
# -CA: 使用CA对其签名
# -CAkey: CA的私钥key
# -set_serial 01: 签发的序列号,如果证书过期的话,可以直接用.csr修改序列号重新签一个,不需要重新生成.csr文件
$ sudo openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
  • [5] 验证生成的证书
    • 可以使用这条命令验证生成的证书是正常
    • 重复此流程再签发一个 client 端的证书
# 如下输入即可
$ sudo openssl verify -verbose -CAfile ca.crt server.crt
server.crt: OK
  • [5] 配置 Nginx 服务
    • ssl_certificate: 告诉 Nginx 使用哪一个公有证书
    • ssl_certificate_key: 此证书对用的私钥是什么,服务器需要有私钥才能工作
    • ssl_verify_client: 需要验证客户端的证书
    • ssl_client_certificate: 我们信任这个 CA 所签发的所有证书
# 使用自签证书 - Server端
server {
    listen 443 default_server ssl;
    listen [::]:443 default_server ssl;

    server_name _;
    ssl_certificate /data/cert/server.crt;
    ssl_certificate_key /data/cert/server.key;

    ssl_verify_client on;
    ssl_client_certificate /data/cert/ca.crt;

    location / {
        proxy_pass http://127.0.0.1:8000;
    }
}
# 使用自签证书 - Client端
upstream remote{
    server 127.0.0.1:443;
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

    location / {
        proxy_pass https://remote;
        proxy_ssl_trusted_certificate /home/vagrant/cert/ca.crt;
        proxy_ssl_verify on;
        proxy_ssl_server_name on;
        proxy_ssl_name proxy.example.com;

        proxy_ssl_certificate /home/vagrant/crt/client.crt;
        proxy_ssl_certificate_key /home/vagrant/cert/client.key;
    }
}

7. 普通用户执行特权指令

还是应该回顾下,之前掌握的基础知识!

  • [问题起因] 自己在测试机器上面新建了一个普通用户,当我后续使用的时候,发现竟然可以执行 newgrp 命令。按照常理来说,执行 newgrp 命令的话是需要输入密码才对的。
ls -lh /usr/bin/newgrp
-rwsr-xr-x 1 root root 40K Aug 21  2019 /usr/bin/newgrp
  • [解决方法] 最终发现,是因为该用户在 /etc/passwd/etc/group 文件中的权限不一致导致的(有可能是人为直接修改了配置文件导致的),即虽然该用户没有特权权限,但是其对应组是可以执行特权命令的。所以后续管理用户需要使用命令进行操作,并且需要对用户和组进行监控和告警,放置后续问题的出现。
    • pwck => 用来验证系统认证文件 /etc/passwd/etc/shadow 的内容和格式的完整性
    • grpck => 用于验证组文件 /etc/group/etc/gshadow 的完整性
# 用来验证系统认证文件内容和格式的完整性
# -q: 仅报告错误信息
# -s: 以用户id排序文件
# -r: 只读方式运行指令
$ sudo pwck -q [/etc/passwd /etc/shadow]

# 用于验证组文件的完整性
# -s: 以用户id排序文件
# -r: 只读方式运行指令
$ sudo grpck -q [/etc/group /etc/gshadow]
  • Linux 系统里的用户和群组密码,分别存放在 /etc/passwd/etc/group 文件中。因系统运作所需,任何人都得以读取它们,造成安全上的破绽。投影密码将文件内的密码改存在 /etc/shadow/etc/gshadow 文件内,只允许系统管理者读取,同时把原密码置换为 x 字符,只需执行 grpconv 就能开启群组投影密码。
# 默认系统都是开启的状态
$ sudo grpconv

8. 邮件被识别为垃圾邮件

此邮件类似于我们的垃圾邮件过滤器检测到的邮件

  • [问题起因] 使用其他外域邮箱给特定域名邮箱发送邮件,会概率性被拒收或者收进垃圾箱的情况。

Linux常见零碎问题汇总 - 邮件被识别为垃圾邮件

  • [解决方法] 查了下,发现官方建议需要进行 SPF 设置,将对于的域名加到 DNS TXT 解析里面,以下是 QQ 邮箱给出的示例,可以根据实际情况调整不同的域名信息。

Linux常见零碎问题汇总 - 邮件被识别为垃圾邮件

  • 配置上之后可以通过如下命令进行检测是否已经添加成功了,如果还是有问题的话,可以排除下是否是因为有 QoS 策略导致的,比如会检测和过滤有些关键字等。
# 检测是否添加成功
$ dig @8.8.8.8 -t TXT escapelife.site
; <<>> DiG 9.10.6 <<>> @8.8.8.8 -t TXT escapelife.site
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1752
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;escapelife.site.        IN    TXT

;; ANSWER SECTION:
;escapelife.site.        600    IN    TXT    "v=spf1 include:spf.mail.qq.com ~all"

;; Query time: 62 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Thu Mar 10 11:31:03 CST 2022
;; MSG SIZE  rcvd: 109

9. 在 Supervisor 中用符号

在 Supervisor 工具中添加环境变量如果存在百分比(%)的话,需要进行特殊的方式转义!

  • [问题起因] 在使用 Supervisor 工具部署服务的时候,给某个服务添加环境变量的之后,update 发现服务直接异常了。然后把某个环境变量删除掉之后,就正常了,挺奇怪的。
yaml.scanner.ScannerError: mapping values are not allowed here
  in "<unicode string>", line 1, column 64:
     ... id={'process_num': 0, 'ENV_PATH': '/usr/local/sbin:/usr/local/bi ...
                                         ^
  • [解决方法] 查了下,发现之前看到过这个内容,只不过是后续时间长了给忘记了,使用 % 号的话需要使用 %% 转义一下,才可以。

Linux常见零碎问题汇总 - 在Supervisor中用符号

Linux常见零碎问题汇总 - 在Supervisor中用符号


10. Linux 系统启动性能分析

分析系统性能,发现并解决引起性能不佳、启动时间长的问题

Linux 启动过程是值得学习关注的地方,因为 systemd-analyze 工具很多功能聚焦在启动 startup 过程。但是首先,要理解引导 boot 和启动 startup。引导阶段从 BIOS 加电自检(POST)开始,结束于内核完成加载并控制主机系统,然后是开始了启动过程,也是 systemd 日志的开始点。

  • [1] 启动的几个主要部分耗费的时间
    • 防火墙(BIOS)、内核启动、装载运行(initrd)、用户空间
$ systemd-analyze
Startup finished in 7.038s (firmware) + 32.527s (loader) + 2.323s (kernel) + 22.704s (userspace) = 1min 4.594s
graphical.target reached after 22.695s in userspace
  • [2] 哪个 systemd 单元的初始化时间最长
    • 果按照初始化时间长短排序,从多到少
$ systemd-analyze blame
1min 26.562s fstrim.service
     21.255s plymouth-quit-wait.service
      4.325s NetworkManager-wait-online.service
       838ms snapd.service
       602ms apt-daily-upgrade.service
       ......
  • [3] 启动过程中发生的时间关键的事件链
    • 前面有 + 的数字显示单元启动所需的时间
    • 前面有 @ 的数字表示单元激活开始启动所使用的绝对秒数
$ systemd-analyze critical-chain
graphical.target @22.695s
└─multi-user.target @22.695s
  └─plymouth-quit-wait.service @1.440s +21.255s
    └─systemd-user-sessions.service @1.435s +2ms
      └─network.target @1.432s
        └─NetworkManager.service @1.309s +122ms
          └─dbus.service @1.308s
            ......
  • [4] 转储了当前系统状态的大量数据
    • 有主要的启动时间戳
    • 每个 systemd 单元的列表,并对每个单元状态进行了完整描述
$ systemd-analyze dump
Timestamp firmware: 39.566011s
Timestamp loader: 32.527224s
Timestamp kernel: Fri 2022-04-08 15:07:47 CST
Timestamp userspace: Fri 2022-04-08 15:07:49 CST
Timestamp finish: Fri 2022-04-08 15:08:12 CST
Timestamp security-start: Fri 2022-04-08 15:07:49 CST
Timestamp security-finish: Fri 2022-04-08 15:07:49 CST
......
  • [5] 生成一个矢量图文件显示在引导和启动过程发生的事件
    • 时间轴上零点的左边是引导阶段,零点的右边是启动阶段
    • 这一小部分显示了内核、initrdinitrd 启动的进程
# svg
$ systemd-analyze plot > /tmp/bootup.svg

# dot
$ time systemd-analyze dot | dot -Tsvg > /tmp/test.svg
  • [6] 其他高级设置和操作
    • 条件子命令
    • 列出配置文件
    • 单元文件检查
    • 检查指定服务的安全级别
# 条件子命令
$ systemd-analyze condition \
    'ConditionKernelVersion = ! <4.0' \
    'ConditionKernelVersion = >=5.1' \
    'ConditionACPower=|false' \
    'ConditionArchitecture=|!arm' \
    'AssertPathExists=/etc/os-release' ; \
    echo $?

# 列出配置文件
$ systemd-analyze cat-config systemd/system/display-manager.service
$ systemctl cat backup*

# 单元文件检查
$ systemd-analyze verify /etc/systemd/system/backup.service

# 检查指定服务的安全级别
$ systemd-analyze security display-manager

11. 非交互下安装工具和软件

因为某些问题,我们不需要安装的时候遇到系统提示!

  • [问题起因 一] 打包镜像的时候,安装工具绝大多数都是不应该需要人为参与的(妨碍自动化),所以我们静默自动化安装。常常遇到问题是,安装时区、键盘布局等,需要我们选择时区和键盘布局。如下所示,是安装 chef 工具提示的对话框。

Linux常见零碎问题汇总 - 非交互下安装工具和软件

  • [解决方法 一] 可以通过 StackExchange 这解决方法,达到非交互安装。
# DEBIAN_FRONTEND
$ sudo DEBIAN_FRONTEND=noninteractive apt install -y -q chef

# DebConf
# 查出对应包的预配置项
$ sudo debconf-show chef

# 设置对应默认值
# 格式: {包名} {包名}/{配置项key} {配置项类型} {配置项value}
# 格式: package package/key {boolean,string} {true, some string}
$ echo "chef chef/chef_server_url string" | sudo debconf-set-selections
$ sudo apt-get install chef
# 查出对应包的预配置项
$ sudo debconf-show tzdata
* tzdata/Zones/Etc: UTC
  tzdata/Zones/US:
  tzdata/Zones/Asia:
  tzdata/Zones/Africa:
  tzdata/Zones/Pacific:
  tzdata/Zones/America:
  tzdata/Zones/Antarctica:
  tzdata/Zones/Atlantic:
  tzdata/Zones/Arctic:
  tzdata/Zones/Indian:
  tzdata/Zones/Australia:
* tzdata/Areas: Etc
  tzdata/Zones/Europe:

# 设置对应默认值
$ echo "tzdata tzdata/Areas select Etc" | debconf-set-selections
$ echo "tzdata tzdata/Zones/Etc select UTC" | debconf-set-selections
$ sudo apt-get install -y tzdata

  • [问题起因 二] 打包镜像的时候,容器里边 upgrade 卡住的话,看了一下是否配置文件冲突导致的。如果是的话,可以这么处理一下。
Setting up sudo (1.8.16-0ubuntu1.5) ...

Configuration file '/etc/sudoers'
==> Modified (by you or by a script) since installation.
==> Package distributor has shipped an updated version.
What would you like to do about it ?  Your options are:
    Y or I  : install the package maintainer's version
    N or O  : keep your currently-installed version
      D     : show the differences between the versions
      Z     : start a shell to examine the situation
The default action is to keep your current version.
*** sudoers (Y/I/N/O/D/Z) [default=N] ?
Setting up ubuntu-minimal (1.361.1) ...
  • [解决方法 二] 可以通过 StackExchange 这解决方法,达到非交互安装。可以通过 apt-getdpkg 传递一些选项来处理配置选择,通常可以这样做:
# 加下对应参数
$ apt-get install -y --no_install_recommends \
    -o Dpkg::Options::='--force-confdef' \
    -o Dpkg::Options::='--force-confold' <package_name>

# 如果没有解决的话,而已使用解决
DEBIAN_FRONTEND=noninteractive

12. 修复安装依赖报错问题

这是一种偷巧的方法,所以并不推荐使用!

  • [问题起因] 安装某个系统工具(xxx)的时候发现,发现有如下报错,提示 zfsutils-linux 需要更高版本的依赖。尝试使用提供的命令,进行解决,无果。
# 问题排除
$ sudo apt install --no-install-recommends -y xxx
Reading package lists... Done
Building dependency tree
Reading state information... Done
You might want to run 'apt --fix-broken install' to correct these.
The following packages have unmet dependencies:
 zfsutils-linux : Depends: libnvpair3linux (= 2.1.4-0york0~18.04) but 2.1.1-0york0~18.04 is to be installed
                  Depends: libuutil3linux (= 2.1.4-0york0~18.04) but 2.1.1-0york0~18.04 is to be installed
                  Depends: libzfs4linux (= 2.1.4-0york0~18.04) but 2.1.1-0york0~18.04 is to be installed
E: Unmet dependencies. Try 'apt --fix-broken install' with no packages (or specify a solution).

# 尝试修复
$ sudo apt --fix-broken install
Reading package lists... Done
Building dependency tree
Reading state information... Done
Correcting dependencies... Done
The following packages were automatically installed and are no longer required:
  ......
The following packages will be upgraded:
  libnvpair3linux libuutil3linux libzfs4linux
3 upgraded, 0 newly installed, 0 to remove and 121 not upgraded.
46 not fully installed or removed.
Need to get 0 B/355 kB of archives.
After this operation, 8,192 B of additional disk space will be used.
Do you want to continue? [Y/n] y
(Reading database ... 212110 files and directories currently installed.)
Preparing to unpack .../libnvpair3linux_2.1.4-0york0~18.04_amd64.deb ...
Unpacking libnvpair3linux (2.1.4-0york0~18.04) over (2.1.1-0york0~18.04) ...
dpkg: error processing archive /var/cache/apt/archives/libnvpair3linux_2.1.4-0york0~18.04_amd64.deb (--unpack):
  trying to overwrite '/lib/x86_64-linux-gnu/libnvpair.so.3.0.0', which is also in package libnvpair1linux 2.0.4-0york0~18.04
  ......
Errors were encountered while processing:
  /var/cache/apt/archives/libnvpair3linux_2.1.4-0york0~18.04_amd64.deb
  /var/cache/apt/archives/libuutil3linux_2.1.4-0york0~18.04_amd64.deb
  /var/cache/apt/archives/libzfs4linux_2.1.4-0york0~18.04_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
  • [解决方法] 其实问题可以通过更新系统软件包来处理这个问题(系统帮我们处理掉了),如果因为某些需求导致不能这样操作的话,则可以手动查找对应上述冲突的包,手动将其依赖删除掉,就可以了。
# 查找依赖
$ ls -lh /var/lib/dpkg/info/libnvpair3linux.list

# 手动处理
$ cat /var/lib/dpkg/info/libnvpair3linux.list
/.
/usr/share/lintian
/usr/share/lintian/overrides
/usr/share/lintian/overrides/libnvpair3linux
/lib/x86_64-linux-gnu/libnvpair.so.3

13. 在机器上使用 X11 做转发

远程机器,使用其图形化工具界面!

X11-forwarding 说简单点就是,可以通过一个支持 X ServerSSH 客户端连接到远程 Linux 服务器,可以在本地运行、操作一个远程 Linux 服务器上有图形界面的程序。其中,X11 中的 X 指的就是 X 协议,而 11 指的是采用 X 协议的第 11 个版本。

出于安全原因,OpenSSH 服务默认将 X11 转发请求绑定到本地回环地址上,并且在 DISPLAY 环境变量中将主机名设置为 “localhost”。在这样的设定下,一些 X11 客户端不能正确处理 X11 转发,这会导致如下的错误。要解决这个问题,在 /etc/ssh/sshd 配置文件中加入下面这几行,它可以将 X11 转发请求绑定到外网卡地址上。

  • 配置 X11 服务
# 配置服务
# https://linux.cn/article-4014-1.html
$ sudo vim /etc/ssh/sshd_config
X11Forwarding yes    # 支持转发
X11DisplayOffset 10  # 默认的显示窗口
X11UseLocalhost no   # 不监听本地回环地址
AddressFamily inet   # SSH服务禁止了IPv6(可选)

# 重启服务
$ sudo systemctl restart sshd
  • 本机使用 X11 服务
# Mac的话需要先安装工具
$ brew install xquartz

# 链接远程主机
$ ssh -v -X user@hostname

# 执行图形化工具(没有就安装下)
$ xeyes
  • 常见的报错信息汇总
# 配置不对
X11 forwarding request failed on channel 0

# 配置不对
x11 forwarding cannot open display localhost 10.0

# 配置不对
Unable to init server: Could not connect: Connection refused
(gedit:26888): Gtk-WARNING **: 17:00:04.268: cannot open display:

# Mac需要启动XQuartz工具
connect /tmp/.X11-unix/X10: No such file or directory

14. 监控是哪个进程写的文件

Find out which process is changing a file

  • 比如我们发现在 /var/log 目录下面有一个文件疯狂写文件,一会儿就几个 GB 的体量,这个时候就需要我们排除到底是哪个进行导致的呢?可以使用 auditctl 来监听对应文件,然后使用查询命令查询出对应进程。
# install
$ sudo apt-get install auditd
$ sudo auditctl -l

# config
/etc/audit/auditd.conf
# -w watch /etc/hosts
# -p warx watch for write, attribute change, execute or read events
# -k hosts-file is a search key
$ /sbin/auditctl -w /etc/hosts -p war -k hosts-file

# search
$ /sbin/ausearch -f /etc/hosts
time->Tue May 24 14:33:12 2022
type=PROCTITLE msg=audit(1653373992.503:379): proctitle="fcitx"
type=PATH msg=audit(1653373992.503:379): item=1 name="/tmp/xxxtmp.log" inode=4469 dev=00:23 mode=0100644 ouid=1000 ogid=1001 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
type=PATH msg=audit(1653373992.503:379): item=0 name="/tmp/" inode=1 dev=00:23 mode=041777 ouid=0 ogid=0 rdev=00:00 nametype=PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(1653373992.503:379): cwd="/dev/mqueue"
type=SYSCALL msg=audit(1653373992.503:379): arch=c000003e syscall=257 success=yes exit=15 a0=ffffff9c a1=7f0bd1206b4b a2=442 a3=1b6 items=2 ppid=1 pid=1720 auid=1000 uid=1000 gid=1001 euid=1000 suid=1000 fsuid=1000 egid=1001 sgid=1001 fsgid=1001 tty=(none) ses=1 comm="fcitx" exe="/usr/bin/fcitx" subj==unconfined key=(null)

15. 服务无法收到回调请求

升级服务器或者调优的时候,需要只要对应参数到底代表着什么,不懂就表示你用不到!

  • [问题起因] 流程是:服务 A 收到任务之后需要请求服务 B,等 B 处理完毕之后才可以继续执行。但是由于服务器升级、内核调优、机器迁移等操作,突然服务无法事情了,即 A 收不到 B 服务的回调了。但是排除服务(看日志)和端口(网络是通的)都是可用和通达的,并且手动调用是没有问题的。实在是没有办法了,最后只能抓包了,发现了如下所示的报错:
# 可用使用TCPDump或者WireShark工具
[TCP Retransmission] [TCP Port numbers reused] 61000 -> 80 xxx
# 统计已连接上的状态为established数量
$ netstat -na | grep ESTABLISHED | wc -l

# 查看80端口连接数
$ netstat -ant | grep -i "80" | wc -l

# 如果需要统计tcp连接每种状态的连接的数量
$ netstat -an | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
  • [解决方法] 搜一下相关信息,会发现是大多都是说 在高并发的情况导致服务的端口都已经用完了,但是显然我们这个服务并没有大量的并发,但是看着还是和内核参数有关。但是中的来说,还是因为内部网络不够稳定导致的。
# 客户端HTTP请求的头部的connection设置为keep-alive保持存活一段时间
# 现在的浏览器,一般都允许time_wait状态的socket被重用,让TIME_WAIT状态可以重用
# 这样即使TIME_WAIT占满了所有端口,也不会拒绝新的请求造成障
$ echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse

# 让TIME_WAIT尽快回收,我也不知是多久,观察大概是一秒钟(1MSL)
$ echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle

# 永久修复方式(默认均关闭)
$ sudo vim /etc/sysctl.conf
net.ipv4.tcp_retries1 = 3     # 放弃回应一个TCP连接请求前需要进行多少次重试
net.ipv4.tcp_syn_retries = 5  # 一个新建连接内核要发送多少个SYN连接请求才决定放弃(默认值是5)
net.ipv4.tcp_tw_reuse = 0     # 开启重用;让TIME_WAIT的socket可以重用
net.ipv4.tcp_tw_recycle = 0   # 开启TCP连接中TIME_WAIT的sockets快速回收
$ sudo sysctl -p

16. 清华 Apt 源特殊设置

这个只针对于清华源,阿里云现在开始限速了(不讲武德)!

  • [问题起因] 使用 apt update 检查更新的时候,发现使用 清华源 的地址,提示证书好像失效或错误了。
$ sudo apt update
Ign:1 https://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports focal InRelease
Ign:2 https://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports focal-updates InRelease
Ign:3 https://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports focal-backports InRelease
Ign:4 https://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports focal-security InRelease
Err:5 https://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports focal Release
  Certificate verification failed: The certificate is NOT trusted. The certificate chain uses expired certificate.  Could not handshake: Error in the certificate verification. [IP: 2402:f000:1:400::2 443]
Err:6 https://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports focal-updates Release
# https改为http
$ vim /etc/apt/sources.list

# 执行apt更新和创新安装证书
$ sudo apt-get update
$ sudo apt-get install --reinstall ca-certificates

# http改为https
$ vim /etc/apt/sources.list

17. 在 tar 包无法追加文件

发现了一个有趣的地方,但是想想也是合理的!

  • [问题起因] 使用 tar 压缩文件之后,后来发现又有新的文件或目录需要追加到压缩包里面,说是可以直接追加,但是自己执行发现并不可以。

  • [解决方法] 只能已归档的文件才能追加文件,即纯 tar 才可以追加文件,使用压缩过的就不可以了。
# 可使用来追加文件
$ tar -cvf test.tar.gz a.txt
$ tar -rvf test.tar.gz b.txt

# 即tar.gz是无法追加文件
# -z: 压缩文件
# -c: 归档文件
$ tar -zcvf test.tar.gz c.txt

# 查看归档内容
$ tar -tf test.tar.gz

18. 常见命令代理设置记录

记录下常见的工具,对应代理的变量设置!

Linux常见零碎问题汇总 - 常见命令代理设置记录


19. 常规服务发布模式

记录下常见的发布模式!

在一般情况下,升级服务器端应用,需要将应用源码或程序包上传到服务器,然后停止掉老版本服务,再启动新版本。但是这种简单的发布方式存在两个问题,一方面,在新版本升级过程中,服务是暂时中断的,另一方面,如果新版本有 BUG,升级失败,回滚起来也非常麻烦,容易造成更长时间的服务不可用。

蓝绿发布、滚动发布、灰度发布是常用的软件部署发布方式。它们在软件部署的方式和策略上有所不同,以达到在发布新版本时最小化影响,最大化保证服务的可用性和稳定性的目的。

  • 蓝绿发布 - Blue-Green Deployment
    • 优点:便于服务异常时的回退操作;减少停机时间
    • 缺点:运行完整的两个版本资源双倍;全局状态的应用(缓存等)需考虑如何同步数据

所谓蓝绿部署,是指同时运行两个版本的应用,蓝绿部署的时候,并不停止掉老版本,而是直接部署一套新版本,等新版本运行起来后,再将流量切换到新版本上。但是蓝绿部署要求在升级过程中,同时运行两套程序,对硬件的要求就是日常所需的二倍,比如日常运行时,需要 10 台服务器支撑业务,那么使用蓝绿部署,你就需要购置二十台服务器。

  • 滚动发布
    • 优点:解决资源双倍的问题;保证升级过程中不会停机且服务不会中断
    • 缺点:为了防止更新过程中的不稳定;需要实现流量控制能力及回滚策略

所谓滚动升级,就是在升级过程中,并不一下子启动所有新版本,是先启动一台新版本,再停止一台老版本,然后再启动一台新版本,再停止一台老版本,直到升级完成,这样的话,如果日常需要 10 台服务器,那么升级过程中也就只需要 11 台就行了。

但是滚动升级有一个问题,在开始滚动升级后,流量会直接流向已经启动起来的新版本,但是这个时候,新版本是不一定可用的,比如需要进一步的测试才能确认。那么在滚动升级期间,整个系统就处于非常不稳定的状态,如果发现了问题,也比较难以确定是新版本还是老版本造成的问题。

  • 灰度发布
    • 优点:减少了对用户的影响(流量控制);增加了部署的灵活性;提高了发布的质量
    • 缺点:部署成本较高(部署和流量控制等机制);需要更多的测试和监控;增加管理难度

灰度发布也叫金丝雀发布,在灰度发布开始后,先启动一个新版本应用,但是并不直接将流量切过来,而是测试人员对新版本进行线上测试,启动的这个新版本应用,就是我们的金丝雀。如果没有问题,那么可以将少量的用户流量导入到新版本上,然后再对新版本做运行状态观察,收集各种运行时数据,如果此时对新旧版本做各种数据对比,就是所谓的 A/B 测试。

当确认新版本运行良好后,再逐步将更多的流量导入到新版本上,在此期间,还可以不断地调整新旧两个版本的运行的服务器副本数量,以使得新版本能够承受越来越大的流量压力。直到将 100%的流量都切换到新版本上,最后关闭剩下的老版本服务,完成灰度发布。


20. Shebang 是什么

参考链接

我们常常在 shell 脚本中看到顶部的以 #! 作为开头的 shebang,其中初始字符 #! 告诉操作系统这不是常规二进制文件,而是需要通过解释器运行的东西,即  #!  之后的解释器。因此,你可以看到类似  #!/usr/bin/python 、 #!/usr/bin/awk 的行。

执行像  ./test.sh  这样的文件(#!/bin/sh),类似于调用以下命令: /bin/sh ./test.sh。但是,我们可能会在其他脚本里面看到 shebang 之后还有参数,比如:

  • #!/usr/bin/awk -f - 以脚本文件的形式传递脚本代码
  • #!/usr/bin/python -u - 以启用无缓冲输出

如果我们想为脚本添加额外参数的话,理想情况下就想到将其加到 shebang 里面,但是发现不起作用,将所有标志混合成一个字符串,不是我想要的所以也就不对了。

  • #!/usr/bin/awk -i inplace -f -翻译-> awk "-i inplace -f" file.awk
argv[0] argv[1] argv[2] argv[3] argv[4]
Linux /usr/local/bin/args -a -b --something ./file.txt
FreeBSD OpenBSD /usr/local/bin/args -a -b --something ./file.txt
macOS /usr/local/bin/args -a -b --something ./file.txt
OpenIndiana /usr/local/bin/args -a ./file.txt

文章作者: Escape
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Escape !
  目录