Мне удалось создать сценарий Python для принятия магнитных проведений карты от основанного на USB читателя. Это, кажется, работает как ожидалось. Часть стандартной программы является вихревой командой для продвижения данных к другому серверу. Так как сервер Ubuntu не будет иметь монитора/клавиатуры/мыши, мой единственный способ ответить пользователю со звуком от докладчика сервера.
Обычно, вихревая команда получает стандартные 200 ответов от другого сервера приложений. Иногда, однако, это получает 500 ошибочных ответов, и я должен передать что-то назад пользователю, чтобы предупредить их, которые "на этот раз не работали, просканируйте свою карту снова".
Простой механизм должен подать звуковой сигнал однажды для успеха и ничего для отказа. Как записано и выполнено от терминала, это работает. Как запланировано от rc.local, системный звуковой сигнал не звучит.
...
args = 'card=' + trackone.group(2)
r = requests.get('http://apiserver/api/', args)
if r.status_code == 200:
# First attempt which doesn't work from rc.local
# print("\a")
# Second attempt, wrap the beep in a shell script
os.system("sh /home/myuser/beep.sh")
else
print(r.status_code)
И я попытался создать простой сценарий оболочки beep.sh:
#!/bin/bash
echo "\a"
Как упомянуто, обе попытки работают от терминала, но не, как выполнено от корня под управлением rc.local. И я знаю, что API называют, так как я вижу записи в журнале.
Строка в rc.local похожа на это:
python '/home/myuser/scancards.py'
Существует ли способ позволить этой команде - как выполнено в рамках процесса init.d - мочь подать звуковой сигнал динамик?
Звуковой сигнал установки с sudo apt install beep
(используют склонный - добирается вместо Кв. для более ранних версий, чем 16,04)
, Так как звуковой сигнал поддерживает различные частоты, Вы могли просто beep -f "$r.statuscode" or beep once for yes
звуковой сигнал-r1and twice for no
звукового сигнала-r2'.
, Если по некоторой неизвестной причине Вы не можете получить больше чем один звуковой сигнал, можно использовать переключатель-f для корректировки частоты для получения, например, более низкого тона для не и более высокого тона для да.
Примеры:
номер: beep -f 250
Да: beep -f 2500
Да, я знаю, что это - короткий ответ, но иногда это - все, что требуется.
дальнейшее исследование указывает, что необходимо будет прокомментировать черный список pcspkr в/etc/modprobe.d/blacklist.conf, чтобы заставить это работать. Вам, вероятно, также придется установить suid, обдумал звуковой сигнал, чтобы заставить это работать (я использовал sudo chmod 4755 /usr/bin/beep
, поскольку у меня нет опасений по поводу других, играющих со звуковым сигналом в этой системе), можно хотеть использовать группы для корректировки полномочий так, чтобы только достойные пользователи могли выполнить звуковой сигнал.
Примечание: Как @JdeBP указывает в его ответе, который Вы можете иметь к , открывают дескриптор файла для оконечного устройства
Источники: man beep
Для подачи звукового сигнала динамика компьютера из сценария Python Вы могли использовать Linux evdev API:
#!/usr/bin/env python
import ctypes
import math
import os
import time
EV_SND = 0x12 # linux/input-event-codes.h
SND_TONE = 0x2 # ditto
time_t = suseconds_t = ctypes.c_long
class Timeval(ctypes.Structure):
_fields_ = [('tv_sec', time_t), # seconds
('tv_usec', suseconds_t)] # microseconds
class InputEvent(ctypes.Structure):
_fields_ = [('time', Timeval),
('type', ctypes.c_uint16),
('code', ctypes.c_uint16),
('value', ctypes.c_int32)]
frequency = 440 # Hz, A440 in ISO 16
device = "/dev/input/by-path/platform-pcspkr-event-spkr"
pcspkr_fd = os.open(device, os.O_WRONLY) # root! + modprobe pcspkr
fsec, sec = math.modf(time.time()) # current time
ev = InputEvent(time=Timeval(tv_sec=int(sec), tv_usec=int(fsec * 1000000)),
type=EV_SND,
code=SND_TONE,
value=frequency)
os.write(pcspkr_fd, ev) # start beep
try:
time.sleep(0.2) # 200 milliseconds
finally:
ev.value = 0 # stop
os.write(pcspkr_fd, ev)
Выполнение beep-evdev.py
как корень. /etc/rc.local
выполняется корнем, и поэтому сценарий должен работать, как.
, Если файл /dev/input/by-path/platform-pcspkr-event-spkr
не делает, существует, удостоверьтесь, что pcspkr
модуль загружается:
root# modprobe pcspkr
сценарий не имеет никаких других зависимостей за исключением python
сам.
как выполнено в рамках процесса init.d
Нет такой вещи как "init.d процесс".
rc.local
часть rc
система, которая была заменена три раза. Та система была заменена van Smoorenburg rc
, выскочка (десятилетие назад), и (с версии 15 Ubuntu) systemd. То, что Вы используете, является третьим повторением назад контейнер совместимости.
В systemd операционных системах, таких как версии Ubuntu 15 и позже, контейнер является systemd сервисом, названным rc-local.service
. Можно узнать его сервисное определение с
systemctl cat rc-local.service
Как Вы видите, это не определяется как присоединение сервиса к оконечному устройству. Сервисный процесс не выполняется с терминалом управления, и его стандартный ввод и вывод не подключен к терминалу.
Тот код Python и сценарий оболочки "не подают звуковой сигнал динамик компьютера". Они пишут символьный № 7 в свои стандартные выводы. Это именно так происходит при выполнении их в интерактивном режиме на сессии входа в систему, что устройство, которое является их стандартным выводом, интерпретирует символьный № 7 как инструкцию шуметь. Перенаправьте стандартный вывод интерактивной команды к /dev/null
и наблюдайте, как тихий код становится.
Который является почему то, что rc.local
(очень) назад контейнер совместимости не имеет никакого соединения с оконечным устройством, важно.
Можно решить это с beep
утилита. Это пытается (если вызвано соответственно) явно открыть дескриптор файла для оконечного устройства и отправить символьный № 7 в (или консоль использования или evdev ioctl()
s на), что устройство вместо того, чтобы просто предположить, что стандартный вывод является оконечным устройством.
Но это стоит думать трудно о не использовании rc.local
, также.
Подавать звуковой сигнал динамик компьютера от /etc/rc.local
Сценарий Python через консоль Linux, Вы могли использовать console_ioctl(4)
: KDMKTONE
, KIOCSOUND
:
#!/usr/bin/env python
import os
from fcntl import ioctl
CLOCK_TICK_RATE = 1193180 # magic https://github.com/johnath/beep/blob/0d790fa45777896749a885c3b93b2c1476d59f20/beep.c#L31-L49
KDMKTONE = 0x4B30 # generate tone include/uapi/linux/kd.h#L25
def beep(console_fd, frequency=440, length_millis=200):
period = CLOCK_TICK_RATE // frequency
ioctl(console_fd, KDMKTONE, (length_millis << 16) | period) # start beeping
# return immediately
beep(console_fd=os.open('/dev/tty0', os.O_RDONLY | os.O_NOCTTY)) # I'm [G]root
Посмотрите beep.py
. Это работает потому что /etc/rc.local
выполняется root
. Можно выполнить его как обычный пользователь при владении терминалом, например, в виртуальной консоли Ctrl+Alt+F1 (нажмите Alt+F7 для переключения назад в менеджер окон GUI).
Удостоверьтесь это pcspkr
модуль ядра не помещен в черный список (прокомментируйте значение по умолчанию):
$ sudo sed -i 's/^blacklist pcspkr/#blacklist pcspkr/' /etc/modprobe.d/blacklist.conf
Удостоверьтесь, что это может быть загружено без любых ошибок:
$ sudo modprobe pcspkr
Удостовериться /etc/rc.local
исполняемый файл:
$ sudo chmod +x /etc/rc.local
print('\a')
(запись U+0007 BELL*
символ к stdout), приводит к разным вещам в зависимости от Вашей среды.
Это может играть bell.ogg
образец загрузил использование pactl
команда (для PulseAudio звучат как сервер):
$ pactl upload-sample /usr/share/sounds/ubuntu/stereo/bell.ogg bell.ogg
Вероятно, что PulseAudio не использует динамик компьютера для проигрывания звука.
В моей системе Ubuntu 16.04, print('\a')
от /etc/rc.local
записи #007
кому: /var/log/syslog
и звуковые сигналы динамик компьютера (systemctl cat rc-local.service
шоу StandardOutput=journal+console
т.е. вывод переходит к файлу журнала и консоли).