ubuntu linux 控制wifi功能 dbus控制
dbus 控制wifi功能
原理:ubuntu系统自带的NetworkManager 守护进程专门接管了系统网络的功能,避免了用户手动写代码调用系统函数驱动来间接操作硬件。
所以有这个NetworkManager来管理这个这部分网络功能,并且提供dbus通信,让各个应用来共享该功能,避免了各个不同的应用都控制该功能导致冲突。
⚠️ 重要前提:
- 你的系统使用 NetworkManager(检查:
systemctl is-active NetworkManager应为 active)- 你有无线网卡,设备名如
wlan0(可通过ip link或nmcli device查看,但后者是工具,我们尽量不用)- 所有命令需在终端以普通用户或 root 执行(部分需 root,我会标注)
🎯 1. 开启 WiFi(启用无线射频)
dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager \
org.freedesktop.DBus.Properties.Set \
string:"org.freedesktop.NetworkManager" \
string:"WirelessEnabled" \
variant:boolean:true
🎯 2. 关闭 WiFi(禁用无线射频)
dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager \
org.freedesktop.DBus.Properties.Set \
string:"org.freedesktop.NetworkManager" \
string:"WirelessEnabled" \
variant:boolean:false
🎯 3. 连接指定的 WiFi(SSID + 密码)
这需要 3 步:
Step 1️⃣:扫描 WiFi(可选,确保目标 AP 可见)
该命令行相当于查看当前的网络设备有哪些
dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager \
org.freedesktop.NetworkManager.GetDevices
从返回结果中找到你的无线设备路径,比如:/org/freedesktop/NetworkManager/Devices/3
dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager/Devices/7 \
org.freedesktop.DBus.Properties.Get \
string:"org.freedesktop.NetworkManager.Device" \
string:"Interface"
它会告诉你 /Devices/7 对应的名字(比如 docker0 或 virbr0)。
方法 2:用 dbus-send 查类型
dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager/Devices/3 \
org.freedesktop.DBus.Properties.Get \
string:"org.freedesktop.NetworkManager.Device" \
string:"DeviceType"
# 返回值是一个数字:
| 数字 | 类型 |
| -- | --------------------------------------------------- |
| 0 | Unknown |
| 1 | Ethernet |
| 2 | Wi-Fi (802.11 wireless LAN) |
| 3 | Unused (保持兼容) |
| 5 | Bridge |
| 6 | VLAN |
| 7 | Modem (GSM/UMTS/LTE, CDMA, etc.) ← 📡 就是 4G/USB 上网卡 |
| 8 | Infiniband |
| 9 | Bond |
| 10 | Veth |
| 11 | Macvlan |
| 12 | VXLAN |
| 13 | VethPair |
| 14 | Tun/Tap |
| … | 其他虚拟设备类型 |
# 等等
然后请求扫描:
RequestScan 只是触发扫描,不返回结果(dbus会扫到wifi会增加对应的AccessPoint的路径对象,每个都表示一个wifi)
# 无问题
busctl call \
org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager/Devices/3 \
org.freedesktop.NetworkManager.Device.Wireless \
RequestScan \
a{sv} 0
Step 2️⃣:获取目标 AP 的对象路径
等待几秒(5s)让扫描完成。(会触发信号当扫描到wifi的时候)
# 监听信号
dbus-monitor --system "interface='org.freedesktop.NetworkManager.Device.Wireless'"
获取对应的AccessPoint 与SSId的输出
for ap in $(dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager/Devices/3 \
org.freedesktop.NetworkManager.Device.Wireless.GetAllAccessPoints \
| grep object | awk '{print $3}' | tr -d '"'); do
ssid=$(dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
$ap \
org.freedesktop.DBus.Properties.Get \
string:"org.freedesktop.NetworkManager.AccessPoint" \
string:"Ssid" \
)
if [ -n "$ssid" ]; then
echo "$ap"
echo "$ssid"
echo ""
fi
done
# 获取可连接的wifi 上面扫描完成之后 会增加AccessPoint的对象这里,列出来所有的可连接的wifi
dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager/Devices/3 \
org.freedesktop.NetworkManager.Device.Wireless.GetAccessPoints
# 包括不可访问的wifi
dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager/Devices/3 \
org.freedesktop.NetworkManager.Device.Wireless.GetAllAccessPoints
在返回列表中找到你要连接的 SSID 对应的路径,如:/org/freedesktop/NetworkManager/AccessPoint/123
Step 3️⃣:创建并激活连接
先创建一个临时连接配置(一次性,不保存):
用命令行很难做出来,这里给出python调用dbus功能连接指定的wifi
wifi名字叫gt 密码是12345678
python 连接指定的wifi
#!/usr/bin/env python3
import dbus
import uuid
import sys
SSID = "gt"
PASSWORD = "12345678"
bus = dbus.SystemBus()
NM_BUS_NAME = "org.freedesktop.NetworkManager"
NM_OBJECT_PATH = "/org/freedesktop/NetworkManager"
nm_proxy = bus.get_object(NM_BUS_NAME, NM_OBJECT_PATH)
nm_iface = dbus.Interface(nm_proxy, NM_BUS_NAME)
# 1️⃣ 找到无线设备
devices = nm_iface.GetDevices()
wifi_device = None
interface_name = None
for dev_path in devices:
dev_proxy = bus.get_object(NM_BUS_NAME, dev_path)
dev_props = dbus.Interface(dev_proxy, "org.freedesktop.DBus.Properties")
dev_type = dev_props.Get("org.freedesktop.NetworkManager.Device", "DeviceType")
if dev_type == 2: # wireless
wifi_device = dev_path
interface_name = dev_props.Get("org.freedesktop.NetworkManager.Device", "Interface")
print("wireless path:", wifi_device, "| type:", type(wifi_device))
print("interface_name:", interface_name, "| type:", type(interface_name))
break
if wifi_device is None:
print("没有找到无线设备")
sys.exit(1)
# 2️⃣ 构造连接字典
connection = {
'connection': dbus.Dictionary({
'id': dbus.String(SSID),
'type': dbus.String('802-11-wireless'),
'uuid': dbus.String(str(uuid.uuid4())),
'interface-name': dbus.String(interface_name)
}, signature='sv'),
'802-11-wireless': dbus.Dictionary({
'ssid': dbus.ByteArray(SSID.encode())
}, signature='sv'),
'802-11-wireless-security': dbus.Dictionary({
'key-mgmt': dbus.String('wpa-psk'),
'psk': dbus.String(PASSWORD)
}, signature='sv')
}
# 3️⃣ 调用 AddAndActivateConnection
conn_path, active_path = nm_iface.AddAndActivateConnection(
connection,
dbus.ObjectPath(wifi_device),
dbus.ObjectPath("/") # 不指定 AP, 自动选择
)
print("连接成功!")
print("Connection path:", conn_path)
print("Active path:", active_path)
✅ 此时 WiFi 应该已连接。
🎯 4. 断开当前 WiFi 连接
获取当前激活的连接:
dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager \
org.freedesktop.NetworkManager.GetActiveConnections
找到返回中类型为 802-11-wireless 的连接路径,如:/org/freedesktop/NetworkManager/ActiveConnection/5
然后停用它:
busctl call org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager \
org.freedesktop.NetworkManager DeactivateConnection \
o /org/freedesktop/NetworkManager/ActiveConnection/5
🎯 5. 创建并打开 WiFi 热点(AP 模式)
Step 1:创建热点连接配置
Step 2:激活热点
#!/usr/bin/env python3
import dbus
# -------------------------------
# 配置热点信息
SSID = b"MyHotspot" # 热点名称(Byte)
PASSWORD = "12345678" # 热点密码
# -------------------------------
# 连接到系统总线
bus = dbus.SystemBus()
# 获取 NetworkManager 对象
nm_proxy = bus.get_object('org.freedesktop.NetworkManager', '/org/freedesktop/NetworkManager')
nm_iface = dbus.Interface(nm_proxy, 'org.freedesktop.NetworkManager')
# 获取 NetworkManager 设置接口
settings_proxy = bus.get_object('org.freedesktop.NetworkManager', '/org/freedesktop/NetworkManager/Settings')
settings_iface = dbus.Interface(settings_proxy, 'org.freedesktop.NetworkManager.Settings')
# 获取所有设备,找到第一个无线设备
device_paths = nm_iface.GetDevices()
wifi_device_path = None
wifi_iface_name = None
for path in device_paths:
dev_proxy = bus.get_object('org.freedesktop.NetworkManager', path)
dev_props = dbus.Interface(dev_proxy, 'org.freedesktop.DBus.Properties')
dev_type = dev_props.Get('org.freedesktop.NetworkManager.Device', 'DeviceType')
# DeviceType 2 = Wi-Fi
if dev_type == 2:
wifi_device_path = path
wifi_iface_name = dev_props.Get('org.freedesktop.NetworkManager.Device', 'Interface')
break
if not wifi_device_path:
raise RuntimeError("未找到无线设备,请检查你的网络接口。")
print(f"使用无线接口: {wifi_iface_name}")
# 构造热点连接配置
connection = {
'connection': {
'id': 'MyHotspot',
'type': '802-11-wireless',
'interface-name': wifi_iface_name,
'autoconnect': False,
},
'802-11-wireless': {
'ssid': dbus.ByteArray(SSID),
'mode': 'ap',
},
'802-11-wireless-security': {
'key-mgmt': 'wpa-psk',
'psk': PASSWORD,
},
}
# 调用 AddConnection 添加热点
connection_path = settings_iface.AddConnection(connection)
print("连接已添加,路径:", connection_path)
# 激活热点(使用 ActivateConnection)
active_path = nm_iface.ActivateConnection(connection_path, wifi_device_path, '/')
print("热点已激活,Active path:", active_path)
print(f"SSID: {SSID.decode()}, Password: {PASSWORD}")
✅ 热点已启动!
🎯 6. 关闭热点
和“断开 WiFi”一样:
如之前使用了打开热点的的时候输出的内容:
使用无线接口: wlp7s0 连接已添加,路径: /org/freedesktop/NetworkManager/Settings/15 热点已激活,Active path: /org/freedesktop/NetworkManager/ActiveConnection/12 SSID: MyHotspot, Password: 12345678
或着找到类型为 802-11-wireless 且模式是 ap 的连接路径,如:/org/freedesktop/NetworkManager/ActiveConnection/6 关键要想办法得到这个ActiveConnection
然后:
busctl call org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager \
org.freedesktop.NetworkManager DeactivateConnection \
o /org/freedesktop/NetworkManager/ActiveConnection/12
📌 附录:如何获取设备路径(不用 nmcli)
dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager \
org.freedesktop.NetworkManager.GetDevices
遍历返回的设备路径,对每个设备查询设备类型:
dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager/Devices/3 \
org.freedesktop.DBus.Properties.Get \
string:"org.freedesktop.NetworkManager.Device" \
string:"DeviceType"
返回值 2 表示无线设备(NM_DEVICE_TYPE_WIFI)。
✅ 总结命令表(纯 dbus-send)
| 功能 | 命令摘要 |
|---|---|
| 开启 WiFi | Set WirelessEnabled true |
| 关闭 WiFi | Set WirelessEnabled false |
| 连接 WiFi | AddConnection + ActivateConnection(需 SSID 字节数组) |
| 断开 WiFi | DeactivateConnection(需 ActiveConnection 路径) |
| 打开热点 | AddConnection(mode=ap) + ActivateConnection |
| 关闭热点 | DeactivateConnection(找 AP 类型的 ActiveConnection) |
💡 温馨提示:
- 使用
dbus-sendbusctl操作 NetworkManager 极其繁琐,参数结构复杂,错误难调试。 - 生产环境或脚本中强烈建议使用
nmcli。 - 如果想要更详细的控制就调用dbus的功能通信,nmcli 也是这么做的
- 如果你是为了学习 D-Bus 或嵌入式定制系统,这些命令非常有价值。
(可以用命令先跑通,然后再转换具体的代码)
更多推荐




所有评论(0)