nmcli 之Wi-Fi 设置
一、理论
1、nmcli 是 Linux 系统中 NetworkManager 提供的命令行工具,
用于 管理网络连接,特别适用于图形界面不可用或自动化脚本环境下。
🧾 基本信息
-
全称:NetworkManager Command Line Interface
-
所属包:
NetworkManager -
用途:配置 以太网、Wi-Fi、VLAN、桥接、代理、VPN 等连接
2、只看当前正在使用的连接
# nmcli connection show --active NAME UUID TYPE DEVICE xxx 7d1ab3e0-ba49-4ece-a59a-fd41be6ec5ab wifi wlp3s0 # nmcli device status DEVICE TYPE STATE CONNECTION wlp3s0 wifi 已连接 healsci enp1s0 ethernet 未托管 -- enp2s0 ethernet 未托管 -- lo loopback 未托管 --
3、查看详细信息
nmcli -p device show wlp3s0
4、实时扫描、列出周围的 Wi-Fi 热点
nmcli device wifi list
5、查看连接过的 “历史记录“
nmcli connection show
6、查看连接是静态还是动态
nmcli connection show hexxxi | grep ipv4.method ipv4.method: manual
7、修改Wi-Fi
修改配置文件方式:
cat /etc/NetworkManager/system-connections/healsci.nmconnection
8、查看密码
方法1: cat /etc/NetworkManager/system-connections/wifi-name.nmconnection 方法2(更方便): nmcli -s -g 802-11-wireless-security.psk connection show wifi-name
9、连接没有连过的
nmcli device wifi connect "xxx" --ask nmcli device wifi connect “xxxx" password 'your_password_here'
10、设置静态ip
nmcli connection modify xxx ipv4.method manual ipv4.addresses 192.168.1.100/24 ipv4.gateway 192.168.1.1 ipv4.dns "8.8.8.8 1.1.1.1"
nmcli connection up xxx
连接名必须准确:
不是设备名(如 eth0),而是 nmcli connection show 中的 NAME。
接口必须由 NetworkManager 管理:
如果系统用了 netplan 或 systemd-networkd 管理接口,nmcli 不会生效。
CIDR 格式正确:
如 192.168.1.100/24,确保写的是 IP 加掩码。
11、查看信号强度
# iwconfig wlp3s0
wlp3s0 IEEE 802.11 ESSID:"xxxxxxx"
Mode:Managed Frequency:5.24 GHz Access Point: D4:68:BA:86:04:9F
Bit Rate=121.5 Mb/s Tx-Power=15 dBm
Retry short limit:7 RTS thr:off Fragment thr:off
Encryption key:off
Power Management:on
Link Quality=61/70 Signal level=-49 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:1 Invalid misc:3052 Missed beacon:0
# iw dev wlp3s0 link
Connected to d4:68:ba:86:04:9f (on wlp3s0)
SSID: xxxx
freq: 5240
RX: 93389237 bytes (479148 packets)
TX: 79328016 bytes (63432 packets)
signal: -49 dBm
rx bitrate: 216.0 MBit/s MCS 13 40MHz
tx bitrate: 121.5 MBit/s MCS 6 40MHz
bss flags: short-slot-time
dtim period: 1
beacon int: 100
- Link Quality :链路质量为 61
/70,表示信号质量约为74%(计算方法:61/ 70 * 100% ≈ 87%)。 - Signal level :信号强度为
-49 dBm。- 信号强度的参考范围:
-30 dBm到-50 dBm:良好信号。-50 dBm到-70 dBm:中等信号。-70 dBm以下:信号较弱。
-49 dBm属于 良好信号强度 ,可能会影响连接稳定性。
- 信号强度的参考范围:
12、从静态切换为dhcp
nmcli connection modify healsci ipv4.method auto ipv4.ignore-auto-dns no nmcli connection up healsci
13、重载配置文件
# 热重启。不断开 nmcli device reapply wlp3s0 # 会断开连接 nmcli connection down [id] && nmcli connection up [id]
二、脚本工具
1、Wi-Fi 设置
提供四个功能:加入、删除、转静态、转dhcp
#!/bin/bash
# Check NetworkManager service status
if ! systemctl is-active --quiet NetworkManager; then
echo "Error: NetworkManager is not running. Please start the service first!"
exit 1
fi
# Check root privileges
if [ "$(id -u)" != "0" ]; then
echo "Please run this script with sudo or as root"
exit 1
fi
# Main menu function
show_menu() {
clear
echo "=================================="
echo " WiFi Network Configuration Tool "
current_wifi=$(nmcli connection show --active | tail -1 | awk '{print $1}')
ip_method=$(nmcli connection show "$current_wifi" | grep ipv4.method | awk '{print $2}')
if [ -n "$current_wifi" ] && [ -n "$ip_method" ]; then
echo "Current WiFi: $current_wifi, $ip_method"
else
echo "Not connected to WiFi"
fi
echo "=================================="
echo "1. Connect to a new WiFi network"
echo "2. Delete saved WiFi network"
echo "3. Configure static network"
echo "4. Configure DHCP network"
echo "5. Exit"
echo "=================================="
read -p "Select an option [1-5]: " choice
}
# Function: Join WiFi
join_wifi() {
echo -e "\nScanning for nearby WiFi networks..."
nmcli device wifi rescan &> /dev/null
sleep 2
# Display available networks
echo -e "\nAvailable WiFi Networks:"
nmcli device wifi list
read -p "Enter WiFi SSID: " ssid
if [ -z "$ssid" ]; then
echo "Error: SSID cannot be empty!"
return
fi
# Check if config already exists
if nmcli -g NAME connection show | grep -q "^$ssid$"; then
read -p "This network already exists. Connect now? [y/N]: " choice
if [ "$choice" = "y" ] || [ "$choice" = "Y" ]; then
nmcli connection up "$ssid"
fi
return
fi
# Request password and connect
read -sp "Enter WiFi password (hidden input): " password
echo
if [ -z "$password" ]; then
echo "Warning: No password entered. Trying to connect to open network..."
nmcli device wifi connect "$ssid"
else
nmcli device wifi connect "$ssid" password "$password"
fi
# Check result
if [ $? -eq 0 ]; then
echo -e "\n✓ Successfully connected to $ssid"
else
echo -e "\n✗ Connection failed. Please check password and network state"
fi
}
# Function: Delete WiFi
delete_wifi() {
echo -e "\nSaved WiFi configurations:"
nmcli --fields NAME,TYPE,UUID connection show | grep wifi
read -p "Enter configuration name to delete: " conn_name
if [ -z "$conn_name" ]; then
echo "Error: Configuration name cannot be empty!"
return
fi
# Validate existence
if ! nmcli -g NAME connection show | grep -q "^$conn_name$"; then
echo "Error: Configuration '$conn_name' not found!"
return
fi
# Confirm deletion
read -p "Confirm deletion of '$conn_name'? [y/N]: " choice
if [ "$choice" = "y" ] || [ "$choice" = "Y" ]; then
nmcli connection delete "$conn_name"
echo "✓ Configuration '$conn_name' deleted"
else
echo "Operation canceled"
fi
}
# Function: Set static IP
set_static_ip() {
echo -e "\nSaved WiFi configurations:"
nmcli --fields NAME,TYPE,DEVICE connection show | grep wifi
read -p "Enter network name to configure: " conn_name
if [ -z "$conn_name" ]; then
echo "Error: Configuration name cannot be empty!"
return
fi
# Validate existence
if ! nmcli connection show "$conn_name" &> /dev/null; then
echo "Error: Configuration '$conn_name' not found!"
return
fi
# Get current device info
device=$(nmcli -g connection.interface-name connection show "$conn_name")
if [ -z "$device" ]; then
echo "Error: Unable to get device information!"
return
fi
# Get current gateway
current_gateway=$(nmcli -g ip4.gateway connection show "$conn_name")
# Get recommended values
echo -e "\nCurrent network info:"
ip_addr=$(ip -o -4 addr show dev $device | awk '{print $4}')
gateway=${current_gateway:-$(ip route | grep default | grep $device | awk '{print $3}')}
dns_servers=$(nmcli -g ip4.dns connection show "$conn_name" 2>/dev/null | tr '|' ' ')
[ -z "$ip_addr" ] || echo "Current IP: $ip_addr"
[ -z "$gateway" ] || echo "Current Gateway: $gateway"
[ -z "$dns_servers" ] || echo "Current DNS: $dns_servers"
# Get user input
echo -e "\nEnter static IP configuration (Format: IP/CIDR)"
read -p "Example: 192.168.1.100/24: " static_ip
if [ -z "$gateway" ]; then
read -p "Enter Gateway Address: " gateway
else
read -p "Enter Gateway [default: $gateway]: " new_gateway
gateway=${new_gateway:-$gateway}
fi
if [ -z "$dns_servers" ]; then
read -p "Enter DNS servers (space-separated): " dns_servers
else
read -p "Enter DNS servers [default: $dns_servers]: " new_dns
dns_servers=${new_dns:-$dns_servers}
fi
# Apply static IP
echo -e "\nApplying static IP configuration..."
nmcli connection modify "$conn_name" \
ipv4.method manual \
ipv4.addresses "$static_ip" \
ipv4.gateway "$gateway"
# Set DNS (clear first)
nmcli connection modify "$conn_name" ipv4.dns ""
nmcli connection modify "$conn_name" ipv4.dns "$dns_servers"
# Restart connection
echo "Restarting connection..."
nmcli connection up "$conn_name"
# Verify configuration
if nmcli -g ipv4.method connection show "$conn_name" | grep -q manual; then
echo -e "\n✓ Static IP configured successfully!"
echo "New IP: $(nmcli -g ipv4.addresses connection show "$conn_name")"
echo "DNS Servers: $(nmcli -g ipv4.dns connection show "$conn_name")"
else
echo -e "\n✗ Configuration failed. Please check input parameters"
fi
}
# Function: Set DHCP
set_dhcp() {
echo -e "\nSaved WiFi configurations:"
nmcli --fields NAME,TYPE,DEVICE connection show | grep wifi
read -p "Enter network name to switch to DHCP: " conn_name
if [ -z "$conn_name" ]; then
echo "Error: Configuration name cannot be empty!"
return 1
fi
# Validate existence and type
if ! nmcli connection show --active | grep -q "$conn_name"; then
echo "Error: WiFi configuration '$conn_name' not found!"
return 1
fi
# Switch to DHCP
echo -e "\nSwitching to DHCP..."
if ! nmcli connection modify "$conn_name" \
ipv4.method auto \
ipv4.ignore-auto-dns no 2>/dev/null; then
echo "Error: Failed to modify configuration!"
return 1
fi
# Reactivate connection
if nmcli connection up "$conn_name"; then
echo -e "\n✓ Successfully switched to DHCP"
else
echo -e "\n✗ Failed to activate connection"
return 1
fi
}
# Main loop
while true; do
show_menu
case $choice in
1) join_wifi ;;
2) delete_wifi ;;
3) set_static_ip ;;
4) set_dhcp ;;
5) echo "Exiting program"; exit 0 ;;
*) echo "Invalid selection, please try again!"; sleep 1 ;;
esac
echo && read -p "Press Enter to continue..." -n 1
done
2、Wi-Fi监控
#!/bin/bash
TARGET_IP=""
LOG_FILE="/var/log/wifi_monitor.log"
log() {
local message="$(date '+%Y-%m-%d %H:%M:%S') | $1"
echo "$message" | tee -a "$LOG_FILE"
}
# Check if TARGET_IP is valid IPv4 address
is_valid_ip() {
local ip="$1"
local regex='^([0-9]{1,3}\.){3}[0-9]{1,3}$'
if [[ -z "$ip" ]]; then
log "Error: TARGET_IP is empty."
return 1
elif [[ ! "$ip" =~ $regex ]]; then
log "Error: TARGET_IP '$ip' is not a valid IPv4 address."
return 1
else
# Further check each octet to be between 0 and 255
IFS='.' read -r -a octets <<< "$ip"
for octet in "${octets[@]}"; do
if (( octet < 0 || octet > 255 )); then
log "Error: TARGET_IP '$ip' is not a valid IPv4 address."
return 1
fi
done
fi
return 0
}
# Check for active network connections (using nmcli)
check_internet_connection() {
if nmcli connection show --active | grep -q "ethernet\|wifi"; then
log "Network status: There is an active network connection (online)"
return 0
else
log "Network status: No active network connection (offline)"
return 1
fi
}
# Check if the target server is reachable
check_server() {
ping -c 3 "$TARGET_IP" > /dev/null 2>&1
if [ $? -eq 0 ]; then
log "Server $TARGET_IP status: Reachable"
return 0
else
log "Server $TARGET_IP status: Unreachable"
return 1
fi
}
# Restart Wi-Fi
restart_wifi() {
log "Attempting to restart Wi-Fi..."
INTERFACE=$(nmcli -t --fields DEVICE dev wifi | head -n 1)
if [ -n "$INTERFACE" ]; then
nmcli device disconnect "$INTERFACE" > /dev/null 2>&1
sleep 5
nmcli device reapply "$INTERFACE" > /dev/null 2>&1 || nmcli radio wifi off && nmcli radio wifi on
sleep 10
else
log "Unable to get Wi-Fi interface name, skipping Wi-Fi restart"
return 1
fi
}
# Reboot system
reboot_system() {
log "Network recovery failed, system will now reboot..."
reboot
}
# Main logic
main() {
log "Starting network health check..."
# Validate TARGET_IP first
if ! is_valid_ip "$TARGET_IP"; then
log "Invalid or missing TARGET_IP, exiting script."
exit 1
fi
check_internet_connection
internet_ok=$?
check_server
server_ok=$?
if [ $internet_ok -eq 0 ] && [ $server_ok -eq 0 ]; then
log "Network status is normal, no action to do."
else
log "Network issue detected, attempting to fix..."
restart_wifi
# Re-check after restarting Wi-Fi
check_internet_connection
internet_ok=$?
check_server
server_ok=$?
if [ $internet_ok -eq 0 ] && [ $server_ok -eq 0 ]; then
log "Network has been restored."
else
log "Network still not restored, preparing to reboot system."
reboot_system
fi
fi
}
main
补充:关于ip的验证
is_valid_ip() {
local ip="$1"
local regex='^([0-9]{1,3}\.){3}[0-9]{1,3}$'
if [[ -z "$ip" ]]; then
log "Error: TARGET_IP is empty."
return 1
elif [[ ! "$ip" =~ $regex ]]; then
log "Error: TARGET_IP '$ip' is not a valid IPv4 address."
return 1
else
# Further check each octet to be between 0 and 255
IFS='.' read -r -a octets <<< "$ip"
for octet in "${octets[@]}"; do
if (( octet < 0 || octet > 255 )); then
log "Error: TARGET_IP '$ip' is not a valid IPv4 address."
return 1
fi
done
fi
return 0
}
local regex='^([0-9]{1,3}\.){3}[0-9]{1,3}$'
- 定义一个正则表达式
regex来初步检查 IP 格式:^表示开头;[0-9]{1,3}表示由 1 到 3 位数字组成的一个“段”;\.是点号;([0-9]{1,3}\.){3}表示这种格式重复三次;- 最后再加上一个
[0-9]{1,3}; $表示结尾。- 所以这个正则匹配的是类似
xxx.xxx.xxx.xxx的格式。
检查每个 octet 是否在 0~255 范围内
IFS='.' read -r -a octets <<< "$ip"
- 设置内部字段分隔符
IFS为.,然后使用read将 IP 地址按.分割成数组octets。 -r防止反斜杠被转义;-a octets表示将结果保存到数组octets;<<< "$ip"是 here string 语法,把变量内容作为输入传递给命令。
for octet in "${octets[@]}"; do
if (( octet < 0 || octet > 255 )); then
log "Error: TARGET_IP '$ip' is not a valid IPv4 address."
return 1
fi
done
- 遍历分割后的每个“八位组”(即 IP 的每一部分);
- 使用算术运算
(( ))判断它是否在0 ~ 255范围之外; - 如果有任意一个不在范围内,就输出错误信息并返回
1。
if ! is_valid_ip "$TARGET_IP"; then
log "Invalid or missing TARGET_IP, exiting script."
exit 1
fi
如果is_valid_ip "$TARGET_IP" return 任何一个非0 都为false (假) ! 取反为 true

浙公网安备 33010602011771号