You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派PHP配置WiFi时RECONFIGURE命令超时问题求助

树莓派无头系统WiFi配置问题排查与修复方案

问题背景

在64位无头树莓派上搭建开机WiFi检测系统:有WiFi连接时全屏打开指定网页;无连接时启用AP模式,通过Apache+PHP搭建的本地站点扫描WiFi,提交密码后修改wpa_supplicant-wlan0.conf配置。终端执行sudo wpa_cli -i wlan0 reconfigure正常,但PHP端执行时出现**'RECONFIGURE命令超时'**错误。要求保留Pi与设备的AP连接,已排除重启WiFi方案,寻求代码修复或替代的连接检测方案。

现有脚本代码

扫描WiFi的PHP脚本

<?php

$result = shell_exec('sudo iwlist wlan0 scan');
$networks = explode('Cell', $result);

unset($networks[0]);
$data = [];
$cachedNetworks = [];

foreach ($networks as $item) {

    $pattern = '/Address:(.*?)Channel:(.*?)Frequency:(.*?)GHz.*?Quality=(.*?)\/(.*?) Signal level=(.*?) dBm.*?ESSID:&quot;(.*?)&quot;/s';
    preg_match($pattern, $item, $matches);

    if ((!in_array($matches[7], $cachedNetworks)) && ($matches[7] != '')) {
        $cachedNetworks[] = $matches[7];
        $data[] = array(
            'Address' => trim($matches[1]),
            'Channel' => trim($matches[2]),
            'Frequency' => trim($matches[3]),
            'Quality' => trim($matches[4]),
            'MaxQuality' => trim($matches[5]),
            'SignalLevel' => trim($matches[6]),
            'ESSID' => trim($matches[7])
        );
    }
}


echo json_encode($data, true);

配置WiFi的PHP脚本

<?php

$psk = $_GET["password"];
$response['success'] = false;

$fileContent = "country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid=\"" . $_GET['ssid'] . "\"
    psk=\"" . $_GET['password'] . "\"
    key_mgmt=WPA-PSK
}";

// 检查路径并确保文件可写
$filePath = '/etc/wpa_supplicant/wpa_supplicant-wlan0.conf';

if (is_writable($filePath)) {
    // 覆盖文件
    file_put_contents($filePath, $fileContent);

    $response['response'] = "文件已成功覆盖。";
} else {
    $response['response'] = "无法覆盖文件,请检查文件权限。";
    return;
}


// 检查连接状态

$t = exec("sudo wpa_cli -i wlan0 reconfigure");

$output = shell_exec("/sbin/iwconfig wlan0");

if (strpos($output, 'Frequency:') !== false) {
    $response['success'] = true;
    $response['response'] = "已连接。T:" . $t . " 结果:" . $output;
} else {
    $fileContent = "country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1";
    file_put_contents($filePath, $fileContent);
    $response['response'] = "未连接。T:" . $t . " 结果:" . $output;
}

echo json_encode($response);

问题原因分析

  • PHP执行超时限制:Apache的PHP进程默认执行超时较短,wpa_cli reconfigure涉及WiFi协商,耗时可能超过限制导致被终止。
  • 权限与环境差异:PHP以www-data用户执行sudo,可能缺少终端环境中的权限或环境变量,导致命令执行异常。
  • 连接检测逻辑不可靠:用iwconfig的Frequency:字段判断连接状态不准确,部分连接场景下该字段可能不出现。

代码修复方案

1. 延长PHP脚本执行时间

在配置WiFi的脚本开头添加超时设置,给WiFi协商足够时间:

// 延长脚本执行时间至60秒,可根据实际情况调整
set_time_limit(60);

2. 优化wpa_cli执行方式,捕获完整输出

替换原exec调用为proc_open,捕获命令的输出和错误信息,便于排查问题:

$descriptorspec = [
    0 => ['pipe', 'r'], // 标准输入
    1 => ['pipe', 'w'], // 标准输出
    2 => ['pipe', 'w'], // 标准错误
];

$process = proc_open('sudo wpa_cli -i wlan0 reconfigure', $descriptorspec, $pipes);
$t = '';
if (is_resource($process)) {
    $output = stream_get_contents($pipes[1]);
    $errors = stream_get_contents($pipes[2]);
    fclose($pipes[0]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    $returnCode = proc_close($process);
    $t = "退出码: $returnCode | 输出: $output | 错误: $errors";
} else {
    $t = "无法启动wpa_cli进程";
}

3. 替换连接检测逻辑,使用可靠方式

推荐两种更准确的检测方式:

方式一:用iwgetid检查关联SSID

$connectedSSID = trim(shell_exec('iwgetid wlan0 -r'));
if (!empty($connectedSSID)) {
    $response['success'] = true;
    $response['response'] = "已成功连接到SSID: $connectedSSID | wpa_cli输出: $t";
} else {
    // 恢复默认配置
    $fileContent = "country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1";
    file_put_contents($filePath, $fileContent);
    $response['response'] = "连接失败,已恢复默认配置 | wpa_cli输出: $t";
}

方式二:用wpa_cli status获取连接状态

$wpaStatus = shell_exec('sudo wpa_cli -i wlan0 status');
if (strpos($wpaStatus, 'wpa_state=COMPLETED') !== false) {
    $response['success'] = true;
    $response['response'] = "连接成功 | wpa_cli状态: $wpaStatus";
} else {
    // 恢复默认配置
    $fileContent = "country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1";
    file_put_contents($filePath, $fileContent);
    $response['response'] = "连接失败,已恢复默认配置 | wpa_cli输出: $t";
}

4. 配置www-data用户免sudo密码

编辑sudoers文件(执行sudo visudo),添加以下内容,避免PHP执行sudo时需要输入密码:

www-data ALL=(ALL) NOPASSWD: /sbin/wpa_cli, /sbin/iwlist, /sbin/iwgetid

替代连接检测方案(异步执行)

如果wpa_cli reconfigure始终超时,可将配置验证逻辑放到Shell脚本中异步执行,避免PHP等待超时:

1. 创建Shell脚本(/usr/local/bin/wifi-config-test.sh)

#!/bin/bash
SSID="$1"
PSK="$2"
CONF_FILE="/etc/wpa_supplicant/wpa_supplicant-wlan0.conf"
LOG_FILE="/var/log/wifi-config.log"

# 写入WiFi配置
cat > $CONF_FILE << EOF
country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="$SSID"
    psk="$PSK"
    key_mgmt=WPA-PSK
}
EOF

# 执行配置重载
sudo wpa_cli -i wlan0 reconfigure

# 等待10秒让WiFi完成协商
sleep 10

# 检查连接状态
if iwgetid wlan0 -r > /dev/null; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') 成功连接到SSID: $SSID" >> $LOG_FILE
else
    # 恢复默认配置
    cat > $CONF_FILE << EOF
country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
EOF
    echo "$(date '+%Y-%m-%d %H:%M:%S') 连接SSID:$SSID失败,已恢复默认配置" >> $LOG_FILE
fi

2. 赋予脚本执行权限

sudo chmod +x /usr/local/bin/wifi-config-test.sh

3. 修改PHP脚本调用异步执行

<?php
$ssid = $_GET['ssid'];
$password = $_GET['password'];
$response['success'] = true;
$response['response'] = "配置已提交,正在后台验证连接,请稍候查看WiFi状态。";

// 异步执行Shell脚本,不等待返回
shell_exec("sudo /usr/local/bin/wifi-config-test.sh '$ssid' '$password' > /dev/null 2>&1 &");

echo json_encode($response);

内容的提问来源于stack exchange,提问作者ysLuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 21:55:00