1、通过文件配置Ubuntu设备网口
在Ubuntu工控机上,通过文件配置网口(网络接口)可以让网络配置在每次系统启动时自动生效。以下是常见的方法步骤:
1.1 使用 netplan
配置网口(Ubuntu 18.04 及以上版本)
-
编辑
netplan
配置文件:netplan
的配置文件通常位于/etc/netplan/
目录下,文件名通常是01-netcfg.yaml
或者类似的.yaml
文件。打开该文件进行编辑:
sudo nano /etc/netplan/01-netcfg.yaml
-
配置网口: 在文件中添加或修改如下内容,假设你要配置的是
eth0
网口,并且希望它有静态 IP 地址:network:version: 2renderer: networkdethernets:<eth0>:dhcp4: noaddresses:- 192.168.1.100/24gateway4: 192.168.1.1nameservers:addresses:- 8.8.8.8- 8.8.4.4
eth0
需要配置的网口,根据实际换成自己设备的网口dhcp4: no
表示关闭 DHCP。addresses:
配置静态 IP 地址和子网掩码。gateway4:
配置网关。nameservers:
配置 DNS 服务器地址。
1.2 使用 ifupdown
配置网口(Ubuntu 16.04 及以下版本)
Ubuntu 16.04 及之前的版本使用 /etc/network/interfaces
文件来配置网口。
-
编辑
/etc/network/interfaces
文件: 打开该文件进行编辑:sudo nano /etc/network/interfaces
-
配置网口: 在文件中添加或修改如下内容,假设你要配置的是
eth0
网口:-
如果是静态 IP:
auto eth0 iface eth0 inet staticaddress 192.168.1.100netmask 255.255.255.0gateway 192.168.1.1dns-nameservers 8.8.8.8 8.8.4.4
-
如果是动态 IP(通过 DHCP 获取 IP):
auto eth0 iface eth0 inet dhcp
-
-
重启网络服务: 保存文件后,使用以下命令重启网络服务使配置生效:
sudo systemctl restart networking
1.3 验证配置
你可以使用 ifconfig
或 ip a
命令来检查网口的配置是否正确生效。例如:
ip a
这两种方法分别适用于不同的 Ubuntu 版本。你可以根据自己的系统版本选择合适的方式。
2、使用python搭建一个web服务
要使用 Python 搭建一个 Web 服务,允许远程修改 netplan
网络配置并在没有新的 Web 访问后一分钟内恢复原始配置,可以使用 Flask
框架和定时任务来实现。以下是详细步骤:
2.1 后端python脚本
2.1.1 项目依赖
因为python脚本编辑/etc路径下文件,脚本需要在root权限下运行,因此安装依赖首先需要获取root权限:
sudo -i
安装依赖:
首先,你需要安装 Flask
框架和 schedule
模块(用于定时任务),以及确保工控机有权限修改网络配置,。
pip3 install flask flask-cors schedule
2.1.2 Python 代码实现
以下是一个完整的 Python 脚本示例,该脚本包含:
- 启动一个 Flask Web 服务,用于接收网络配置修改请求。
- 使用定时任务,在没有新的 Web 访问后 60 秒内恢复为原始配置。
#!/usr/bin/env python3
import os
import time
import shutil
import threading
from flask import Flask, request, jsonify
from flask_cors import CORS
import schedule
import subprocess
import reapp = Flask(__name__)
CORS(app) # 启用 CORS 允许跨域请求
# 全局变量,用来保存最后一次修改时间
last_access_time = time.time()# 保存原始的 netplan 配置文件路径
netplan_file = "/etc/netplan/01-network-manager-all.yaml"
backup_file = "/etc/netplan/01-network-manager-all.yaml.bak"change_config = False
revisit = False# 备份原始配置
def backup_netplan():# if not os.path.exists(backup_file):shutil.copy(netplan_file, backup_file)print("Netplan configuration backed up.")# 定时器:在 60 秒后没有新的请求访问时恢复配置
def restore_config_if_needed():global last_access_timeglobal change_configglobal revisitif not change_config:returnif revisit:backup_netplan()print("Netplan configuration already in effect.")change_config = Falserevisit = False# 计算当前时间距离上次访问的时间差time_since_last_access = time.time() - last_access_timeif time_since_last_access > 60:# 恢复原始配置if os.path.exists(backup_file):shutil.copy(backup_file, netplan_file)change_config = False# 应用 netplan 配置os.system("sudo netplan apply")print("Netplan configuration restored to original.")# 启动一个独立线程来定时检查恢复配置
def schedule_checker():while True:schedule.run_pending()time.sleep(1)def get_current_ip():"""获取系统当前设置的 IP 地址"""try:# 通过 ip 命令获取网口 eth0 的 IP 地址result = subprocess.run(['ip', 'addr', 'show', 'enp2s0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)output = result.stdout# 使用正则表达式查找 IP 地址ip_match = re.search(r'inet\\s(\\d+\\.\\d+\\.\\d+\\.\\d+)', output)if ip_match:return ip_match.group(1) # 返回第一个匹配的 IP 地址else:return "No IP address found"except Exception as e:return str(e)@app.route('/current_ip', methods=['GET'])
def current_ip():"""API 返回当前的 IP 地址"""global revisitrevisit = Trueip_address = get_current_ip()print("received new current_ip request")return jsonify({"ip_address": ip_address})# 修改 netplan 配置的路由
@app.route('/update_netplan', methods=['POST'])
def update_netplan():global last_access_timeglobal change_configglobal revisitlast_access_time = time.time()# 获取新的 netplan 配置信息new_config = request.json.get("config")if new_config:# 写入新的配置到 netplan 文件with open(netplan_file, "w") as f:f.write(new_config)change_config = Truerevisit = False# 应用 netplan 配置os.system("sudo netplan apply")return jsonify({"message": "Netplan configuration updated successfully."}), 200else:return jsonify({"error": "Invalid configuration."}), 400@app.route('/ping', methods=['GET'])
def ping():"""用于接收前端的访问请求,更新最后一次访问时间"""global last_access_timelast_access_time = time.time() # 更新最后访问时间print("ping received.")return jsonify({"message": "Ping received, reset timeout."}), 200# 主程序入口
if __name__ == '__main__':# 启动时备份原始配置backup_netplan()# 每隔 10 秒检查一次是否需要恢复配置schedule.every(10).seconds.do(restore_config_if_needed)# 启动http服务器,以便远程访问前端服务os.system("python3 -m http.server 8000 &")# 启动定时任务线程threading.Thread(target=schedule_checker, daemon=True).start()# 启动 Flask Web 服务app.run(host='0.0.0.0', port=5000)
2.1.3 功能说明
-
备份原始配置: 在脚本启动时,会自动备份当前的
netplan
配置文件到/etc/netplan/01-netcfg.yaml.bak
。 -
修改
netplan
配置: 提供了一个/update_netplan
API,用户可以通过 POST 请求发送新的netplan
配置信息。修改后的配置会立即写入/etc/netplan/01-netcfg.yaml
并通过netplan apply
命令生效。 -
超时恢复配置:
我们可以利用 Flask 的路由来记录前端的访问时间,并通过一个后台线程定期检查是否有新访问。如果超时则恢复原来的
netplan
配置。 该脚本每隔 10 秒检查一次最后的 Web 请求时间。如果超过 60 秒没有新的 Web 请求,则会自动恢复原始的netplan
配置文件并重新应用。 -
定时任务: 使用
schedule
和threading
来定期执行恢复操作,保证主程序可以继续处理 Web 请求。
2.1.4 使用说明
1. 启动 Web 服务:
运行该 Python 脚本后,Web 服务会在 0.0.0.0:5000
上启动,允许外部访问。
2. 修改网络配置:
通过以下 curl
请求或使用其他 API 客户端向服务发送请求来修改 netplan
配置:
curl -X POST http://<your-ip>:5000/update_netplan -H "Content-Type: application/json" -d '{"config": "network:\\n version: 2\\n renderer: networkd\\n ethernets:\\n eth0:\\n addresses:\\n - 192.168.1.101/24\\n gateway4: 192.168.1.1\\n nameservers:\\n addresses:\\n - 8.8.8.8\\n - 8.8.4.4\\n"}'
其中 config
字段的内容就是新的 netplan
YAML 配置。
3. 自动恢复:
如果 60 秒内没有新请求访问,脚本会自动恢复到启动时备份的原始网络配置。
2.1.5 权限与安全性
- 由于修改网络配置需要超级用户权限,你可能需要使用
sudo
来运行该脚本,或者将相关操作(如netplan apply
)设为无需密码执行的命令。 - 建议在实际部署中对 Web 服务添加身份认证,确保外部访问的安全性。
这样,你就可以通过 Web 服务远程修改 netplan
配置,并在无活动时自动恢复配置。
2.1.6 解决 CORS 问题:
-
安装
Flask-CORS
库:pip3 install flask-cors
-
在 Flask 应用中启用 CORS: 修改 Flask 代码,添加 CORS 支持:
python 复制代码 from flask import Flask, request, jsonify from flask_cors import CORSapp = Flask(__name__) CORS(app) # 启用 CORS 允许跨域请求@app.route('/update_netplan', methods=['POST']) def update_netplan():global last_access_timelast_access_time = time.time()new_config = request.json.get("config")if new_config:with open("/etc/netplan/01-netcfg.yaml", "w") as f:f.write(new_config)os.system("sudo netplan apply")return jsonify({"message": "Netplan configuration updated successfully."}), 200else:return jsonify({"error": "Invalid configuration."}), 400
2.2 创建 Python 脚本的 systemd 服务
2.2.1:保存 Python 脚本
将你的 Python 脚本保存到某个目录,例如 /opt/netplan_service/
,并命名为 netplan_service.py
。
确保该目录和文件的权限设置正确,允许脚本执行:
sudo mkdir -p /opt/netplan_service
sudo cp netplan_service.py /opt/netplan_service/
sudo chmod +x /opt/netplan_service/netplan_service.py
2.2.2:创建 systemd 服务文件
创建一个新的 systemd 服务单元文件,使得脚本可以在系统启动时以 root 权限运行。
-
使用
nano
编辑器创建一个名为netplan_service.service
的服务文件:sudo nano /etc/systemd/system/netplan_service.service
-
在文件中添加以下内容:
[Unit] Description=Netplan Configuration Web Service After=network.target[Service] ExecStart=/usr/bin/python3 /opt/netplan_service/netplan_service.py WorkingDirectory=/opt/netplan_service Restart=always User=root Environment=PYTHONUNBUFFERED=1[Install] WantedBy=multi-user.target
说明:
ExecStart
指定了 Python 脚本的启动路径,确保使用 Python 3 解释器。WorkingDirectory
指定服务运行的工作目录。Restart=always
确保服务在失败后自动重启。User=root
确保脚本以 root 权限运行。WantedBy=multi-user.target
使服务在系统启动的多用户模式下自动启动。
2.2.3:重新加载 systemd 守护进程
在创建或修改 systemd 服务文件后,需要重新加载 systemd 守护进程以使其识别新服务:
sudo systemctl daemon-reload
2.2.4:启用并启动服务
-
启用服务(使其开机自启):
sudo systemctl enable netplan_service.service
-
启动服务:
sudo systemctl start netplan_service.service
-
检查服务状态: 使用以下命令检查服务是否正常启动:
sudo systemctl status netplan_service.service
如果服务启动正常,你会看到类似这样的输出:
● netplan_service.service - Netplan Configuration Web ServiceLoaded: loaded (/etc/systemd/system/netplan_service.service; enabled; vendor preset: enabled)Active: active (running) since Tue 2024-09-19 10:00:00 UTC; 5s agoMain PID: 1234 (python3)Tasks: 1 (limit: 2345)CGroup: /system.slice/netplan_service.service└─1234 /usr/bin/python3 /opt/netplan_service/netplan_service.py
2.2.5 验证服务是否开机自启
为了确保服务在每次开机时自动运行,可以重启你的工控机,并检查服务状态:
susdo reboot
重启后,使用以下命令再次检查服务状态:
sudo systemctl status netplan_service.service
如果显示服务为 active (running),说明服务已成功开机自启。
2.2.6 安全性注意事项
由于该服务需要 root 权限来修改网络配置,因此:
- 确保只有受信任的用户能够访问和修改
/etc/systemd/system/netplan_service.service
和 Python 脚本。 - 如果你担心远程 Web 访问的安全性,建议在 Web 服务上启用身份验证机制,或者通过防火墙限制外部访问。
通过这种方式,Python 脚本会在系统启动时自动运行,并具备 root 权限,从而能够修改 netplan
配置并恢复网络配置。
2.3 前端配置
为了搭建一个能够发送类似 curl -X POST http://<your-ip>:5000/update_netplan
的前端界面,你可以使用 HTML 和 JavaScript 来构建一个简单的 Web 界面,允许用户通过表单提交新的 netplan
配置。你可以使用 JavaScript 的 fetch
API 发送 POST 请求。 我们可以使用textarea
为两个独立的输入框,一个用于配置 addresses
,另一个用于配置 gateway4
,并在提交时动态生成完整的 netplan
配置文件。
在后端获取ip地址,并在前端显示
要在前端显示当前系统的 IP 地址,你可以通过后端 Flask 提供一个新的接口,获取当前的 netplan
配置或系统的 IP 地址,并将其返回给前端。前端加载时,发送请求获取并显示当前的 IP 地址。
2.3.1 前端界面实现
以下是一个简单的前端页面代码,前端可以显示当前系统的 IP 地址,用户可以输入新的 netplan
配置,并通过点击按钮发送 POST 请求
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Netplan Configuration</title><style>body {font-family: Arial, sans-serif;padding: 20px;}.container {max-width: 600px;margin: 0 auto;}label {font-size: 16px;margin-top: 10px;}input {width: 100%;padding: 10px;margin-top: 5px;font-size: 16px;}button {margin-top: 10px;padding: 10px;font-size: 16px;background-color: #007bff;color: white;border: none;cursor: pointer;}button:hover {background-color: #0056b3;}.response {margin-top: 20px;padding: 10px;background-color: #f1f1f1;border: 1px solid #ccc;}.current-ip {margin-bottom: 20px;font-size: 18px;color: #333;}</style>
</head>
<body><div class="container"><h1>Netplan Configuration</h1><!-- 显示当前 IP 地址 --><div class="current-ip"><strong>Current IP Address: </strong><span id="current-ip">Loading...</span></div><form id="netplan-form"><label for="ip-address">Enter IP Address (CIDR notation):</label><br><input type="text" id="ip-address" placeholder="e.g. 192.168.1.101/24" required><br><label for="gateway">Enter Gateway Address:</label><br><input type="text" id="gateway" placeholder="e.g. 192.168.1.1" required><br><button type="submit">Submit Configuration</button></form><div class="response" id="response-message"></div></div><script>document.getElementById('netplan-form').addEventListener('submit', function(e) {e.preventDefault(); // 阻止表单默认提交行为const ipAddress = document.getElementById('ip-address').value;const gateway = document.getElementById('gateway').value;// 创建 netplan 配置的 YAML 内容const netplanConfig = `
network:version: 2renderer: NetworkManagerethernets:enp2s0:dhcp4: noaddresses:- ${ipAddress}gateway4: ${gateway}nameservers:addresses:- 8.8.8.8- 8.8.4.4
`;// 发送 POST 请求到后端fetch('http://<your-ip>:5000/update_netplan', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({config: netplanConfig})}).then(response => response.json()).then(data => {document.getElementById('response-message').innerText = JSON.stringify(data);}).catch(error => {document.getElementById('response-message').innerText = "Error: " + error;});});// 加载时获取当前 IP 地址并显示window.onload = function() {fetch('http://<your-ip>:5000/current_ip').then(response => response.json()).then(data => {document.getElementById('current-ip').innerText = data.ip_address;}).catch(error => {document.getElementById('current-ip').innerText = "Error: " + error;});}// 定时每隔 30 秒发送 ping 请求setInterval(function() {fetch('http://<your-ip>:5000/ping').then(response => response.json()).then(data => console.log(data)).catch(error => console.error("Ping failed:", error));}, 30000); // 每 30 秒发送一次请求</script>
</body>
</html>
界面大概长这样
2.3.2 代码解释
-
IP地址和网关输入:
input
标签分别用于输入addresses
(IP地址)和gateway4
(网关)。- 表单提交时会从这两个输入框中获取用户输入的 IP 地址和网关。
-
动态生成
netplan
配置:-
在 JavaScript 里,根据用户输入,动态生成符合
netplan
配置文件格式的 YAML 字符串。 -
生成的 YAML 字符串类似于:
yaml 复制代码 network:version: 2renderer: networkdethernets:eth0:addresses:- 192.168.1.101/24gateway4: 192.168.1.1nameservers:addresses:- 8.8.8.8- 8.8.4.4
-
-
POST 请求:
fetch
函数会发送一个 POST 请求,将生成的配置文件通过 JSON 格式传递给后端 Flask 服务。- 请求的内容是
config
字段,该字段包含用户输入生成的 YAML 文件。
2.3.3 部署说明
- 修改
<your-ip>
:- 将 JavaScript 中的
http://<your-ip>:5000/update_netplan
中的<your-ip>
替换为实际工控机的 IP 地址或域名。
- 将 JavaScript 中的
- 安全性:
- 通过防火墙限制外部访问或为表单页面增加身份验证,确保只有授权用户可以访问和配置网络设置。
通过这个方法,前端界面仅允许用户配置 IP 地址和网关,同时提供用户友好的界面进行提交,后端将自动生成完整的 netplan
配置并应用。