Linux Network配置及工作原理

Linux Network不同发行版配置方法不同,管理工具纷繁复杂,即使是同一种发行版不同版本管理工具也不断变化。作为系统管理员,环境里可能有各种版本的系统,所以要理一理关于Network的配置思路。

发行版配置工具

  • Centos6 使用 network.service。
  • Centos7 network.service 和 NetworkManager.service并存。
  • Centos8 之后只使用 NetworkManager.service。
  • Ubuntu 17.10之后使用 netplan 前端,NetworkManager/networkd 后端。

network.service

Centos7虽然引入了NetworkManager工具但是,依旧可以使用network.service,直到今年(2024)年centos7才彻底EOL,所以相信大部分系统管理人员包括我自己,依旧停留在network.service管理思路上。

# 开启Centos7上纯粹用network.service管理
systemctl stop NetworkManager
systemctl disable NetworkManager

网络配置修改 /etc/sysconfig/network-scripts 下的 ifcfg-*文件,之后执行 service network restart,配置即可生效。
network.service会执行 /etc/rc.d/init.d/network start 启动网络服务,启动的过程中,使用 ip 命令启动各 device,使用 route 配置系统路由,使用 sysctl 配置等。

ifcfg-*配置参考手册

NetworkManager

最近公司推动停用Centos7/6,推动升级到RockyLinux 8.x,便在自己机器上装了个RockyLinux 8.10作为Playground熟悉。分分钟装完系统,开机网卡没配置(装机时候特意没开,想着自己配),/etc/sysconfig/network-scripts/目录依旧熟悉,重启网络systemctl restart network报Unit network.service not found,傻了只有NetworkManager,这玩意咱不会啊,先Google条命令nmcli con reload搞定,看来这坑必须填了。

NetworkNanager有两个组件:

  • NetworkManager daemon, 管理连接和监听并报告网络变化。
  • 管理前端, 比如 nmcli,一些 GUI 程序等。

NetworkManager daemon 依赖于 D-Bus 实现了前端管理接口,底层使用 netlink 跟内核交互。nmcli 跟 D-Bus 交互连接 NetworkManager daemon,获得信息以及配置网络。

从NetworkManager的命令行工具nmcli开始:

# nmcli help
Usage: nmcli [OPTIONS] OBJECT { COMMAND | help }

OBJECT
  g[eneral]       NetworkManager's general status and operations
  n[etworking]    overall networking control
  r[adio]         NetworkManager radio switches
  c[onnection]    NetworkManager's connections
  d[evice]        devices managed by NetworkManager
  a[gent]         NetworkManager secret agent or polkit agent
  m[onitor]       monitor NetworkManager changes

所有的操作都针对OBJECT,别的对象按下不表,两个核心的对象必须整明白。

第一个对象是device,也就是设备,怎么理解呢,一个设备对应一个网口,基本上ip link里看到的那些都有对应的设备,基本上可以认为就是物理的网卡,每个物理网卡都会是一个device,当然,有些虚拟的网卡,也会是一个device,比如网桥bridge等。

另外一个对象是connection,也就是连接,就是一系列配置,比如IP地址获取方式是DHCP或者手动配置,如果是手动配置,则配置IP地址,网关,DNS等等信息。

连接最终要被apply到某个device上的,针对同一个device,可以有多个connection,但是有且只能有一个活动的connection被apply到一个device。

结合这个场景就很容易理解了:针对笔记本的无线网卡,在公司,连接的是公司的WIFI,这就需要一个connection,到了家里,连接家里的WIFI,这就是另外一个connection,这俩都是针对同一个device的配置,但是不会同时起作用。这种场景在服务器上不太常见,服务器上基本配置成一个connection对应一个device。

查看设备

nmcli dev
DEVICE  TYPE      STATE      CONNECTION
eth0    ethernet  connected  eth0
lo      loopback  unmanaged  --

可以看到两个设备eth0和lo,其中eth0是以太网类型被NetworkManager管理,对应的连接配置为eth0,状态为connected,lo是loopback目前不被NetworkManager所管理,状态为unmanaged。

查看连接

nmcli con
NAME  UUID                                  TYPE      DEVICE
eth0  4e4a729c-8303-4acf-a636-e8bb97184b14  ethernet  eth0

可以看到所有的连接列表。

查看连接详情

nmcli con show eth0
connection.id:                          eth0
...
ipv4.method:                            auto
...
ipv6.method:                            auto
...

可以看到大量的该连接的配置信息。

添加连接

# 对eth0添加一个静态IP配置的连接命名为eth0-static
nmcli con add type ethernet con-name eth0-static ifname eth0 ipv4.method manual ipv4.addresses "192.168.31.222/24" ipv4.gateway 192.168.31.1 ipv4.dns 192.168.31.1 ipv6.method auto
nmcli con
NAME         UUID                                  TYPE      DEVICE
eth0         4e4a729c-8303-4acf-a636-e8bb97184b14  ethernet  eth0
eth0-static  546f5039-130a-4ac7-af22-afdce2bc8a04  ethernet  --

对eth0添加了一个eth0-static连接,但是当前生效的仍为eth0连接。

切换连接

# 切换过程会导致ssh等连接断开
nmcli con up eth0-static
nmcli con
NAME         UUID                                  TYPE      DEVICE
eth0-static  546f5039-130a-4ac7-af22-afdce2bc8a04  ethernet  eth0
eth0         4e4a729c-8303-4acf-a636-e8bb97184b14  ethernet  --

可以看到现在eth0设备生效的连接为eth0-static。

