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

Flask中执行sudo iwlist wlan0 scan异常问题求助

问题描述

我正在更新树莓派上的Python 3.x应用,想要实现扫描附近WiFi网络的功能,但执行sudo iwlist wlan0 scan时遇到问题:

  • 独立脚本中执行该命令完全正常,能返回WiFi列表
  • 在Flask应用中以同一用户执行时,要么无输出,要么报错[Errno 2] No such file or directory: 'sudo'

测试情况

独立脚本(正常运行)

import os
import getpass
import subprocess

output = os.popen("sudo iwlist wlan0 scan").read() # 独立运行时正常工作
print(output)

print(f'Effective user is {getpass.getuser()}')

执行输出:

pi@BenchPi3BPlus:~ $ python3 test.py
wlan0     Scan completed :
  Cell 01 - Address: 11:22:BF:21:33:44
            Channel:1
    
<edit>
        
  Cell 10 - Address: 55:55:EB:66:77:25
            Channel:5
<edit> 

Effective user is pi
pi@BenchPi3BPlus:~ $

Flask中执行(无输出)

app.logger.debug(f'Effective user is {getpass.getuser()}')
output = os.popen("sudo iwlist wlan0 scan").read()
app.logger.debug(f'SUCCESS: {output}')

日志输出:

[2023-11-06 09:49:54 +1100] [3983] [DEBUG] GET /network
[2023-11-06 09:49:55 +1100] [3983] [DEBUG] Effective user is pi
[2023-11-06 09:49:55 +1100] [3983] [DEBUG] SUCCESS: 

改用subprocess.Popen(Flask中报错)

import os
import getpass
import subprocess

cmd = ["sudo", "iwlist", "wlan0", "scan"]
result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, encoding='utf-8')
(stdoutdata, stderrdata) = result.communicate()
if stdoutdata:
    print(stdoutdata.strip())
if stderrdata:
    print(stderrdata.strip())

print(f'Effective user is {getpass.getuser()}')

Flask日志输出:

[2023-11-09 09:24:45 +1100] [11683] [DEBUG] GET /network
[2023-11-09 09:24:46 +1100] [11683] [DEBUG] Effective user is pi
[2023-11-09 09:24:46 +1100] [11683] [DEBUG] runSubprocess threw: [Errno 2] No such file or directory: 'sudo'
解决方案

1. 使用命令的绝对路径

Flask运行时的环境变量PATH可能和终端不同,导致找不到sudo或iwlist。先在终端查绝对路径:

which sudo  # 通常输出 /usr/bin/sudo
which iwlist # 通常输出 /sbin/iwlist

然后在代码中替换为绝对路径:

# os.popen写法
output = os.popen("/usr/bin/sudo /sbin/iwlist wlan0 scan").read()

# subprocess写法
cmd = ["/usr/bin/sudo", "/sbin/iwlist", "wlan0", "scan"]
result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, encoding='utf-8')

2. 给pi用户免密执行iwlist命令

避免使用sudo,直接给pi用户授权无需密码执行iwlist wlan0 scan:

  1. 编辑sudoers文件:
sudo visudo
  1. 在文件末尾添加一行:
pi ALL=(ALL) NOPASSWD: /sbin/iwlist wlan0 scan
  1. 保存退出后,代码中直接执行命令,去掉sudo:
# os.popen写法
output = os.popen("/sbin/iwlist wlan0 scan").read()

# subprocess写法
cmd = ["/sbin/iwlist", "wlan0", "scan"]
result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, encoding='utf-8')

3. 检查并设置Flask的PATH环境变量

在Flask代码中打印当前PATH,确认是否包含sudo和iwlist所在目录:

app.logger.debug(f"Current PATH: {os.environ.get('PATH')}")

如果缺少/usr/bin或/sbin,手动添加:

import os
os.environ['PATH'] += ':/usr/bin:/sbin'

之后再执行命令即可。

4. 改用subprocess.check_output简化写法

推荐使用更安全的subprocess.check_output,同时捕获异常:

import subprocess
try:
    output = subprocess.check_output(["/usr/bin/sudo", "/sbin/iwlist", "wlan0", "scan"], encoding='utf-8')
    app.logger.debug(f'SUCCESS: {output}')
except subprocess.CalledProcessError as e:
    app.logger.debug(f'Error: {e.stderr}')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 16:43:23