Код Raspberry Pi Python не выполняется должным образом при вызове в php-скрипте с помощью браузера

У меня есть Raspberry Pi 1B под управлением Raspbian 10 (buster) с установленными Python3, Apache2 и PHP, а также полосой светодиодов WS2812.

У меня есть простой скрипт Python (PixelTestOn.py, см. ниже), который включает все светодиоды. При использовании следующей команды терминала все светодиоды загораются, а текст в скрипте отображается, как и ожидалось:

sudo python3 PixelTestOn.py*

PixelTestOn.py

#! /usr/bin/env python3

print("PixelTestOn started<br>")

from rpi_ws281x import PixelStrip, Color

# LED strip configuration:
LED_COUNT = 30        # Number of LED pixels.
LED_PIN = 18          # GPIO pin connected to the pixels (18 uses PWM!).
# LED_PIN = 10        # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0).
LED_FREQ_HZ = 800000  # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10          # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 40   # Set to 0 for darkest and 255 for brightest
LED_INVERT = True     # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL = 0       # set to '1' for GPIOs 13, 19, 41, 45 or 53

# Create NeoPixel object with appropriate configuration.
strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL)

# Intialize the library (must be called once before other functions).
strip.begin()

# Switch all pixels on
for i in range(strip.numPixels()):
    strip.setPixelColor(i, Color(255, 255, 255))
strip.show()

print("PixelTestOn finished")

exit()

У меня также есть php-скрипт (PixelTestOn.php, см. ниже), который должен отображать некоторый текст, выполнять python-скрипт PixelTestOn.py, чтобы включить светодиоды, а затем отображать еще немного текста. При использовании следующей команды терминала отображается HTML-код, загораются все светодиоды и отображается текст в сценарии Python, все, как и ожидалось:

sudo php PixelTestOn.php

PixelTestOn.php

<html>
<head>
<title>Pixel Test</title>

<h3>Test to turn LEDs on</h3>
<p>Should see all LEDs light up</p>
<p></p>
<p>About to call shell_exec() (5)</p>

<?PHP
echo shell_exec("python PixelTestOn.py");
?>

<p>Returned from shell_exec()</p>

</head>

Однако, когда я ввожу следующее в браузер Chromium, отображается вывод html (не код), а текст в первом операторе print() в начале кода python отображается, как и ожидалось, однако светодиоды не загораются и текст во втором операторе print() в конце кода Python не отображается:

localhost/PixelTestOn.php

Если я закомментирую все операторы между двумя операторами print(), тогда скрипт будет выполнен, как и ожидалось, в браузере.

Все файлы хранятся в каталоге /var/www/html, у всех есть www-данные о владельце, и для всех установлены элементы управления доступом «Любой».

Вот что я пробовал:

  • Использование shell_exec(), exec() и system() в php-скрипте
  • Использование разных браузеров (Echo, IE, Chrome) на ПК с Windows 10 и Chrome на планшете Android. Обратите внимание, что SSH включен на Pi.
  • Две разные библиотеки управления светодиодами, rpi_ws281x и neopixel.
  • Общий интерфейс шлюза (CGI). Я не мог заставить это работать с html-формой с кнопкой [Отправить], когда кнопка была нажата для ввода данных, в браузере отображалось сообщение «Внутренняя ошибка сервера».

Мое конечное намерение — создать электронное табло для крикета на основе безголового Raspberry Pi с индивидуально адресуемыми светодиодами, к которому можно получить удаленный доступ через планшет Android.

Обновление После комментария Джея я попытался запустить «python3 PixelTestOn.py», то есть без «sudo» в Терминале, и получил следующее сообщение об ошибке после отображения оператора печати «PixelTestOn start
»:

Can’t open /dev/mem: Permission denied
Traceback (most recent call last):
  File “PixelTestOn.py”, line 24, in <module>
    strip.begin()
  File “/home/pi/.local/lib/python3.7/site-packages/rpi_ws281x/rpi_ws281x.py”, line 130, in begin
    raise RuntimeError(‘ws2811_init failed with code {0} ({1})’.format(resp, str_resp))
RuntimeError: ws2811_init failed with code -5 (mmap() failed)

Увидев заявление «Отказано в доступе», я записал разрешения для файла «/dev/mem», а затем ввел следующее, чтобы изменить контроль доступа на «Любой» для всех трех вариантов.

sudo 777 /dev/mem

Затем я повторно запустил «python3 PixelTestOn.py» в Терминале и снова после того, как отобразился оператор печати «PixelTestOn start
», получил похожее сообщение об ошибке, но на этот раз начиная с:

Can’t open /dev/mem: Operation not permitted

Затем я изменил разрешения на /dev/mem обратно на исходные настройки.


person Colin Winton    schedule 19.02.2020    source источник
comment
Нужно ли запускать PixelTestOn.py от имени sudo? Можно с уверенностью сказать, что ваш PHP-скрипт не запущен от имени пользователя root или чего-то в этом роде.   -  person Jay Blanchard    schedule 19.02.2020
comment
Я добавил обновление после запуска PixelTestOn.py без sudo. Я согласен, что это, скорее всего, связано с разрешениями, просто я не знаю, какие разрешения и где.   -  person Colin Winton    schedule 20.02.2020


Ответы (1)


Добро пожаловать в Stack-overflow.

По приведенной ниже ссылке я вижу, что вы не можете избежать запуска скрипта Python от имени пользователя root — https://github.com/jgarff/rpi_ws281x/issues/155#issuecomment-370939228

Так нужно сделать ниже, точно -

echo shell_exec("sudo python PixelTestOn.py"); # Note the 'sudo' prefix

Кроме того, когда вы запускаете PHP через браузер, такой как Chromium или Firefox и т. д., запрос должен проходить через ваш веб-сервер (Apache, NginX и т. д.). Следовательно, ваш PHP-скрипт будет выполняться как веб-пользователь, а не как root.

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

www-data ALL=(ALL) NOPASSWD: ALL

Это должно решить вашу проблему.

person ArunKolhapur    schedule 21.02.2020
comment
Спасибо за предложение, Арун, к сожалению, оно не сработало, при запуске в браузере php-файл по-прежнему не запускает скрипт python. Однако комментарий в конце вашей ссылки на GitHub предложил попробовать SPI на GPIO 10, поэтому я попробую. - person Colin Winton; 22.02.2020