配置持久化

命令行操作了一大堆,那么这些配置能持久化吗?重启了机器之后还会有么?如果有,那这些配置是保存在哪里的?我能不能不用nmcli这个命令行工具了,使用配置文件,能完成网络的配置么?

这些问题的答案都是肯定的!

首先呢,针对老版本network-scripts,也就是存放在/etc/sysconfig/network-scripts/目录下的那些ifcfg-*开头的配置文件,NetworkManager通过一个ifcfg-rh plugin去识别,这个插件在RHEL里是默认开启的,通过nmcli创建或者修改connections,都会同步到这个目录下对应的配置文件里。另外NetworkManager还会读取/etc/NetworkManager/system-connections/目录下的配置文件,通过nmcli创建和修改的其他类型的connections,比如ovs-bridge, dummy也会同步写入到对应目录下。

ll /etc/sysconfig/network-scripts
-rw-r--r--. 1 root root 269 Aug 16 22:45 ifcfg-eth0
-rw-r--r--  1 root root 349 Aug 17 07:07 ifcfg-eth0-static

所以可以到这两个目录下直接修改配置文件来配置网路,修改后需要手动执行nmcli connection load xxx手动重载单个配置或执行nmcli con reload重新加载所有的配置文件。加载完成后,要想配置真正生效,还需要执行nmcli con down xxx; nmcli con up xxx或者nmcli device reapply xxx来真正让配置生效。

删除连接

nmcli con del eth0-static
Connection 'eth0-static' (546f5039-130a-4ac7-af22-afdce2bc8a04) successfully deleted.
ll /etc/sysconfig/network-scripts
-rw-r--r--. 1 root root 269 Aug 16 22:45 ifcfg-eth0

可以看到命令行删除的eth0-static在/etc/sysconfig/network-scripts目录下的配置文件也同步删除了。

netplan

TODO

参考

https://exfly.github.io/linux_config_network/#netplan
https://www.ichenfu.com/2021/02/16/networkmanager-tutorial/

阅读全文

CentOS 7 EOL 更换YUM源

CentOS 7结束了生命周期(EOL),CentOS官方删除了原mirrorlist子域名的解析,如果仍需要使用CentOS 7系统中的一些安装包,可以如下操作,切换一下yum源。

cp -r /etc/yum.repos.d /etc/yum.repos.d.bak
sed -i -r -e 's|^mirrorlist=|#mirrorlist=|g' -e 's|^#?baseurl=http://mirror.centos.org/centos|baseurl=https://vault.centos.org/centos|g' -e 's|^#?baseurl=http://mirror.centos.org/altarch|baseurl=https://vault.centos.org/altarch|g' -e 's|^#?baseurl=http://download.fedoraproject.org|baseurl=http://download.fedoraproject.org|g' /etc/yum.repos.d/CentOS-*.repo
yum clean all && yum makecache
阅读全文

Alpine Linux DNS问题排查记录

问题现场

kubernetes coredns配置

.:53 {
        errors
        health
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
        }
        hosts /etc/coredns/NodeHosts {
          ttl 60
          reload 15s
          fallthrough
        }
        prometheus :9153
        forward . 172.x.8.8 {
          prefer_udp
        }
        cache 30
        loop
        reload
        loadbalance
        log
    }

pod resolv.conf配置

nameserver 10.43.0.10
search default.svc.cluster.local svc.cluster.local cluster.local svc.inner
options ndots:5

预期解析:

  • 集群内service用服务名解析到集群内服务。
  • svc.inner域内forward到172.x.8.8内网dns上,解析到内网dns注册的服务。
  • 其他公共域通过内网172.x.8.8的再上游,同样可以解析。

实际现象:

  • baidu.com在使用ubuntu基础镜像的pod内可以ping通。
  • baidu.com在使用alpine linux 3.15基础镜像的pod内报bad address,其他内网域名但是不是svc.inner域的报could not resolve host。

根因分析

