我在 ubuntu 18.04 服务器上。我需要运行一个更新 CloudFlare 上的 IP 地址的脚本(一种 DynDNS 脚本)。在以前的版本中,我可以使用接口 enp1s0 的 DHCLIENT 退出挂钩来执行此操作。
但是,systemd 现在使用自己的内置 DHCP 客户端。如何编写一个 systemd 单元,在向 DCHP 客户端提供新 IP 地址后立即执行 bash 脚本?
Systemd 正在管理接口 enp1s0:
#sudo systemctl status systemd-networkd
● systemd-networkd.service - Network Service
Loaded: loaded (/lib/systemd/system/systemd-networkd.service; enabled-runtime; vendor preset: enabled)
Active: active (running) since Tue 2018-09-18 01:54:16 +08; 10h ago
Docs: man:systemd-networkd.service(8)
Main PID: 878 (systemd-network)
Status: "Processing requests..."
Tasks: 1 (limit: 4915)
CGroup: /system.slice/systemd-networkd.service
└─878 /lib/systemd/systemd-networkd
Sep 18 01:54:27 xxx systemd-networkd[878]: enp1s0: Configured
答案1
网络调度程序
可用于更精细地控制您希望脚本执行的时间。
根据您希望脚本执行的状态,您必须决定将脚本放入哪个文件夹。
- 网络脚本文件夹列表:https://gitlab.com/craftyguy/networkd-dispatcher#usage
- 网络文件夹定义:https://www.freedesktop.org/software/systemd/man/networkctl.html#missing
- 网络脚本文件夹 if-up/if-down/etc 等效表:https://github.com/canonical-web-and-design/netplan.io/blob/master/faq.md#use-pre-up-post-up-etc-hook-scripts
例子:
我们将使用该文件夹routable.d
,此时该链路已配置运营商和可路由地址。
将脚本文件复制到/usr/lib/networkd-dispatcher/routable.d
cp path/to/my/ipchange_script.sh /usr/lib/networkd-dispatcher/routable.d
ipchange_script.sh
#!/bin/bash
if [[ $IFACE == "eth0" && $AdministrativeState == "configured" ]]; then
echo "IP Address has changed to: $ADDR" >> /tmp/iplog.txt
fi
exit 0
刷新您的 IP ( dhclient -r eth0 && dhclient -v eth0
),然后查看脚本的输出或查看脚本是否有任何错误,您可以使用以下命令检查:
sudo service networkd-dispatcher status
PS 我断断续续地搜索了几个月,但没有找到关于如何使用networkd-dispatcher
.我今天才弄清楚。享受!
答案2
我不知道有任何 systemd 解决方案,但您可以有效地监视接口的更改,ip monitor
并将输出通过管道传输到脚本中,以查找您感兴趣的更改。例如,如果我这样做
$ ip monitor address dev enp3s0
然后添加一个新的别名地址到接口 enp3s0 我得到了这一行
2: enp3s0 inet 192.168.77.77/24 brd 192.168.77.255 scope global enp3s0:1
valid_lft forever preferred_lft forever
我想您会看到类似的 dhcp 更改。
如果你愿意,你可以编写一个 C 程序来做同样的事情,参见ipevent.c。
答案3
许多软件包还不能与systemd-networkd
...一起使用。 (请参阅 LaunchPad 上的错误报告)
目前,ISC DHCP 客户端 ( dhclient
) 仍然占据主导地位,特别是在许多 ISP 的 DHCP 服务器(我指的是您,Juniper Networks)所需的自定义 DHCP 选项以及支持操作系统脚本方面。
因此,请转到/etc/systemd/network
编辑处理动态 IP 寻址的配置文件并禁用 systemd 的 DHCP,如下所示:
[Match]
Name=eth1
[Network]
# Using ISC DHCP client (dhclient) instead of systemd-networkd
# Better support of DHCP-Options and OS-specific script supports
DHCP=no
dhclient
然后确保 ISC DHCP 客户端 ( ) 中的以下内容/etc/network/interfaces
:
auto eth0
iface eth0 inet dhcp
对于/etc/dhcp/dhclient.conf
:
send host-name "Wireless_Broadband_Router";
send domain-name "home";
request subnet-mask, broadcast-address, time-offset, routers,
domain-name, domain-name-servers, time-servers, log-servers,
default-ip-ttl, dhcp-requested-address, dhcp-lease-time,
dhcp-server-identifier,dhcp-parameter-request-list,
vendor-class-identifier,dhcp-client-identifier,
www-server,
dhcp6.name-servers, dhcp6.domain-search, dhcp6.fqdn,
dhcp6.sntp-servers,
interface-mtu,
ntp-servers;
最后一步是让 systemd 将 ISC DHCP 客户端作为守护进程启动。在 中创建一个文件。/etc/systemd/system/[email protected]
# cat /etc/systemd/system/[email protected]
[Unit]
Description=dhclient on %I
Wants=network.target
Before=network.target
BindsTo=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
[Service]
# ExecStart=/sbin/dhclient -4 -q %I
ExecStart=/sbin/dhclient -4 -v -pf /run/dhclient.%I.pid -lf /var/lib/dhcp/dhclient.%I.leases %I
[Install]
WantedBy=multi-user.target
systemd
并通过从 shell 执行使 ISC DHCP 客户端可供守护进程使用:
sudo systemctl daemon-reload #makes the [email protected] available
sudo systemctl enable [email protected]
sudo systemctl start [email protected]
答案4
使用网络管理器
我无法networkd-dispatcher
响应 Ubuntu Server 20.04 上的 dhcp 更改,但是网络管理器systemd-networkd
(在 Ubuntu 桌面中被替换)可以。
- 安装网络管理器
sudo apt install network-manager
编辑以下配置文件/etc/netplan/
:
network:
version: 2
renderer: NetworkManager
sudo netplan generate
生成配置文件网络管理器
- 禁用
systemd-networkd
并重新启动
sudo systemctl mask systemd-networkd
sudo reboot now
- 把你的脚本放在下面
/etc/NetworkManager/dispatcher.d
网络管理器将使用 $1 = 接口、$2 = 操作(例如,dhcp-change
, up
)运行它并设置一些环境变量。看它的手册https://developer.gnome.org/NetworkManager/stable/NetworkManager.html