Перейти к содержимому


Фотография

RC. Что за зверь такой?

OpenOS rc туториал бесплатное пиво сыр ведьмы

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 6

#1 Онлайн   LeshaInc

LeshaInc
  • Пользователи
  • Сообщений: 1 206
  • Уровень сигнала: 15,55%
  • В игре: 117 час. 1 мин.
  • ГородЛуна

Награды

                       

Отправлено 22 Июнь 2016 - 19:00

Если вы когда нибудь сталкивались с созданием серверов под OpenOS, вам знакома проблема блокирования всего компьютера. Его нельзя использовать, пока сервер не выключится. Некоторые придумывали свои велосипеды, которые запускали event.listen или event.ignore. Но не то это!
 
Для таких вещей существует rc, в OpenOS. Сейчас я расскажу вам, что это за зверь, где он живет и зачем он нам.

 Немного теории B-)
Итак, все скрипты для rc хранятся в папочке /etc/rc.d/. Любой файл с расширением .lua, который находится там, является rc-скриптом.

У такого скрипта все глобальные функции это команды. Запустить такую команду можно командой rc <имя скрипта, без расширения> <имя команды>. Например если мы создадим глобальную функцию start в файлике /etc/rc.d/test.lua, то запустив команду rc test start эта команда выполнится. Все просто.
 
Получить список команд определенного скрипта можно при помощи команды rc <имя скрипта, без расширения>. Например так: rc test.
 
RC сам создает некоторые команды, хотя мы их можем переопределить:

  • enable/disable. Соответственно включают/выключают скрипт. Все включенные скрипты получат команду start при запуске компьютера.
  • restart если есть start и stop. Перезапускает скрипт, то есть поочередно запускает stop и start.

Каждый скрипт можно конфигурировать. Конфиг находится в /etc/rc.cfg.
Формат файла прост:

<имя скрипта> = <конфиг: все что угодно, таблица, текст, число>

По сути это обычный луа-файл, все глобальные значения из которого считаются полями.

Каждый скрипт может получить доступ к своему конфигу. Конфиг записывается в переменную args.

 

С теорией покончено, приступим к практике!

 

Практика

Я предлагаю написать простой эхо-сервер. Он будет слушать определенный порт (из конфига), и отвечать на любое сообщение эхом.

Начнем!

 

Создадим файл /etc/rc,d/echo.lua, и начнем писать в нем код.

 

Нам понадобятся некоторые переменные

-- нам понадобятся библиотека event
-- что бы установить свой обработчик событий
local event = require("event")

-- еще нам нужна библиотека computer
-- что бы подключить компонент `modem`
local component = require("component")

-- будем считать количество ответов
-- зачем? для диванных аналитиков конечно!
local count = 0

-- будем хранить текущее положение
-- что б никто не запустил случайно сервер два раза
local started = false

-- сюда запишем прокси модема, когда убедимся что он есть
local modem

-- а сюда запишем рабочий порт
local port

Создадим обработчик события modem_message. Он будет вызываться при каждом сообщении по сетевой карте.

-- функция ниже будет запускаться
-- при каждом сообщении по сетевой плате
local function onModemMessage(_, _, snd, prt, _, ...)
  -- `_` в нашем понимании - неиспользуемый аргумент

  -- если порт сообщения не совпадает с портом
  -- из конфига, выходим
  print(prt)
  if prt ~= port then
    return
  end

  -- добавим еденицу к счетчику
  count = count + 1

  -- здесь мы уверены, что modem существует
  -- так как обработчик поставится только если у нас есть модем
  modem.send(snd, prt, ...)
  --         /     |    \
  -- получатель, порт, данные

  -- просто напросто пересылаем отправителю то что он
  -- отправил нам =)
end

Теперь мы добавим команду start, которая запустит наш сервер.

-- функция ниже глобальная, `local` нет.
-- потому _rc_ ее будет смело считать командой
-- а команда эта будет запускать наш сервер
function start()
  -- мы должны проверить, есть ли у нашего сервера
  -- сетевая карта
  if not component.isAvailable("modem") then
    -- если ее нет, мы выводим ошибку и выходим
    io.stderr:write("Сетевая карта не найдена!")
    return
  end

  -- еще нам нужно проверить, выключены ли мы
  -- если это не так, снова ошибка
  if started then
    io.stderr:write("Сервер уже запущен!")
    return
  end

  count = 0   -- сбросим счетчик
  started = true   -- теперь мы знаем, что с этого момента
                   -- сервер включен.

  port = args or 666
  -- args это переменная, в которую _rc_ запишет данные из конфига
  -- конфиг находится в /etc/rc.cfg
  -- но если в конфиге порт не настроен, используем дефолтный

  modem = component.modem
  -- мы проверили, что модем существует,
  -- поэтому смело его подключаем

  -- откроем порт
  modem.open(port)

  -- нам нужно сделать так, что бы все сообщения
  -- по сетевой карте обслуживались нашей функцией
  event.listen("modem_message", onModemMessage)
  -- ну а теперь мы точно включились!
end

Куда без команды stop? Добавим ее!