当程序使用系统libc库做dns resolv的时候,走resolv.conf文件的配置,使用非完全限定域(即后面不带".", “baidu.com.“为完全限定,“baidu.com"为非完全限定)且”.“数量不超过ndots配置(这里kubernetes默认是5)时会走search的配置,超过ndots会认为约等于完全限定直接解析。

search逻辑是,在请求域名后面拼上配置的子域,逐个向后搜索解析,如果都找不到最后直接使用请求域名做解析,所以解析域名尝试如下。

baidu.com.default.svc.cluster.local.
baidu.com.svc.cluster.local.
baidu.com.cluster.local.
baidu.com.svc.inner.
baidu.com.

打开集群coredns的日志抓alpine/musl libc的请求解析日志如下:

[INFO] 10.42.0.84:42628 - 64655 "AAAA IN baidu.com.default.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.000218161s
[INFO] 10.42.0.84:42628 - 64204 "A IN baidu.com.default.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.00024845s
[INFO] 10.42.0.84:51564 - 50608 "AAAA IN baidu.com.svc.cluster.local. udp 45 false 512" NXDOMAIN qr,aa,rd 138 0.000113998s
[INFO] 10.42.0.84:51564 - 50368 "A IN baidu.com.svc.cluster.local. udp 45 false 512" NXDOMAIN qr,aa,rd 138 0.000119976s
[INFO] 10.42.0.84:55236 - 16067 "AAAA IN baidu.com.cluster.local. udp 41 false 512" NXDOMAIN qr,aa,rd 134 0.00011871s
[INFO] 10.42.0.84:55236 - 15864 "A IN baidu.com.cluster.local. udp 41 false 512" NXDOMAIN qr,aa,rd 134 0.00010077s
[INFO] 10.42.0.84:57937 - 2123 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059392615s
[INFO] 10.42.0.84:57937 - 1930 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.061797511s
[INFO] 10.42.0.84:57937 - 2123 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059379512s
[INFO] 10.42.0.84:57937 - 1930 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.062035159s
[INFO] 10.42.0.84:57937 - 2123 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059311395s
[INFO] 10.42.0.84:57937 - 1930 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.061721482s
[INFO] 10.42.0.84:57937 - 2123 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059639921s
[INFO] 10.42.0.84:57937 - 1930 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.061894263s
[INFO] 10.42.0.84:57937 - 2123 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059525564s
[INFO] 10.42.0.84:57937 - 1930 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.062518585s
[INFO] 10.42.0.84:57937 - 2123 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059316764s
[INFO] 10.42.0.84:57937 - 1930 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.061810188s

ubuntu/glibc的请求日志如下:

[INFO] 10.42.0.75:49573 - 11268 "AAAA IN baidu.com.app-ops.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.000235088s
[INFO] 10.42.0.75:49573 - 59129 "A IN baidu.com.app-ops.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.000188461s
[INFO] 10.42.0.75:54693 - 6359 "AAAA IN baidu.com.svc.cluster.local. udp 45 false 512" NXDOMAIN qr,aa,rd 138 0.00012188s
[INFO] 10.42.0.75:54693 - 44242 "A IN baidu.com.svc.cluster.local. udp 45 false 512" NXDOMAIN qr,aa,rd 138 0.000096248s
[INFO] 10.42.0.75:34199 - 10294 "A IN baidu.com.cluster.local. udp 41 false 512" NXDOMAIN qr,aa,rd 134 0.000104275s
[INFO] 10.42.0.75:34199 - 64057 "AAAA IN baidu.com.cluster.local. udp 41 false 512" NXDOMAIN qr,aa,rd 134 0.000173845s
[INFO] 10.42.0.75:42076 - 10254 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059601407s
[INFO] 10.42.0.75:42076 - 24081 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.062046559s
[INFO] 10.42.0.75:42076 - 24081 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059077476s
[INFO] 10.42.0.75:42076 - 10254 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.061514225s
[INFO] 10.42.0.75:52980 - 30220 "AAAA IN baidu.com. udp 27 false 512" NOERROR qr,aa,rd,ra 97 0.000639532s
[INFO] 10.42.0.75:52980 - 39944 "A IN baidu.com. udp 27 false 512" NOERROR qr,rd,ra 77 0.024779792s

baidu.com.svc.inner.在内网dns上肯定是不存在的(我们的内网dns也是用coredns),返回了一个SERVFAIL状态码。

问题就出在这:

  • glibc在DNS服务器返回SERVFAIL后,继续向后搜并最终返回到根域”.“解析获取到了NOERROR 正确的DNS结果。
  • musl libc认为SERVFAIL是DNS服务器的错误,应该报告给调用者,并且不向后继续搜了,并且还不返回到根域”.",所以就获取不到结果了。

musl libc和glibc这个行为差异,有不同的观点,所以至今(2024-07-19)还是这样的行为,也有相关的patch, 如: https://www.openwall.com/lists/musl/2018/03/30/6 并未合并。

个人观点: musl的态度没错,DNS服务器的实现返回的状态码不符合语义,但从客户端兜底和大家都错了这么多年了讲,咱就别较真了呗。

问题解决

最简单的方法:生产别用alpine镜像。

个人当场的解决方法: 因为我是开发环境,没有调用内网其他服务的需要,就在自己集群干掉了svc.inner内网域,没有人返回SERVFAIL了,就没有问题了。

实测一波,把最后一个域改成svc.lan,这个svc.lan forward到内网dns,不是内网的私域会再次forward到公共dns解析,返回NXDOMAIN,musl认为没问题,继续向后搜索到根域,就正确获取结果了。

所以musl libc是对的?DNS服务器的问题: 是自己的域,自己没有记录,为啥返回SERVFAIL。

貌似基于coredns写插件定义dns很容易犯"不标准"这个错?自己遇到不止一次基于coredns开发做权威的问题了,待有空研究研究coredns插件的玩法。

[INFO] 10.42.0.84:55744 - 20786 "AAAA IN baidu.com.default.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.000199026s
[INFO] 10.42.0.84:55744 - 20370 "A IN baidu.com.default.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.000095497s
[INFO] 10.42.0.84:47264 - 56647 "AAAA IN baidu.com.svc.cluster.local. udp 45 false 512" NXDOMAIN qr,aa,rd 138 0.000128401s
[INFO] 10.42.0.84:47264 - 56392 "A IN baidu.com.svc.cluster.local. udp 45 false 512" NXDOMAIN qr,aa,rd 138 0.00009345s
[INFO] 10.42.0.84:41203 - 59447 "AAAA IN baidu.com.cluster.local. udp 41 false 512" NXDOMAIN qr,aa,rd 134 0.00014027s
[INFO] 10.42.0.84:41203 - 59202 "A IN baidu.com.cluster.local. udp 41 false 512" NXDOMAIN qr,aa,rd 134 0.000207786s
[INFO] 10.42.0.84:54762 - 27818 "AAAA IN baidu.com.svc.lan. udp 35 false 512" NXDOMAIN qr,aa,rd,ra 110 0.000680326s
[INFO] 10.42.0.84:54762 - 27556 "A IN baidu.com.svc.lan. udp 35 false 512" NXDOMAIN qr,rd,ra 110 0.031160567s
[INFO] 10.42.0.84:35257 - 46005 "A IN baidu.com. udp 27 false 512" NOERROR qr,rd,ra 77 0.008211487s
[INFO] 10.42.0.84:35257 - 46267 "AAAA IN baidu.com. udp 27 false 512" NOERROR qr,rd,ra 97 0.196307927s

其他发现

一番研究alpine/musl libc的dns resolv实现,返现和传统不一致的地方还不止这一处。

alpine linux 3.18/musl libc 1.2.4之前,当dns udp结果大于512字节,会截断就获取不到正确结果了,因为貌似按照rfc截断语义,是这样,没毛病。但是传统大部分resolve实现大于512字节的结果会fallback 使用tcp。

也许是经不住大家diss了,musl终于在去年(2023)加上了dnc fallback tcp的实现,这个commit

参考链接

https://stackoverflow.com/questions/65181012/does-alpine-have-known-dns-issue-within-kubernetes
https://wiki.musl-libc.org/functional-differences-from-glibc.html#Name-Resolver/DNS
https://git.musl-libc.org/cgit/musl/tree/src/network/lookup_name.c?h=v1.2.4#n190
https://www.openwall.com/lists/musl/2018/03/30/6
https://help.dnsfilter.com/hc/en-us/articles/4408415850003-DNS-return-codes

阅读全文

Rsync工具

rsync是一个用于文件同步和备份的命令行工具,它可以在本地或远程系统之间同步文件和目录。

服务端

全局参数

在文件中[module]之前参数是全局参数,rsync允许使用"[global]“模块名称来指示全局参数部分的开始。

可以在配置文件的全局部分中包含任何模块参数,这样提供的值将成为该参数的默认值。

motd file
此参数允许您指定要在每次连接时显示给客户端的“每日消息”。通常包含站点信息和任何法律声明。默认值为没有motd文件。启动守护进程时,可以通过--dparam=motdfile=FILE命令行选项覆盖此设置。

pid file
此参数告诉rsync守护进程将其进程ID写入该文件。如果文件已经存在,则rsync守护进程将中止而不是覆盖该文件。启动守护进程时,可以通过--dparam=pidfile=FILE命令行选项覆盖此设置。

port
您可以通过指定此值(默认为873)来覆盖守护进程的默认端口号。如果守护进程由inetd运行,则此设置将被忽略,并且将被--port命令行选项所取代。

address
您可以通过指定此值来覆盖守护进程的默认IP地址。如果守护进程由inetd运行,则此设置将被忽略,并且将被--address命令行选项所取代。

socket options
此参数可以为喜欢尽可能调整系统的人提供无尽的乐趣。您可以设置各种可能使传输更快或更慢的套接字选项!有关一些可能设置的选项的详细信息,请参阅setsockopt()系统调用的man页。默认情况下,不设置任何特殊的套接字选项。这些设置也可以通过--sockopts命令行选项指定。

listen backlog
当守护进程侦听连接时,您可以覆盖默认的等待队列长度。默认值为5。

模块参数

comment
该参数指定一个描述字符串,当客户端获取可用模块列表时,该字符串将显示在模块名称旁边。默认情况下没有评论。

path
该参数指定守护程序文件系统中要在此模块中提供的目录。您必须为CWrsyncd.conf中的每个模块指定此参数。

use chroot
如果"use chroot"参数为true,则rsync守护程序将在与客户端开始文件传输之前,将其根目录更改为指定的路径。这样做的好处是能够额外防止可能存在的实现安全漏洞,但缺点是需要超级用户权限,不能跟踪绝对路径或位于新根目录之外的符号链接,并且会复杂化通过名称保留用户和组。

numeric ids
启用此参数会禁用当前守护程序模块中用户和组的名称映射。这将阻止守护程序尝试加载任何与用户/组相关的文件或库。启用此参数使传输行为看起来就像客户端已经传递了--numeric-ids命令行选项。默认情况下,此参数对于chroot模块是启用的,对于非chroot模块是禁用的。除非您采取了确保模块具有必要的资源以进行名称转换并且不可能更改这些资源的步骤,否则不应启用chroot启用的模块上的此参数。

charset
这指定了模块文件名所采用的字符集名称。如果客户端使用 --iconv选项,无论实际传递的字符集是什么,守护进程将使用charset参数的值。这样可以使得守护进程在 chroot 模块中支持字符集转换而无需额外文件,并且确保名称转换以一致的方式进行。如果未设置charset参数,则拒绝 --iconv 选项,就像通过refuse options指定了iconv一样。

max connections
此参数允许您指定允许的最大同时连接数。当达到最大连接数时,任何连接的客户端都会收到一条消息告知他们稍后再试。默认值为0,表示没有限制。负值禁用该模块。还请参阅 lqlock filerq 参数。

log file
当 log file参数设置为非空字符串时,rsync 守护进程将将消息记录到指定的文件中,而不是使用 syslog。如果对每个模块而不是全局设置进行了这个值的设置,全局日志仍将包含任何授权失败或配置文件错误消息。
如果守护进程无法打开指定的文件,它将回退到使用 syslog,并输出关于失败的错误信息。(请注意,以前无法打开指定日志文件被视为致命错误。)

syslog facility
此参数允许您指定从 rsync 守护进程记录消息时要使用的 syslog 设施名称。您可以使用系统上定义的任何标准 syslog 设施名称。常见的名称有 auth、authpriv、cron、daemon、ftp、kern、lpr、mail、news、security、syslog、user、uucp、local0、local1、local2、local3、local4、local5、local6 和 local7。默认值为 daemon。如果log file设置为非空字符串(无论是在每个模块的设置中设置,还是从全局设置继承),此设置将不起作用。

max verbosity
此参数允许您控制守护程序生成的最大冗长信息量(因为这些信息会记录在日志文件中)。默认设置为1,允许客户端请求一级冗长度。

lock file
此参数指定用于支持“max connections”参数的文件。rsync守护程序在该文件上使用记录锁定以确保不超过共享锁定文件的模块的最大连接数限制。默认设置为/var/run/rsyncd.lock。

read only
此参数确定客户端是否可以上传文件。如果“read only”为true,则任何尝试的上传都将失败。如果“read only”为false,则如果守护程序端的文件权限允许,可以进行上传。默认情况下,所有模块都是只读的。

write only
此参数确定客户端是否可以下载文件。如果“write only”为true,则任何尝试的下载都将失败。如果“write only”为false,则如果守护程序端的文件权限允许,可以进行下载。默认情况下,此参数被禁用。

list
此参数确定当客户端请求列出可用模块时,是否应列出此模块。通过将其设置为false,您可以创建隐藏模块。默认情况下,模块是可列出的。

uid
此参数指定在进行与该模块之间的文件传输时应作为守护程序以root身份运行时的用户名或用户ID。与“gid”参数结合使用,确定可用的文件权限。默认设置为-2,通常为用户“nobody”。

gid
此参数指定在进行与该模块之间的文件传输时应作为守护程序以root身份运行时的组名或组ID。这与“uid”参数相辅相成。默认设置为-2,通常为组“nobody”。

fake super
为一个模块设置“fake super = yes”会使守护端表现得好像已经指定了“--fake-user”命令行选项一样。这允许存储文件的全部属性,而无需实际将守护程序运行为root。

exclude
这个参数接受一个以空格分隔的守护进程排除模式列表。与客户端的--exclude选项一样,模式可以使用“-”或“+”来显式指示排除/包含。对于给定的模块,只能应用一个“exclude”参数。有关排除文件如何影响守护进程的详细信息,请参见“filter”参数。

include
使用“include”参数覆盖“exclude”参数的效果。对于给定的模块,只能应用一个“include”参数。有关排除文件如何影响守护进程的详细信息,请参见“filter”参数。

exclude from
该参数指定了守护进程上包含守护进程排除模式的文件的名称,空格分隔。对于给定的模块,只能应用一个“exclude from”参数;如果有多个排除文件,则可以将它们指定为“filter”参数中的合并文件。有关排除文件如何影响守护进程的详细信息,请参见“filter”参数。

include from
类似于“exclude from”的参数,用于守护进程包含模式的文件。对于给定的模块,只能应用一个“include from”参数。有关排除文件如何影响守护进程的详细信息,请参见“filter”参数。

incoming chmod
此参数允许您指定一组逗号分隔的chmod字符串,这些字符串将影响所有传入文件(由守护进程接收的文件)的权限。这些更改发生在所有其他权限计算之后,即使在客户端未指定--perms时,它也会覆盖目标默认和/或现有权限。有关此字符串格式的信息,请参阅--chmod rsync选项的描述和chmod(1)手册页。

outgoing chmod
此参数允许您指定一组逗号分隔的chmod字符串,这些字符串将影响所有传出文件(从守护进程发送的文件)的权限。这些更改首先发生,使发送的权限看起来与存储在文件系统中的权限不同。例如,您可以在服务器上禁用组写入权限,同时对客户端来说它仍然是打开的。有关此字符串格式的信息,请参阅--chmod rsync选项的描述和chmod(1)手册页。

auth users
此参数指定一个以逗号和空格分隔的用户名列表,这些用户名将被允许连接到该模块。这些用户名不需要存在于本地系统上。用户名还可以包含shell通配符字符。如果设置了“auth users”,则客户端将被要求提供用户名和密码来连接到该模块。用于此交换的是挑战-响应身份验证协议。明文用户名和密码存储在“secrets file”参数指定的文件中。默认情况下,所有用户都可以不需要密码连接(称为“anonymous rsync”)。

secrets file
该参数指定包含用于认证此模块的用户名:密码对的文件名。仅当指定了auth users参数时才会查询该文件。该文件以行为基础,每行包含由单个冒号分隔的用户名:密码对。以井号(#)开头的任何行都被视为注释并被跳过。密码可以包含任何字符,但请注意,许多操作系统限制可以在客户端输入的密码长度,因此您可能发现超过8个字符的密码无法工作。

strict modes
此参数确定是否检查秘密文件的权限。如果strict modes为true,则secrets file不得被除rsync守护进程所运行的用户ID之外的任何用户ID读取。如果strict mod为false,则不执行检查。默认值为true。添加此参数是为了适应在Windows操作系统上运行的rsync。

hosts allow
此参数允许您指定与连接客户端的主机名和IP地址匹配的模式列表。如果没有模式匹配,则拒绝连接。

hosts deny
该参数允许您指定与连接客户端的主机名和IP地址匹配的模式列表。如果模式匹配,则拒绝连接。有关更多信息,请参阅“hosts allow”参数。
默认情况下,没有“hosts deny”参数,这意味着所有主机都可以连接。

ignore errors
该参数告诉rsyncd在决定是否运行传输的删除阶段时忽略守护程序上的I/O错误。通常,如果发生任何I/O错误,rsync会跳过--delete步骤,以防止由于临时资源短缺或其他I/O错误而造成灾难性的删除。在某些情况下,此行为是适得其反的,因此您可以使用此参数关闭此行为。

ignore nonreadable
这告诉rsync守护进程完全忽略用户无法读取的文件。这对于可能在目录中包含一些不可读文件的公共存档非常有用,系统管理员不希望这些文件被看到。

transfer logging
此参数启用了按文件的下载和上传进行日志记录,格式与ftp守护进程使用的格式类似。守护进程始终在传输结束时记录传输,因此如果传输被中止,则日志文件中不会提及。

log format
该参数允许您在启用传输日志时指定用于记录文件传输的格式。

timeout
此参数允许您覆盖此模块的I/O超时客户端选择。使用此参数,您可以确保rsync不会永远等待死亡的客户端。超时以秒为单位指定。零值表示没有超时,并且是默认值。对于匿名rsync守护进程,一个不错的选择可能是600(即10分钟超时)。

refuse options
此参数允许您指定一个用空格分隔的rsync命令行选项列表,这些选项将被您的rsync守护进程拒绝。您可以指定完整的选项名称、其一字母缩写或与多个选项匹配的通配符字符串。

dont compress
此参数允许您根据通配符模式选择在从守护程序拉取文件时不应进行压缩的文件名(不存在类似的参数来控制将文件推送到守护程序)。压缩在CPU使用方面是昂贵的,因此通常最好不要尝试压缩无法很好压缩的文件,例如已经压缩过的文件。

pre-xfer exec, post-xfer exec
传输之前和/或之后可以指定要运行的命令。如果pre-xfer exec命令失败,则传输在开始之前被中止。

服务配置示例

uid = nobody
gid = nobody
use chroot = yes
max connections = 4
pid file = /var/run/rsyncd.pid
exclude = lost+found/
transfer logging = yes
timeout = 900
ignore nonreadable = yes
dont compress   = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2

[backup]
auth users = root
secrets file = /etc/rsyncd.pass
path = /data1
list = no

客户端

常用参数

-a/--archive
以归档模式进行同步,包括递归复制、保留权限、时间戳等。

-v/--verbose
输出详细的信息。

-P/--progress
显示传输进度。

--password-file
指定秘钥文件

--bwlimit
限制传输带宽,单位为KB,注意不是Kb。

推/拉文件示例

rsync -avP --password-file=/etc/rsync_backup.pass --bwlimit=50000 data_dir 172.x.x.10::backup/
rsync -avP --password-file=/etc/rsync_backup.pass --bwlimit=50000 172.x.x.10::backup/data_dir/ data_dir/
阅读全文

Logrotate工具

logrotate是一个用于管理日志文件的工具,它可以定期轮转(rotate)和压缩日志文件,以便节省磁盘空间。它通常在Linux系统中使用。

logrotate的主要功能包括:

  1. 轮转日志文件:logrotate可以按照预设的时间间隔(如每天、每周、每月等)对指定的日志文件进行轮转。轮转意味着将当前的日志文件重命名为一个新的文件,并创建一个新的空的日志文件。

  2. 压缩日志文件:logrotate还可以自动对轮转后的旧日志文件进行压缩,以节省磁盘空间。它支持多种压缩格式,如gzip、bzip2等。

  3. 删除旧的日志文件:logrotate可以根据设置的保留时间,自动删除过期的日志文件,以防止占用过多的磁盘空间。

  4. 执行脚本或命令:logrotate允许在轮转日志文件之前或之后执行自定义的脚本或命令。这使得用户能够在日志轮转过程中执行额外的操作,如发送邮件通知、重新启动相关服务等。

logrotate的配置文件通常位于/etc/logrotate.conf或/etc/logrotate.d/目录下,每个日志文件都有一个对应的配置文件。配置文件中可以指定轮转的时间间隔、保留时间、压缩格式等参数。

Centos7示例

logrotate通过cron触发,执行脚本在/etc/cron.daily/logrotate

/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf

logrotate.status是其保存状态的文件,/etc/logrotate.conf是主配置,主配置中可以设置全局轮转配置

# see "man logrotate" for details
# rotate log files weekly
weekly

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# use date as a suffix of the rotated file
dateext

# uncomment this if you want your log files compressed
#compress

# RPM packages drop log rotation information into this directory
include /etc/logrotate.d

以/etc/logrotate.d/syslog为例,子配置继承主配置的属性,在block内可以添加配置或者覆盖配置,大括号block之前表示匹配的日志文件。

/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
    missingok
    sharedscripts
    postrotate
    /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
    endscript
}

结合起来syslog的日志轮转逻辑为:

  • 每周轮转(weekly)
  • 保留最近4份(rotate 4)
  • 轮转掉旧文件创建一个新的(create)
  • 旧文件添加日期后缀(dateext)
  • 没有配置到日志文件不报错(missingok)
  • 所有的文件轮转仅执行一次postrotate/endscript之间的脚本(sharedscripts),相反没有此配置每处理一个文件都会执行一次。

更多属性

compress
默认情况下,旧版本的日志文件会使用gzip(1)进行压缩。也可参见nocompress选项。

compresscmd
指定用于压缩日志文件的命令。默认为gzip(1)。也可参见compress选项。

uncompresscmd
指定用于解压缩日志文件的命令。默认为gunzip(1)。

compressext
指定在启用压缩时要使用的压缩日志文件的扩展名。默认扩展名与配置的压缩命令保持一致。

compressoptions
如果使用了压缩程序,可以通过该选项传递命令行参数给压缩程序。默认情况下,对于gzip(1)来说,参数是"-6"(以牺牲速度换取更高的压缩率)。如果使用其他压缩命令,可能需要修改compressoptions以匹配。

copy
复制日志文件,但不更改原始文件。例如,可以用于创建当前日志文件的快照,或者当其他工具需要截断或解析文件时使用。当使用此选项时,create选项将不起作用,因为旧的日志文件保持在原地。

copytruncate
复制日志文件后,将原始日志文件截断为零大小,而不是移动旧日志文件并可选地创建一个新文件。如果某个程序无法关闭其日志文件,并且可能会继续写入(追加)到前一个日志文件中,可以使用此选项。请注意,在复制文件和截断文件之间有一个非常小的时间间隔,因此可能会丢失一些日志数据。当使用此选项时,create选项将不起作用,因为旧的日志文件保持在原地。

create mode owner group, create owner group
在轮转日志文件后立即创建日志文件(与刚轮转的日志文件相同的名称)。mode指定日志文件的权限(以八进制表示,与chmod(2)相同),owner指定将拥有日志文件的用户,group指定日志文件所属的组。可以省略任何日志文件属性,省略的属性将使用与原始日志文件相同的值。可以使用nocreate选项禁用此功能。

createolddir mode owner group
如果oldir指令指定的目录不存在,则创建它。mode指定olddir目录的权限(以八进制表示,与chmod(2)相同),owner指定将拥有olddir目录的用户,group指定olddir目录所属的组。可以使用nocreateolddir选项禁用此功能。

daily
每天轮转日志文件。

dateext
在归档旧版本的日志文件时,添加一个日期扩展名,如YYYYMMDD,而不仅仅是添加一个数字。可以使用dateformat和dateyesterday选项配置扩展名。

dateformat format_string
使用与strftime(3)函数类似的格式指定dateext的扩展名。只允许使用%Y %m %d %H和%s这些格式化符号。默认值为-"%Y%m%d",每小时轮转的情况下,默认值为-"%Y%m%d%H"。请注意,将日志文件名与扩展名分隔的字符也是dateformat字符串的一部分。系统时钟必须设置在2001年9月9日之后,%s才能正确工作。请注意,此格式生成的日期戳必须按字母顺序排序(即先年份,然后月份,再日期。例如,2001/12/01没问题,但01/12/2001不行,因为01/11/2002排序较低但实际上更晚)。这是因为在使用rotate选项时,logrotate会对所有旋转过的文件进行排序,以确定哪些日志文件是更旧的,应该被删除。

dateyesterday
使用昨天的日期而不是今天的日期来创建dateext扩展名,以便旋转的日志文件的名称中包含一个与其中的时间戳相同的日期。

delaycompress
将前一个日志文件的压缩推迟到下一次轮转周期。只有与compress一起使用时才有效。当某个程序无法关闭其日志文件并且可能会继续写入前一个日志文件一段时间时,可以使用此选项。

extension ext
保留扩展名为ext的日志文件,不进行轮转。如果使用了压缩,则压缩扩展名(通常为.gz)会出现在ext之后。例如,如果有一个名为mylog.foo的日志文件,希望将其旋转到mylog.1.foo.gz而不是mylog.foo.1.gz。

hourly
每小时轮转日志文件。请注意,通常配置logrotate以每天由cron运行。您需要更改此配置并每小时运行logrotate,才能真正每小时轮转日志。

ifempty
即使日志文件为空,也要轮转该日志文件,覆盖notifempty选项(ifempty是默认值)。

include file_or_directory
按照所给定的文件名或目录名包含文件,就好像它是行内包含的一样。如果给定一个目录,将按字母顺序读取该目录中的大多数文件,然后再继续处理包含文件。忽略非普通文件(如目录和命名管道)和文件名以禁止扩展指令指定的禁止扩展名结尾的文件。

mail address
当日志被轮转时,将其发送到指定的地址。如果某个日志文件不应生成邮件,则可以使用nomail指令。

mailfirst
使用mail命令时,发送刚刚轮转的文件,而不是即将过期的文件。

maillast
使用mail命令时,发送即将过期的文件,而不是刚刚轮转的文件(这是默认值)。

maxage count
删除早于<count>天的旋转日志。只有在要轮转日志文件时才检查年龄。如果配置了maillast和mail指令,则将文件发送到配置的地址。

maxsize size
日志文件的大小超过指定的大小(以字节为单位),即使没有达到额外指定的时间间隔(每天、每周、每月或每年)也会进行轮转。相关的size选项类似,但与时间间隔选项互斥,它导致日志文件在不考虑上次轮转时间的情况下进行轮转。当使用maxsize时,同时考虑日志文件的大小和时间戳。

minsize size
只有当日志文件的大小超过指定的大小(以字节为单位),并且尚未达到额外指定的时间间隔(每天、每周、每月或每年)时,才进行日志文件的轮转。相关的size选项类似,但与时间间隔选项互斥,它导致日志文件在不考虑上次轮转时间的情况下进行轮转。当使用minsize时,同时考虑日志文件的大小和时间戳。

missingok
如果日志文件不存在,则继续处理下一个日志文件,而不发出错误消息。参见nomissingok选项。

monthly
每月的第一次运行logrotate时进行日志文件轮转(通常在每月的第一天)。

nocompress
不压缩旧版本的日志文件。参见compress选项。

nocopy
不复制原始日志文件并保留在原地(这会覆盖copy选项)。

nocopytruncate
在创建副本后,不截断原始日志文件(这会覆盖copytruncate选项)。

nocreate
不创建新的日志文件(这会覆盖create选项)。

nocreateolddir
当不存在oldir指令指定的目录时,logrotate不会创建它。

nodelaycompress
不推迟前一个日志文件的压缩到下一个轮转周期(这会覆盖delaycompress选项)。

nodateext
不使用日期扩展名对旧版本的日志文件进行归档(这会覆盖dateext选项)。

nomail
不将旧日志文件发送到任何地址。

nomissingok
如果日志文件不存在,则发出错误。这是默认值。

noolddir
日志在它们通常所在的目录中进行轮转(这会覆盖olddir选项)。

nosharedscripts
对于每个要轮转的日志文件,运行prerotate和postrotate脚本(这是默认值,并覆盖了sharedscripts选项)。将绝对路径传递给脚本作为第一个参数。如果脚本退出时出现错误,则对受影响的日志文件不执行剩余操作。

noshred
删除旧日志文件时不使用shred命令。参见shred选项。

notifempty
如果日志文件为空,则不进行轮转(这会覆盖ifempty选项)。

olddir directory
将日志移动到指定的目录进行轮转。该目录必须与要轮转的日志文件位于同一物理设备上,除非使用了copy、copytruncate或renamecopy选项。假设该目录相对于包含日志文件的目录,除非指定了绝对路径名。当使用此选项时,所有旧版本的日志文件都会放在目录中。这个选项可以被noolddir选项覆盖。

postrotate/endscript
在日志文件轮转后(在运行postrotate脚本之前),以/bin/sh执行postrotate和endscript之间的行。这些指令只能出现在日志文件定义内部。通常,将绝对路径传递给脚本作为第一个参数。如果指定了sharedscripts,则整个模式将传递给脚本。参见prerotate。参见sharedscripts和nosharedscripts用于错误处理。

prerotate/endscript
在日志文件轮转之前(当实际上要轮转日志时)以/bin/sh执行prerotate和endscript之间的行。这些指令只能出现在日志文件定义内部。通常,将绝对路径传递给脚本作为第一个参数。如果指定了sharedscripts,则整个模式将传递给脚本。参见postrotate。参见sharedscripts和nosharedscripts用于错误处理。

firstaction/endscript
在满足通配符模式的所有日志文件轮转之前,执行firstaction和endscript之间的行(只有在至少有一个日志实际上会被轮转时才执行prerotate脚本)。这些指令只能出现在日志文件定义内部。将整个模式作为第一个参数传递给脚本。如果脚本退出时出现错误,将不执行任何进一步处理。参见lastaction。

lastaction/endscript
在满足通配符模式的所有日志文件轮转之后,执行lastaction和endscript之间的行(在运行postrotate脚本之后),只有至少有一个日志被轮转时才执行。这些指令只能出现在日志文件定义内部。将整个模式作为第一个参数传递给脚本。如果脚本退出时出现错误,则仅显示错误消息(因为这是最后一个动作)。参见firstaction。

preremove/endscript
在删除日志文件之前,执行preremove和endscript之间的行。logrotate将传递即将被删除的文件的名称。参见firstaction。

rotate count
在删除或发送到mail指令中配置的地址之前,对日志文件进行count次轮转。如果count为0,则删除旧版本而不进行轮转。

size size
只有当日志文件大小超过指定的大小(以字节为单位)时,才进行轮转。如果size后面跟着k,则认为大小是以千字节为单位。如果使用M,则大小以兆字节为单位;如果使用G,则大小以千兆字节为单位。因此,size 100、size 100k、size 100M和size 100G都是有效的。

sharedscripts
通常,prerotate和postrotate脚本对每个要轮转的日志文件都会运行,并将绝对路径作为第一个参数传递给脚本。这意味着对于匹配多个文件的日志文件条目,可能会多次运行单个脚本。如果指定了sharedscripts,则只运行一次脚本,不管有多少日志与通配符模式匹配,并且整个模式都传递给它们。但是,如果模式中的所有日志都不需要进行轮转,则根本不会运行脚本。如果脚本退出时出现错误,将不对任何日志执行剩余操作。此选项覆盖了nosharedscripts选项,并暗示了create选项。

shred
在删除旧日志文件时使用shred -u而不是unlink()。默认情况下,此选项关闭。参见noshred选项。

shredcycles count
要求GNU shred(1)在删除之前覆盖旧日志文件count次。如果没有使用此选项,将使用shred的默认值。

start count
这是用作轮转基础的数字。例如,如果您指定0,则在从原始日志文件轮转时,日志将以.0扩展名创建。如果指定9,则日志文件将以.9创建,跳过0-8。文件仍将按照rotate指令指定的次数进行轮转。

su user group
以指定的用户和组而不是使用默认的用户/组(通常为root)进行日志文件轮转。user指定用于轮转的用户名,group指定用于轮转的组名。如果在create指令中指定了无法拥有指定权限的用户/组创建文件,将导致错误。

weekly [weekday]
每个工作日都进行一次日志文件轮转,或者如果日期推进了至少7天,自上次轮转开始以来忽略具体时间。工作日的解释如下:0表示周日,1表示周一,...,6表示周六;特殊值7表示每7天,与工作日无关。如果省略weekday参数,默认为0。

yearly
如果当前年份与上次轮转的年份不同,则对日志文件进行轮转。
阅读全文