subproccess.call через Python CGI скрипт Raspberry Pi

Итак, у меня есть Raspberry Pi, который я настроил в качестве точки доступа с hostapd и isc-dhcp-server. Он передает SSID, я подключаюсь к нему с помощью телефона или ноутбука, перехожу на 192.168.42.1 и открывает страницу, где у меня есть форма для SSID, PSK и идентификатора устройства. Идея состоит в том, что он должен затем подключиться к сети с информацией, которую я ему дал, вызвав кучу вызовов подпроцесса, так как это не так.

Это index.html:

<html>
<body>
<form enctype="multipart/form-data" action="/cgi-bin/set_wifi.py" method="POST">

ssid: <input type="text" size="70" name="ssid" value=""><br>
pass: <input type="text" size="70" name="pass" value=""><br>
devid: <input type="text" size="70" name="devid" value=""><br>

<input type="submit" value="Submit">  
<input type="reset" value="Reset">

</form>
</body>
</html>

Содержимое start_wifi.py выглядит следующим образом:

#!/usr/bin/python

import cgi
import cgitb
import subprocess

cgitb.enable()

print "Content-type: text/html\n\n"

form=cgi.FieldStorage()

ssid_val=form['ssid'].value
pass_val=form['pass'].value
devid=form['devid'].value

#Write Device ID to devid.text
myfile= open("/home/pi/project/devid.txt","w")
myfile.write(form['devid'].value)
myfile.close()

#Write SSID and PSK to wpa_supplicant.conf
file = open('/etc/wpa_supplicant/wpa_supplicant.conf','a')
file.write('\n\nnetwork={\n ssid="')
file.write(ssid_val)
file.write('"\n     psk="')
file.write(pass_val)
file.write('"\n}')

file.close()

subprocess.call("sudo service hostapd stop", shell=True)
subprocess.call("sudo service isc-dhcp-server stop",shell=True)
subprocess.call("sudo ifdown wlan0",shell=True)
subprocess.call("sudo /etc/init.d/networking stop",shell=True)
subprocess.call("cp /etc/network/interfaces-manual /etc/network/interfaces",shell=True)
subprocess.call("sudo /etc/init.d/networking start",shell=True)
subprocess.call("sudo ifup wlan0",shell=True)

У меня есть еще один скрипт на python stopapd.py, который, по сути, все, что после file.close() в скрипте set_wifi.py выше. Когда я запускаю его через терминал, он работает нормально. Останавливает сеть, переписывает интерфейсы, перезапускает сеть и восстанавливает wlan0, если сеть уже сохранена в wpa_supplicant.conf

Проблема в том, что когда set_wifi.py выполняется через cgi, первая половина скрипта работает, он записывает в devid.txt и wpa_supplicant.conf, но единственный subproccess.call, который, я думаю, работает правильно, это

cp /etc/network/interfaces-manual /etc/network/interfaces

который изменяет файл интерфейсов со статического на dhcp...

Кажется, что ни одна из других команд не запускается... но когда я запускаю из терминала тот же код, что и stopapd.py, он работает... Я не знаю почему... любая помощь будет принята с благодарностью.

2 ответа

sudo будет работать только для пользователей, указанных в файле sudoers (/etc/sudoers). Весьма вероятно, что ваш веб-сервер работает с другим пользователем без возможности sudo,

Это объясняет, почему только неsudo команды выполняются.

Либо используйте существующее решение сторожевого таймера, либо добавьте пользователя веб-сервера в файл sudoers. Или используйте пользовательский веб-сервер, работающий от вашего имени.

Это сводило меня с ума, но я продолжал работать над этим, и вот что я придумал...

В set_wifi.py я закомментировал все после file.close() и добавил

file=open('/home/pi/project/set_wifi_ran.txt','w')
file.write('set_wifi_ran') 
file.close()

Затем у меня все время выполняется другой скрипт, называемый stopapd.py... он контролирует set_wifi_ran.txt, и, если он когда-либо изменяется, он выполняет subprocess.calls..., который решает все мои проблемы

while True:
    file=open('/home/pi/project/set_wifi_ran.txt')
    length=(file.readline())
    file.close()

    if length>0
        file=open('/home/pi/project/set_wifi_ran.txt','w')
        file.close()

        subprocess.call("sudo service hostapd stop", shell=True)
        subprocess.call("sudo service isc-dhcp-server stop",shell=True)
        subprocess.call("sudo ifdown wlan0",shell=True)
        subprocess.call("sudo /etc/init.d/networking stop",shell=True)
        subprocess.call("cp /etc/network/interfaces-manual /etc/network/interfaces",shell=True)
        subprocess.call("sudo /etc/init.d/networking start",shell=True)
        subprocess.call("sudo ifup wlan0",shell=True)

Я уверен, что это не очень элегантный способ сделать это... Я был бы признателен за любые отзывы, и я все еще хотел бы знать, почему это не работает через сценарий cgi

Другие вопросы по тегам