-- эта функция тоже глобальная, поэтому считаем ее командой
-- эта команда остановит сервер
function stop()
  -- мы должны проверить, включен ли вообще сервер
  -- если он не включен, какой толк его выключать, верно?
  if not started then
    -- если он не включен, выводим ошибку и выходим
    io.stderr:write("Сервер уже выключен!")
    return
  end

  count = 0   -- опять же сбрасываем счетчик
  started = false   -- запоминаем, что теперь
                    -- сервер выключен

  -- теперь нам нужно по-настоящему выключить сервер
  event.ignore("modem_message", onModemMessage)
  -- все! с этого момента сервер выключен, и не принимает сообщение
end

Еще самая малость, добавим команду printCount, которая будет отображать количество полученных сообщений.

-- и это тоже команда, думаю вы понимаете
-- а эта команда напишет количество отправленных сообщений
function printCount()
  -- выводить информацию будем только если сервер не запущен
  -- поэтому выведем ошибку, если он не включен
  if not started then
    io.stderr:write("Сервер выключен!")
    return
  end

  print(count)   -- пишем количество подключений
                 -- диванные аналитики ликуют!
end

Ну вот и все, программа сделана, диванные аналитики ликуют, инженеры недоумевают. :dirol:

 

Полный код:

Спойлер

 

 

Время QA! :crazy_pilot:

 

Симулируем Васю Пупкина...

Спойлер

 

А вот уже на другом компьютере отправлено сообщение на работающий сервер.

Спойлер

 

Счетчик тоже работает.

Спойлер

 

Установим значение в конфиге.

Спойлер

 

Проверим...

Спойлер

 

Все работает, инженеры ликуют!  :)

 

 

 

Такую систему очень удобно использовать для всяческих серверов. Сервер может спокойно работать в фоне, а в главном потоке спокойно можно запускать консоль сервера, интерпретатор луа,  rm -rf /  ...

 

Enjoy!


Сообщение отредактировал LeshaInc: 22 Июнь 2016 - 19:06

  • Zer0Galaxy, Totoro, Fingercomp и 4 другим это нравится

#2 Оффлайн   qwertyMAN

qwertyMAN
  • Пользователи
  • Сообщений: 1 427
  • Уровень сигнала: 0,14%
  • В игре: 1 час. 3 мин.
  • ГородCity17

Награды

                             

Отправлено 22 Июнь 2016 - 19:18

event.listen forever  ;)



#3 Оффлайн   NEO

NEO
  • Пользователи
  • Сообщений: 1 748
  • Уровень сигнала: 4,84%
  • В игре: 36 час. 25 мин.
  • ГородСолнце

Награды

   3                        

Отправлено 22 Июнь 2016 - 19:20

Весь код в спойлеры надо добавить.



#4 Онлайн   LeshaInc

LeshaInc
  • Автор темы
  • Пользователи
  • Сообщений: 1 206
  • Уровень сигнала: 15,55%
  • В игре: 117 час. 1 мин.
  • ГородЛуна

Награды

                       

Отправлено 22 Июнь 2016 - 19:29

event.listen forever  ;)

 

Это точно.

 

Весь код в спойлеры надо добавить.

 

Со спойлерами пропадает весь запах "крутого туториала". :) А еще пропадает юзабилити, надо тыкать на эти кнопуськи "Открыть", не удобно ИМХО.



#5 Оффлайн   Totoro

Totoro
  • Хранители Кода
  • Сообщений: 1 735
  • Уровень сигнала: 0,29%
  • В игре: 2 час. 13 мин.

Награды

                                      

Отправлено 22 Июнь 2016 - 20:49

Весь код в спойлеры надо добавить.

 

Имхо спойлеры эти выглядят фигово в статьях.

Плюс, это туториал. Код тут такой же элемент статьи как и текст. Читаешь текст, читаешь код. Получаешь комплексное впечатление.

А необходимость постоянно тыкать на спойлеры будет раздражать.

Ну и наконец, фрагменты кода просто визуально разбавляют унылую стену текста.


  • LeshaInc это нравится

#6 Оффлайн   NEO

NEO
  • Пользователи
  • Сообщений: 1 748
  • Уровень сигнала: 4,84%
  • В игре: 36 час. 25 мин.
  • ГородСолнце

Награды

   3                        

Отправлено 22 Июнь 2016 - 21:04

Имхо спойлеры эти выглядят фигово в статьях.

Плюс, это туториал. Код тут такой же элемент статьи как и текст. Читаешь текст, читаешь код. Получаешь комплексное впечатление.

А необходимость постоянно тыкать на спойлеры будет раздражать.

Ну и наконец, фрагменты кода просто визуально разбавляют унылую стену текста.

 

 

Это точно.

 

 

Со спойлерами пропадает весь запах "крутого туториала". :) А еще пропадает юзабилити, надо тыкать на эти кнопуськи "Открыть", не удобно ИМХО.

:facepalm:



#7 Онлайн   eu_tomat

eu_tomat
  • Хранители Кода
  • Сообщений: 880
  • Уровень сигнала: 6,38%
  • В игре: 48 час. 1 мин.

Награды

                          

Отправлено 23 Июнь 2016 - 09:49

Весь код в спойлеры надо добавить.

В этом коде комментариев больше, чем самого кода. Хорошее оформление, полезная информация - годная статья

Существование штатного механизма для написания сервисов в OpenOS тоже радует.





Темы с аналогичным тегами OpenOS, rc, туториал, бесплатное пиво, сыр, ведьмы

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных