Случайны выбор дневника Раскрыть/свернуть полный список возможностей


Найдено 1470 сообщений
Cообщения с меткой

автоматизация - Самое интересное в блогах

Следующие 30  »
rss_rss_hh_new

VirusTotal: проверяем файлы на вирусы в один клик

Вторник, 24 Мая 2016 г. 16:47 (ссылка)






Может быть множество причин, почему на том или ином компьютере вы не поставите антивирусное программное обеспечение: слабое железо или простое нежелание делить его с постоянно жрущим ресурсы антивирусом, уверенность в своих действиях на компьютере или дороговизна, особенно для серверных версий операционных систем. С последним, кстати, постоянно сталкиваются пользователи виртуальных серверов (так называемых VPS / VDS), конфигураций большинства которых едва хватает для нормальной работы современного браузера, а провайдер предоставляет исключительно серверную версию Windows.



Будучи одним из таких пользователей, где далеко не везде установлен полноценный антивирус, постоянно приходится залазить на онлайн ресурсы для проверки тех или иных файлов. Оптимизировать этот процесс я сегодня и решил.



Наиболее простым и популярным среди таких ресурсов (и приятный лично мне) является virustotal.com, у которого есть открытое API и использование его от вас ничего не требует, кроме регистрации на сайте.

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





Читать дальше →

https://habrahabr.ru/post/301638/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
Demetrius

Автоматизация умственного труда

Воскресенье, 15 Мая 2016 г. 16:01 (ссылка)
etheroneph.com/cybernetics/...truda.html

Искусство и развитие личности - от философии и психологии до науки и авангарда.
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
Demetrius

Мышление и кибернетика

Понедельник, 09 Мая 2016 г. 20:18 (ссылка)
etheroneph.com/cybernetics/...etika.html

Искусство и развитие личности - от философии и психологии до науки и авангарда.
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
stertenorva

Заметки фенолога, советника по маркетингу и смысл жизни автоматизации в непривычных сегментах

Пятница, 29 Апреля 2016 г. 16:39 (ссылка)

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

Читать далее...
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

5 стадий API: что мы поняли, написав две версии

Понедельник, 25 Апреля 2016 г. 14:52 (ссылка)

Сегодня мы хотим поговорить о сокровенном — у нас есть API.



Мы писали, а затем переписывали его заново на протяжении четырех лет. И за это время прошли почти все классические стадии “принятия неизбежного”. Кроме одной — четвертой. И хотим поделиться нажитыми непосильным трудом выводами, что делать и не делать, если вы решите делать свой “мощный эпиай”.







Процесс создания API uCoz иногда напоминал сюжет сериала The Knick («Больница Никербокер») — с неудачными операциями, кишками и экспериментами на живых людях.



Стадия первая – Отрицание



По концепции пяти стадий:
На первом этапе человек отказывается принимать то, что с ним случилось.



Вообще, API для конструкторов сайтов — редкость и сейчас. А в 2010-м такого инструмента не было еще ни у кого на рынке.



С одной стороны, определенная потребность в API была: мы видели, что люди активно гуглили “скрипты для uCoz”, получали запросы напрямую — часть пользователей хотела создавать свои дополнения и модификации. С другой стороны — и это была проблема, — в те времена все ресурсы были брошены на другие проекты.



Вопрос «быть или не быть» решился просто. API потребовалось нам самим — для запуска функции поддержки PHP в конструкторе. Мы выделили одного разработчика, и он за полгода сделал наше “начальное API” — это был get-only интерфейс, к которым можно было получать данные страниц из 11 модулей. Данные отдавались только в XML. К моменту запланированного анонса PHP мы не успевали наладить еще хотя бы добавление контента, но у API были и плюсы: с ним можно было запускать пхп-скрипты в бесплатном варианте юкоза.



В общем, мы вышли к пользователям. Получилось прям по классике:







Нас не очень-то приняли… Точнее, в основном хвалили. Но за PHP. А в самом “эпиай” люди не увидели того, что представлялось им при этом волшебном слове. В техподдержку посыпались вопросы: «Как добавлять материалы? Как редактировать? Как получить в json?» А этого всего не было.



Стадия вторая – Гнев



По концепции пяти стадий:
На этом этапе проявляется агрессия ко всему окружающему миру.



К вопросу, что API нужно развивать, в компании вернулись где-то через год. В приоритетах были мобильные клиенты — и мы решили писать все заново с учетом требований ребят, делавших клиенты для iOS и Android. Начальная версия осталась жить сама по себе (и даже до сих пор жива, потому что некоторые ей все же пользуются), а мы стали подбирать исполнителя на новый проект.



“Сам себе менеджер”. В ростовский офис как раз пришел толковый парень Илья: он знал Perl, на котором была написана часть старого uCoz, а когда ему по традиции предложили несколько задач, он выбрал из них работу над API. Проблема была в том, что на время парню пришлось стать самому себе менеджером.



Тут наступил гнев: «Как выяснилось в процессе, синтаксис Perl я понимал, а вот дух — нет.







Потому я долго пытался не работу, а мир лучше сделать: думал все переписать, объекты-классы-паттерны внедрить. Очень много времени ушло, чтобы освоиться с идеологией языка. И вот тогда то, что мне поначалу казалось страшным и хотелось переписать, стало казаться нормой».



К моменту просветления появился менеджер и стал требовать отчет. А была готова только отдача контента по нескольким модулям… В общем, еще раз гнев, теперь с другой стороны, — и Илью перевели на новый проект. Его версии API так и не суждено было увидеть свет.





… Между стадий ...



“Идеальная обучающая задача”. К тому моменту компания пробовала открыть офис R&D в Казани. На месте нужен был носитель знания о всей системе — и появилась идея “вырастить” его через работу над API, которое затронет основные модули системы.



Так в этой истории появился Ринат:







С одной стороны, он был в меру азартен, чтобы взяться за проект (он у нас вообще немного экстремал). С другой — в работе спокоен и рассудителен: все же за плечами не только 700+ прыжков с парашютом, но и 20 лет опыта в ИТ.



Он также был знаком с Perl и имел свежий опыт работы с чужими API — интегрировал «Метрику» и GA в панель веб-мастера.



Первое, что нам пригодилось, так это его рассудительность. Ринат попросил паузу, чтобы детальнее поразбираться в запутанных “кишках” системы, — и только затем озвучить сроки и план реализации. Спустя месяц он вышел с таким предложением:



* Переписываем и дублируем часть функций чисто под API — за время создания системы в ней скопилось много старого кода. И некоторые функции, попробуй ты туда еще что-нибудь засунуть, получились бы «километровыми». Значит, нужны подчищенные двойники чисто под API.



* Используем REST — для упрощения архитектуры запроса, что поможет увеличить производительность.



* Используем Oauth 1.0a — аутентификацию, показавшуюся самой защищенной на тот момент.



* Отдаем в разных форматах — JSON, XML, Text Plain.



* Ну и: get, post, put, delete, мир, труд, май…





Третья стадия – Торг



По концепции пяти стадий:
Тут у вас появляются мысли о том, чтобы договориться с кем-то о лучшей участи



К общему пониманию, как сделать удобно, мы вроде пришли. Но дьявол крылся в деталях и спорах.



Принципиальным вопросом стала область видимости токенов. Наша серверная система, как говорит Ринат, «это законченная инкапсулированная фиговина»: на каждом сервере крутится N юзеров, а когда место на нем кончается, берется новое железо.



Ринат хотел использовать один токен, чтобы получить доступ ко всем сайтам. “Ок, давай поговорим об этом”, — и мы позвали в скайп-чат еще коллег. Как это бывает в коллективных чатах, спорили-спорили, но к коллективному решению не пришли. А в угаре разработки тема подзабылась и вновь всплыла, когда была готова интеграция для половины модулей.







Иного варианта, как тиражировать токен, у нас не было: так появилась архитектура с одним основным авторизационным сервером — получив один токен там, его можно использовать везде.



Оформить как массив или объект? Для нас это была не проблема разряда “что правильно, а что нет”. Это была проблема деталей.



Например, мы отдаем данные в JSON — и возникает проблема с типизированными языками. Не все структуры, полученные от API, удобно распарсить — потому что увеличивается количество кода на клиентской стороне.



А ведь API ориентировано на веб-приблуды, поэтому мы прислушались к мнению разработчиков на Java и C++ и пришли к стандарту: поля отдаем в любом случае, именованные параметры дополняем кодом.



Поля и параметры. Тут торги и обсуждения шли все время реализации. Например, стоит ли выдавать пустой параметр? Поскольку мы ориентировались и под мобильную разработку с использованием API, Ринат в процессе доказал — не нужно: ведь в мобильных приложениях важен трафик.



А какие поля нужны? Тут уже мне, менеджеру проекта, нужно было искать и приводить примеры из реальной практики. Часто я брал помощь зала — опрашивал будущих пользователей API. Если присланный случай стороннего разработчика казался ценными, мы реализовывали нужные поля в самом API, чтобы люди потом не делали через костыли. А позже придумали более элегантное решение — о нем еще расскажем ниже.







Четвертая стадия –… (и о сроках)



По концепции пяти стадий:
На четвертой стадии у вас наступает депрессия. [Мы как-то миновали этот этап]



Работа, запланированная на год, заняла почти два. В процессе возникали совсем непредвиденные сложности. Мы быстро поняли, что:







Проблемы со вторым разработчиком. По плану, после того как Ринат сделает авторизацию, к интеграции API с модулям должен был подключиться второй разработчик.



Мы расписали гугл-док, поставив модули в алфавитном порядке. Работу по ним разделили между исполнителями пополам. Определили график — один модуль в месяц от каждого. Когда пора было приступать, второй человек ушел. А мы уже делали новый проект — конструктор uKit, на который бросили основные ресурсы. С потерей второго программиста, к сроку реализации добавились почти 7 месяцев.



Проблемы с тестированием. В теории процесс задумывался таким: после сервера разработчика все уходит на альфа-сервер, а если тестер говорит “давай дальше”, то проходит бета-тестирование и обновление разливается по сотне серверов.



Но оказалось, что наши обычные тестировщики не очень подходили для работы с API — ведь они “заточены” под тестинг веб-страниц. API же — тонкая вещь. Например, когда происходило изменение внутри модуля, с которым мы интегрировались, что-то могло отвалиться — но тестировщики сначала этого не замечали (потом мы их научили).



Тогда мы открыли 4 тестовых сервера и пригласили продвинутых пользователей на самых ранних этапах. Такое крауд, а потому не очень контролируемое (ты не уверен, когда человек что-то сделает и не бросит ли), тестирование тоже сказалось на увеличении сроков.





Пятая стадия – Смирение (и выводы)



По концепции пяти стадий:
По канонам, наступает согласие с неизбежным



В конце концов, мы смирились с неизбежным — API, как и ремонт, можно начать, но не так-то просто закончить. Вот несколько рецептов, как организовать процесс, чтобы вам было проще.



1. Наладьте обратную связь. Больше связи.



Помимо ветки на форуме и постов в блог, т.е. публичных средств обмена комментариями, я завел на сайте с новой документацией раздел “Лаборатория”. По сути, это была форма обратной связи, где можно было обсудить свой случай в личной переписке.



О новом API мы сообщили ранним пользователям в феврале 2015-го, а процесс выкатки всех модулей на сервера завершили лишь в текущем году. Все это время мы получали через “Лабораторию” репорты, предложения и интересные случаи от пользователей (которые я в том числе использовал в «торгах» с Ринатом).





Поток обращений снизился лишь в последние два месяца



Каждый раз, получив обращение «как сделать вот это или как тут поступить», мы выделяли время и садились смотреть, а как же лучше? Иногда из этого рождались интересные истории.



2. Лично помогите тем, кто не разобрался или [Скрипт в подарок].



Бывало, сообщение из “Лаборатории” заинтересовывало настолько, что мы начинали писать скрипт сами. А затем дарили готовое решение пользователю,



В чем профит? Как говорится, «хочешь найти баг – будь багом». А если хочешь погрузиться в проект – сделай на нем как можно больше всего, чтобы проверить работоспособность и удобство. Заодно так на бирже uScript появились первые решения с использованием uAPI — авторизация через соцсети и неглючный вывод картинок в блоке рекомендованных материалов.



3. Проведите внутренний хакатон.



Как вы помните, мы испытывали недостаток в тестировщиках. Так появилась идея внутреннего хакатона для проверки продукта. Для части наших разработчиков работа с API была совершенно новой и непривычной задачей, так что мы имели возможность пристально наблюдать, как действую люди с разными скиллами.





Ринат обычно не общался напрямую с пользователями, но на хакатон к ростовским разработчикам приехал из Казани. Говорит, “за исключением троллинга, остался доволен собранными в процессе данными и критикой”.





4. Попробуйте что-нибудь автоматизировать.



Моей любимой фишкой для работы с API стало полуавтоматическое создание приложения и токена.







Изначально эта система появились из моих личных потребностей — в один момент устал тратить время на подписывание запросов при создании приложения. Тогда решил написать режим полуавтомата — чтобы ни о чем не думать, а скопировал данные — и приложение готово. Как оказалось, сейчас люди в основном пользуются полуавтоматическим решением.



5. Советуйтесь и меняйте документацию.



Изначально мы расписывали пример запроса в PHP и CURL.





Так было. Как выяснилось в процессе, CURL никто не пользовался.



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



Мы решили, что должен быть дополнительный модуль (написан по современному, ООП), где будет автоматически генерироваться подпись для oauth. Один раз вызвал этот модуль – и далее просто пишешь путь и метод запроса.



Параллельно я прошелся по нашим программистам и спросил – документацию к каким API они считают достойным примером для подражания? Посмотрел рекомендованные примеры и с их учетом составил новую версию документации:







А в качестве теста перед публикацией, попросил коллегу из второго нашего офиса проверить соответствие работы API описаниям в документации для всех методов.



6. Реализуйте мобильность.



Во-первых, это поможет получать хорошие отзывы и расширит вашу аудиторию:



Давно была мечта о создании мобильного приложения для своего сайта. Буду изучать uAPI, чтобы наконец-таки воплотить ее в жизнь


Во-вторых, может стать ценным и новым опытом для внутренней команды. Например, на хакатоне несколько наших ребят запилили вот такое приложение:





Тут можно посмотреть код приложения



7. Не ограничивайте желания пользователей.



Вернемся к вопросу полей. Так как все случаи не предусмотришь, в итоге мы сделали конструктор запросов, с которым можно реализовать любые смелые фантазии на эту тему:







Наконец, мы пришли к тому, что API — это двустороннее движение. Сегодня с помощью uAPI можно сделать авторизацию для любого сайта, переносить материалы с uCoz и наоборот, использовать только нашу БД, но выводить данные на стороннем сайте. Чем больше юзкейсов вы вбираете в инструмент, тем дольше реализация. Но одновременно растет и область его применения.





P.S.



Весь процесс выкатки и боевого тестирования новой версии занял у нас 14 месяцев и 20 обновлений. Вот визуализация.



Бывает, после очередного обновления нам пишут: “Когда же вы его уже допишете?” Но процесс и правда очень сложно остановить (мы не шутили про ремонт). Иногда — по техническим причинам: скажем, когда апдейт системы требует изменений в API. А иногда — по творческим. Например, сейчас мы думаем: когда все интеграции с модулями закончены, почему бы не проработать темы изменения дизайна и настроек сайта по API?



Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/282385/

Комментарии (0)КомментироватьВ цитатник или сообщество
Dmitriykn

Автоматизированный сервис контекстной рекламы

Понедельник, 11 Апреля 2016 г. 14:24 (ссылка)
ktonanovenkogo.ru/seo/prodv...ovost.html


А у нас приятная новость! | KtoNaNovenkogo.ru - создание, продвижение и заработок на сайте



Автоматизированный сервис контекстной рекламы

Пресс-релиз от компании WebEffector.ru. Рассказывать они будут о модуле контекстной рекламы, который позволяет отдать рутину составления и ведения рекламной компании на аутсорсинг
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
Dmitriykn

Автоматизированный сервис контекстной рекламы

Понедельник, 11 Апреля 2016 г. 14:07 (ссылка)

Это цитата сообщения KtoNaNovenkogo Оригинальное сообщение

Автоматизированный сервис контекстной рекламы

http://ktonanovenkogo.ru/seo/prodvizhenie-kommercheskix-sajtov/priyatnaya-novost.html

А у нас приятная новость! | KtoNaNovenkogo.ru - создание, продвижение и заработок на сайте

Автоматизированный сервис контекстной рекламы

Пресс-релиз от компании WebEffector.ru. Рассказывать они будут о модуле контекстной рекламы, который позволяет отдать рутину составления и ведения рекламной компании на аутсорсинг

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
KtoNaNovenkogo

Автоматизированный сервис контекстной рекламы

Понедельник, 11 Апреля 2016 г. 14:05 (ссылка)
ktonanovenkogo.ru/seo/prodv...ovost.html

А у нас приятная новость! | KtoNaNovenkogo.ru - создание, продвижение и заработок на сайте

Автоматизированный сервис контекстной рекламы

Пресс-релиз от компании WebEffector.ru. Рассказывать они будут о модуле контекстной рекламы, который позволяет отдать рутину составления и ведения рекламной компании на аутсорсинг

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
bcinform

Полезные компании на БЦИнформ

Четверг, 31 Марта 2016 г. 10:24 (ссылка)


Компания «Qubit» предоставляет услуги по ИТ-аутсорсингу в виде постоянной технической поддержки и системной интеграции.



5582936_kybit (700x563, 124Kb)
Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

libuniset2 — библиотека для создания АСУ. Лучше один раз увидеть…Часть 6 (Заключительная)

Пятница, 12 Марта 2016 г. 01:10 (ссылка)

В предыдущих частях (часть 1, часть 2, часть 3, часть 4, часть 5) были рассмотрены принципы и механизмы libuniset2, на примере сферической задачки по управлению. Осталось показать, что не вошло в поле нашего зрения… Тех, кто ещё не устал, прошу…



Итог



Целью предыдущих частей, было показать как просто и быстро можно написать (или даже развернуть) систему управления с использованием libuniset2. Если обобщить, то всё сводится к нескольким простым шагам:


  • Заложить проект и наполнить его датчиками, входящими в систему (заполнение configure.xml). Кстати этот процесс можно и автоматизировать, генерируя список датчиков (или настроек) из каких-нибудь других более удобных форматов (источников)

  • Реализовать свои алгоритмы управления, предварительно описав каждый в специальном xml-файле, рассматривая свой процесс как чёрный ящик со входами и выходами

  • Отладить локально, при этом воспользовавшись различными утилитами, входящими в состав libuniset2-utils

  • Написать тесты, используя тестовый фрэймворк — uniset2-testsuite



И всё…

Но многие компоненты входящие в состав libuniset2 так и не были рассмотрены, поэтому я просто кратко опишу что, ещё входит в libuniset2 (может наберусь сил когда-нибудь и их описать с примерами использования)

Компоненты, не вошедшие в обзор




  • SharedMemory — Основной элемент системы, через который осуществляется вся работа. На самом деле, помимо собственно хранения текущих значений, SM умеет:


    • Формирование уведомлений об изменении заказанных датчиков

    • Формирование пороговых датчиков (по аналоговым)

    • Реализует механизм зависимости между датчиками

    • Реализует механизм отслеживания «сердцебиения» для процессов

    • Формирование аварийного следа, по событию (сохранение по срабатыванию датчика («детонатора»), значений указанной группы датчиков за последние N точек)

    • Восстановление данных из резервных SM


  • DBServer — Ведение БД. Сохранение истории изменения по каждому датчику. Работа с MySQL, PostgreeSQL, SQLite, RRD

  • Modbus TCP/RTU (Master,Slave) — Реализация готовых процессов обмена по протоколу Modbus TCP/RTU в режимах Master и Slave. Опрос по нескольким каналам, переключение каналов в случае недоступности slave-узлов и т.п.

  • IOControl — Работа с картами ввода/вывода. Работа реализована на основе использования libcomedi. В рамках этого были разработаны драйвера для поддержки карт ввода/вывода Российского производителя фирмы Fastwel

  • Механизмы обработки входных датчиков — задержка на срабатывание и отпускание, работа по переднему и заднему фронтам сигнала, антидребезг, простые цифровые фильтры для аналоговых сигналов, калибровка (линейная и по калибровочным диаграммам) и другие преобразования

  • UNET — протокол собственной разработки, на основе broadcast UDP. Обеспечивает синхронизацию состояния датчиков между узлами распределённой системы. Готовый компонент, только настроить и запустить. В самой первой статье была представлена структурная схема системы с использованием UNET.

  • LogicProcessor — Реализация простого движка для поддержки «простых» логических схем. Создаётся описание логической схемы в виде xml-файла. Для использования доступны элементы «AND», «OR», «Delay», «NOT»

  • MQTTPublisher — Возможность публиковать данные с датчиков в системе по протоколу MQTT. Реализация основана на использовании проекта mosquitto.

  • uniset-timemachine — Это отдельный, очень интересный, проект (на python). Суть его заключается в проигрывании исторических, данных сохранённых в БД. Данные вынимаются из БД и сохраняются в SM в реальном времени. Например, если подключить при этом графический интерфейс или имитаторы панелей управления, то можно визуально наблюдать, какие кнопки нажимал оператор в тот или иной момент, какие лампочки при этом зажигались, что было на экране графического интерфейса и т.п. Т.е. действительно «машина времени» (Правда этот проект ещё ждёт своего часа, там требуется оптимизация при больших объёмах БД, и пока поддерживается только MySQL. Но это всё дело времени…)



В целом вот тут есть, какая-никакая, но документация.



Немного о реальном применении



Конечно, как известно, любая программа содержит ошибки. Думаю и в libuniset2 не всё идеально, но всё-таки она работает. Работает в реальных проектах. На сегодняшний день, самая «большая система» (просто пока не было проектов побольше) это система управления, где:


  • Около двенадцати тысяч датчиков

  • Около восьмидесяти опрашиваемых ModbusSlave устройств

  • При этом сама система состоит всего из 5 контроллеров и 2 графических панелей

  • Синхронизация состояния всех датчиков между узлами — 150 мсек (UNET)



Были проекты с примерно тремя тысячами датчиков, но зато контроллеров (узлов) было около 18-ти. Эти цифры не призваны «впечатлить», просто хочется показать, что это работает. И переваривает большие объёмы, без специальной оптимизации, хотя механизмы для этого в libuniset2 тоже есть (опрос не на каждом цикле для низко приоритетных или редко меняющихся датчиков и т.п.). В целом уже около тридцати или сорока проектов.



Так что попробуйте libuniset2, это легко :)





Ссылки на проект:





Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/278697/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

[Из песочницы] Проверка статуса антивируса в корпоративной сети посредством VBScript

Пятница, 11 Марта 2016 г. 13:37 (ссылка)

Предисловие



Все началось с того, что купленное корпоративное решение для аудита систем не предоставляло нужную информацию по используемому антивирусному продукту, да и работала слишком уж долго, а панель управления, используемого компанией антивируса, оставляет желать лучшего. Решено было использовать «костыль» для сбора информации об антивирусах в домене.



Приведенный ниже сценарий обрабатывает статусы состояний только антивирусов, используемых в нашей корпоративной сети.



Что же собственно нужно и как это сделать?



Первым делом было установлено, что же нужно получать от антивируса и как это сделать в короткий промежуток времени со всего домена.



Получать нужно было:



1) Наименование установленного антивируса

2) Активен ли антивирус

3) Обновлены ли на нем базы



Собственно способ был найден моментально — использовать WMI (Windows Management Instrumentation).



Пришлось погрузиться в изучение самой структуры WMI на ПК, в этом мне помог замечательный набор утилит WMI Tools.



После чего нужно было решить как взаимодействовать с WMI, не долго думая решил написать сценарий на VBScript.



Разбор полетов



Сценарий обрабатывает 3500 хостов примерно за 1 час. Собственно сам код сценария:



Код сценария
WScript.Interactive = true

compid = 0

On Error Resume Next

Set objDomain = GetObject("LDAP://DOMAIN/OU=Workstations,DC=DOMAIN")

comps = Array()

for each objDomainItem in objDomain
if objDomainItem.objectClass = "Computer" then
idxLast = UBound (comps)
ReDim Preserve comps(idxLast + 1)
comps(idxLast + 1) = objDomainItem.dNSHostName
end if
next

Set objFS = CreateObject("Scripting.FileSystemObject")
Set objNewFile = objFS.CreateTextFile("C:\TEMP\AV_Check\Reports\AV_Status_Scan_is_Running.WAIT")

a = ""


objNewFile.WriteLine ""
objNewFile.WriteLine ""
objNewFile.WriteLine "javascript"" src=""TableFilter/tablefilter.js"">"
objNewFile.WriteLine ""
objNewFile.WriteLine a & ""
objNewFile.WriteLine "

AVSI -- Date: " & Now() & "

"

objNewFile.WriteLine "javascript"">"
objNewFile.WriteLine "var tableToExcel = (function() {"
objNewFile.WriteLine " var uri = 'data:application/vnd.ms-excel;base64,'"
objNewFile.WriteLine " , template = '{table}
'"
objNewFile.WriteLine " , base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) }"
objNewFile.WriteLine " , format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) }"
objNewFile.WriteLine "return function(table, name) {"
objNewFile.WriteLine " if (!table.nodeType) table = document.getElementById(table)"
objNewFile.WriteLine " var ctx = {worksheet: name || 'Worksheet', table: table.innerHTML}"
objNewFile.WriteLine " window.location.href = uri + base64(format(template, ctx))"
objNewFile.WriteLine "}"
objNewFile.WriteLine "})()"
objNewFile.WriteLine ""
objNewFile.WriteLine ""

objNewFile.WriteLine ""
objNewFile.WriteLine ""

for each comp in comps
compid = compid + 1

Set WshShell = WScript.CreateObject("WScript.Shell")
Ping = WshShell.Run("ping -n 1 " & comp, 0, True)
Select Case Ping
Case 0
On Error Resume next
Set oWMI = GetObject("winmgmts:\\" & comp & "\root\SecurityCenter2")
On Error Resume next
Set colAVItems = oWMI.ExecQuery("Select * from AntiVirusProduct")
If colAVItems.count = 0 Then
objNewFile.WriteLine ""
ElseIf colAVItems.count = 1 Then
For Each AntiVirus in colAVItems
If (AntiVirus.displayName) <> "Windows Defender" Then
AVStatus = hex(AntiVirus.ProductState)
If (AVStatus = "61000") _
OR (AVStatus = "51000") _
OR (AVStatus = "41000") Then
objNewFile.WriteLine ""
ElseIf (AVStatus = "41010") _
OR (AVStatus = "61010") _
OR (AVStatus = "51010") Then
objNewFile.WriteLine ""
ElseIf (AVStatus = "60000") _
OR (AVStatus = "50000") _
OR (AVStatus = "40000") Then
objNewFile.WriteLine ""
Else
objNewFile.WriteLine ""
End if
End If
Next
End If
Case 1
objNewFile.WriteLine ""
End Select
Next
objNewFile.WriteLine "
idComputerAV NameAV StatusAV BasesHost Status
" & compid & "" & comp & "No AntiViruses foundDisabledNOT Up to DateOnline
" & compid & "" & comp & "" & AntiVirus.displayName & "ActiveUp to DateOnline
" & compid & "" & comp & "" & AntiVirus.displayName & "ActiveNOT Up to DateOnline
" & compid & "" & comp & "" & AntiVirus.displayName & "On Access scanning disabled!Up to DateOnline
" & compid & "" & comp & "" & AntiVirus.displayName & "UnknownUnknownOnline
" & compid & "" & comp & "UnknownUnknownUnknownOffline
"

objNewFile.WriteLine "javascript"">"
objNewFile.WriteLine "//"
objNewFile.WriteLine ""

objNewFile.WriteLine "

End of scan: " & Now() & "

"

objNewFile.WriteLine ""
objNewFile.WriteLine ""
objNewFile.Close
objFS.MoveFile "C:\TEMP\AV_Check\Reports\AV_Status_Scan_is_Running.WAIT", "C:\TEMP\AV_Check\Reports\AV_Status_" & Date & "_" & Hour(Now()) & "." & Minute(Now()) & ".htm"




Что же собственно происходит? А происходит именно вот что:



1) Мы подключаемся к домену и заходим в каталог Workstations:



Подключение к домену посредством LDAP
Set objDomain = GetObject("LDAP://DOMAIN/OU=Workstations,DC=DOMAIN")




2) Создаем пустой массив, в который будут добавляться ПК пользователей с соответствующим классом Computer:



Создание и заполнение массива
for each objDomainItem in objDomain
if objDomainItem.objectClass = "Computer" then
idxLast = UBound (comps)
ReDim Preserve comps(idxLast + 1)
comps(idxLast + 1) = objDomainItem.dNSHostName
end if
next




3) Создаем файл отчета. Отчет было решено формировать в .htm формате и соответственно формируем страницу в самом сценарии:



Заголовок спойлера
Set objFS = CreateObject("Scripting.FileSystemObject") 
Set objNewFile = objFS.CreateTextFile("C:\TEMP\AV_Check\Reports\AV_Status_Scan_is_Running.WAIT")

a = ""


objNewFile.WriteLine ""
objNewFile.WriteLine ""
objNewFile.WriteLine "javascript"" src=""TableFilter/tablefilter.js"">"
objNewFile.WriteLine ""
objNewFile.WriteLine a & ""
objNewFile.WriteLine "

AVSI -- Date: " & Now() & "

"

objNewFile.WriteLine "javascript"">"
objNewFile.WriteLine "var tableToExcel = (function() {"
objNewFile.WriteLine " var uri = 'data:application/vnd.ms-excel;base64,'"
objNewFile.WriteLine " , template = '{table}
'"
objNewFile.WriteLine " , base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) }"
objNewFile.WriteLine " , format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) }"
objNewFile.WriteLine "return function(table, name) {"
objNewFile.WriteLine " if (!table.nodeType) table = document.getElementById(table)"
objNewFile.WriteLine " var ctx = {worksheet: name || 'Worksheet', table: table.innerHTML}"
objNewFile.WriteLine " window.location.href = uri + base64(format(template, ctx))"
objNewFile.WriteLine "}"
objNewFile.WriteLine "})()"
objNewFile.WriteLine ""
objNewFile.WriteLine ""

objNewFile.WriteLine ""
objNewFile.WriteLine ""

{ ... }

objNewFile.WriteLine "
idComputerAV NameAV StatusAV BasesHost Status
"

objNewFile.WriteLine "javascript"">"
objNewFile.WriteLine "//"
objNewFile.WriteLine ""

objNewFile.WriteLine "

End of scan: " & Now() & "

"

objNewFile.WriteLine ""
objNewFile.WriteLine ""
objNewFile.Close




Для удобства был использован HTML Table Filter Generator, который формирует фильтры по завершению выполнения сценария по сформированной таблице с полями id, Computer, AV Name, AV Status, AV Bases.



Также добавлена кнопка выгрузки таблицы в Excel, которую я нашел на каком-то форуме (честно сказать с ней я даже не возился и оставил как есть, работает криво и, как показала практика, только под FireFox).



4) Массив у нас сформирован и хранится в памяти, теперь рассмотрим заполнение таблицы отчета. Первым делом мы ставим счетчик для присваивания id каждому хосту из массива. После этого вызываем Shell скрипт для проверки доступности хоста путем отправки на него 1 icmp пакета. Создаем условия на обработку отклика, Case 0 — хост доступен и выполняем сценарий сбора данных для заполнения таблицы, Case 1 — выводим в таблицу данные о том, что хост не доступен:



Проверка доступности хоста
for each comp in comps 
compid = compid + 1

Set WshShell = WScript.CreateObject("WScript.Shell")
Ping = WshShell.Run("ping -n 1 " & comp, 0, True)
Select Case Ping
Case 0
{ ... }
Case 1
objNewFile.WriteLine "" & compid & "" & comp & "UnknownUnknownUnknownOffline"
End Select
Next




5) Проверяем есть ли у нас ошибки, а если есть, то просто переходим к следующему хосту. Информация по Антивирусам, Антишпионам и Межсетевым экранам в WMI хранится в каталоге \root\SecurityCenter2, по-этому подключаемся к нему и создаем WQL запрос, который собственно и вытаскивает нужную нам информацию по продукту. Проверяем есть ли вообще на хосте антивирус, а если есть, то проверяем не Windows Defender ли он, а если даже и он, то просто игнорируем его. Каждый антивирус имеет свой код состояния, об этом я узнал на форуме:



Проверка статуса Антивируса и заполнение таблицы
On Error Resume next 
Set oWMI = GetObject("winmgmts:\\" & comp & "\root\SecurityCenter2")
On Error Resume next
Set colAVItems = oWMI.ExecQuery("Select * from AntiVirusProduct")
If colAVItems.count = 0 Then
objNewFile.WriteLine "" & compid & "" & comp & "No AntiViruses foundDisabledNOT Up to DateOnline"
ElseIf colAVItems.count = 1 Then
For Each AntiVirus in colAVItems
If (AntiVirus.displayName) <> "Windows Defender" Then
AVStatus = hex(AntiVirus.ProductState)
If (AVStatus = "61000") _
OR (AVStatus = "51000") _
OR (AVStatus = "41000") Then
objNewFile.WriteLine "" & compid & "" & comp & "" & AntiVirus.displayName & "ActiveUp to DateOnline"
ElseIf (AVStatus = "41010") _
OR (AVStatus = "61010") _
OR (AVStatus = "51010") Then
objNewFile.WriteLine "" & compid & "" & comp & "" & AntiVirus.displayName & "ActiveNOT Up to DateOnline"
ElseIf (AVStatus = "60000") _
OR (AVStatus = "50000") _
OR (AVStatus = "40000") Then
objNewFile.WriteLine "" & compid & "" & comp & "" & AntiVirus.displayName & "On Access scanning disabled!Up to DateOnline"
Else
objNewFile.WriteLine "" & compid & "" & comp & "" & AntiVirus.displayName & "UnknownUnknownOnline"
End if
End If
Next
End If




Бонус



Ну и как бонус код на Python. Он создает текстовый файл, который можно использовать для выгрузки в Excel (в виде разделителя колонок — табуляция). К сожалению посредством LDAP выгружать список хостов у меня не получилось, а так же при использовании большого списка сценарий падает, возможно кто-нибудь доработает его для своих нужд:



Сам код
import wmi
import codecs
import os

with open('Comp_list.txt','r') as list:

file = codecs.open('text.txt', 'w', 'utf-8')

file.write("Computer" + " AV Name" + " Host Status" + " AV Status" + " AV Bases\n")

for comp in list:
response = os.system("ping -n 1 " + comp)
if response == 0:
path = '//%s/root/SecurityCenter2' % comp
c = wmi.WMI(moniker=path)
wql = "Select * from AntiVirusProduct"
wql = c.query(wql)
if wql == []:
file.write(comp + " no AntiVirus found" + " Online" + " Unknown" + " Unknown\n")
else:
for AntiVirus in wql:
ProductState_in_hex = str(hex(AntiVirus.ProductState))
check_install = ProductState_in_hex[0:3]
check_state = ProductState_in_hex[3:5]
check_updates = ProductState_in_hex[5:7]
if check_state == "10" and check_updates == "00":
file.write(comp + " " + AntiVirus.displayName + " Online" + " Active" + " Up to Date\n")
elif check_state == "10" and check_updates == "10":
file.write(comp + " " + AntiVirus.displayName + " Online" + " Active" + " NOT Up to Date\n")
elif check_state == "00" and check_updates == "00":
file.write(comp + " " + AntiVirus.displayName + " Online" + " On Access scanning disabled!" + " Up to Date\n")
elif check_state == "00" and check_updates == "00":
file.write(comp + " " + AntiVirus.displayName + " Online" + " On Access scanning disabled!" + " NOT Up to Date\n")
else:
file.write(comp + " " + AntiVirus.displayName + " Online" + " Unknown state\n" + " " + check_install)
else:
file.write(comp + " Unknown" + " Offline" + " Unknown" + " Unknown\n")
file.close()





Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/279049/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

libuniset2 — библиотека для создания АСУ. Лучше один раз увидеть…Часть 5 (uniset2-testsuite)

Четверг, 10 Марта 2016 г. 20:23 (ссылка)

В предыдущих частях (часть 1, часть 2, часть 3, часть 4) было описано создание двух процессов имитатора и процесса управления и предварительная наладка. А теперь я хотел рассказать о написании функциональных тестов и предназначенного специально для этого средства под названием uniset2-testsuite.



Вводная



В общем случае, тестирование сводиться к идее "Подать тестовое воздействие, проверить реакцию". Т.к. в uniset-системе всё при помощи датчиков то и тестирование сводится к тому, чтобы выставить какие-то датчики и проверить по другим датчикам реакцию системы (Именно системы, т.к. функции могут выполнятся группой процессов и возможно раскиданных по разным узлам).

Эта идея была положена в основу небольшого тестового фрэймворка для проектов на базе libuniset. И называется он uniset2-testsuite. Вообще это даже не фрэймворк, а просто программа (на python) умеющая проигрывать «тестовые сценарии» записанные в виде xml и позволяющая делать различные проверки на uniset-датчиках. Полное описание возможностей можно увидеть в небольшой документации здесь.



А я попробую показать как это делается на примере тестирования нашего процесса управления.



Создание тестового сценария



Итак на текущий момент у нас уже есть следующие компоненты в нашем проекте


  • имитатор — который мы «вручную» протестировали здесь

  • процесс управления — который мы собираемся тестировать

  • SharedMemory — обязательная часть (хранение текущего состояния датчиков)



Наш тест подразумевает, что он будет самодостаточным. Т.е. запустили тест, он сам запустил все необходимые программы, провёл тестирование и завершил программы, выдав отчёт.

А также, для создания тестового сценария, нужно продумать, о том, что мы хотим проверить. Исходя из анализа нашего исходного задания можно выделить следующие простые проверки:


  • Процесс управления ничего не должен делать пока не пришла команда «начать работу»

  • Когда пришла команда процесс управления должен то наполнять «цистерну», то «опустошать».

  • Когда «снялась» команда «начать работу» — процесс управления должен прекратить работу



Попробуем записать всё это в виде тестового сценария...



В общем виде структура сценария выглядит следующим образом:




..секция где описывается какие программы нужно запустить (а потом и остановить)



...проверки...


...проверки...

...




Для нашего случая секция RunList примет вид








Все возможные поля расписаны достаточно подробно в документации к uniset2-testsuite, поэтому не буду останавливаться. Тут видно, что мы просто перечислили какие процессы нам нужно запустить.



Переходим собственно к записи тестов.

Первая проверка, что процесс «ничего не делает». Т.к. результатом деятельности процесса управления является изменение датчика уровня Level_AS (ну ещё конечно выставление команд управления), то мы можем переформулировать «ничего не делает» в «датчики не изменяются какое-то достаточное время».

Запишем…








Т.е. мы проверяем что датчики не меняются в течение заданного времени (holdtime).



Второй тест, это надо проверить собственно работу после подачи команды. Т.е. мы подаём команду «начать работу»(OnControl_S=1), процесс управления подаёт команду «наполняем»(CmdLoad_C=1), уровень в «цистерне» начинает увеличиваться и доходит до верхней планки (не обязательно проверять порог, главное зафиксировать, что меняется).

Дальше процесс управления должен начать «опустошать» цистерну, подав команду «опустошение»(CmdUnload_C=0) и уровень должен снизиться до какого-то уровня. В целом этого достаточно для проверки того, что процесс работает.

Запишем в тест…

Текст теста















И последняя проверка: Что при снятии команды «начать работу», процесс останавливается.

Текст теста










Тут единственная тонкость в том, что мы не знаем на каком уровне завершился предыдущий тест, знаем только, что цистерна опустошалась. Поэтому для проверки того, что ничего не происходит, мы проверяем что уровень не поднимается > 80 заданное время.



В итоге полная версия нашего тестового сценария будет такой

Тестовый сценарий





































Запуск теста



Для запуска теста создадим небольшой скрипт

#!/bin/sh
uniset2-start.sh -f uniset2-testsuite-xmlplayer --confile configure.xml --testfile tests.xml --show-test-log --show-result-report --show-comments --show-action-log $*


запускающий «проигрыватель тестов» с нашим сценарием.

Переходим в каталог src/Algorithms/Controller/test-suite/ запускаем ./01-tests.sh и вот что мы должны увидеть:





Вот собственно и всё с функциональным тестированием.

Хочу только отметить, что это был простой демонстрационный тест. А в целом uniset2-testsuite позволяет писать сложные многосоставные тесты, ссылаться на другие тестовые файлы (строить тестовые иерархии), делать в тестах «автозамены» (т.е. по сути аналог «шаблонов»), сохранять отчёты в формате junit, писать сценарии работающие по протоколу ModbusTCP (т.е. можно тестировать не только uniset-проекты) и т.п. Всё это отражено в документации.



Пока писал эти статьи, понял, что много чего осталось «за кадром». Поэтому будет ещё и «заключительная часть»..



Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/278607/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

libuniset2 — библиотека для создания АСУ. Лучше один раз увидеть…Часть 4 (Наладка)

Среда, 09 Марта 2016 г. 15:32 (ссылка)

В предыдущих частях (часть 1, часть 2, часть 3) было описано создание двух процессов: имитатора и процесса управления… Теперь же настало время наладки.



Итак, на текущий момент у нас уже реализованы и запускаются следующие процессы:



можно начинать наладку…



Наладка. Вводная часть.



Пришло время небольшой поясняющей картинки, чтобы понять что у нас тут происходит…

Структура обмена



На самом деле всё конечно немного сложнее, но рисунок призван помочь понять, как у нас устроены «информационные потоки».

Итак..


  • Всё взаимодействие идёт через SharedMemory

  • Процесс управления получает сохраняет в SM команды, а от SM получает уведомления об изменении датчика уровня(Level_s)

  • Имитатор управления получает от SM уведомления об изменении команд, а в SM сохраняет имитируемое состояние уровня

  • Всё взаимодействие идёт через датчики





Раз всё взаимодействие происходит через датчики, то наладка, в целом, это «выставление датчиков» и «отслеживание текущего состояния датчиков». Для этих целей в libuniset2-utils входит несколько утилит:


  • uniset2-admin — это многофункциональная утилита, но в данном случае позволяет ещё и выставлять (setValue) и смотреть текущее состояние датчиков (getValue)

  • uniset2-smviewer — утилита, позволяющая посмотреть сразу состояние всех датчиков, зарегистрированных в SM

  • uniset2-smonit — утилита, «следящая» (мониторинг) за изменением указанных датчиков



Все эти утилиты активно используются в наладке, но это инструменты отслеживания «внешней» жизни процессов. А есть ещё два дополнительных механизма, которые позволяют наблюдать «жизнь процессов» изнутри:


  • vmonit — мониторинг внутренних переменных объекта

  • LogServer — удалённое чтение логов процесса



Конечно можно было бы начать наладку, запустив сразу два процесса, и смотреть, что там происходит. Но правильнее, если это возможно, проводить наладку процессов отдельно. Давайте начнём с имитатора.



Отладка работы имитатора




  • Запускаем SM — Входим в каталог src/Services/SharedMemory/. Запускаем скрипт start_fg.sh

  • Запускаем имитатор — Входим в каталог src/Algorithms/Imitator/. Запускаем скрипт start_fg.sh





Проверяем, что объекты доступны. Заходим в src/Services/Administrator/ и запускаем ./exist

Должны увидеть следующее

Вывод на экране
[pv@pvbook Administrator]$ ./exist

||=======******** UNISET-EXAMPLE/Services ********=========||

пусто!!!!!!

||=======******** UNISET-EXAMPLE/Controllers ********=========||

(22000 )SharedMemory1 <--- exist ok

||=======******** UNISET-EXAMPLE/Objects ********=========||

(20001 )Imitator1 <--- exist ok
[pv@pvbook Administrator]$




Теперь возвращаемся к началу и вспоминаем, что же должен делать имитатор.

Имитатор должен по приходу команды cmdLoad_C=1 начать имитировать наполнение цистерны (рост датчика Level_AS), а по приходу команды cmdUnload_C=1 — имитировать опустошение цистерны (уменьшать датчик Level_AS).



А значит мы должны


  • выставить датчик cmdLoad_C=1 и увидеть нарастание Level_AS

  • выставить датчик cmdUnload_C=1 и увидеть уменьшение Level_AS



Давайте посмотрим вообще текущее состояние датчиков. Воспользуемся утилитой uniset2-smviewer.

Входим в каталог src/Services/SMViewer и запускаем ./start_fg.sh

Видим это…

Вывод на экране
[pv@pvbook SMViewer]$ ./start_fg.sh

======================================================
SharedMemory1 Датчики
------------------------------------------------------
( 101) | AI | Level_AS | 0
( 100) | DI | OnControl_S | 0
------------------------------------------------------

======================================================
SharedMemory1 Выходы
------------------------------------------------------
( 103) | DO | CmdUnload_C | 0
( 102) | DO | CmdLoad_C | 0
------------------------------------------------------

======================================================
SharedMemory1 Пороговые датчики
------------------------------------------------------




Как видно, всё по нулям… Конечно же в реальном проекте датчиков будет ОЧЕНЬ много, и поэтому можно (и нужно) пользоваться uniset2-smviewer вместе с grep если хочется как-то фильтровать вывод…



Вторая утилита, которая нам понадобится — это uniset2-smonit, чтобы посмотреть, как датчик уровня будет меняться. Давайте запустим её. Заходим в src/Services/SMonit/ и…

Для этой утилиты нужно указать, за каким датчиками мы хотим следить, поэтому у неё есть ключик --sid

(для простоты он вписан сразу в start_fg.sh). В качестве параметра --sid можно указать идентификатор, а можно указать имя датчика. Мы укажем имя Level_AS.

./start_fg.sh Level_AS


Вывод команды




smonit запускается и висит ждёт изменений. При этом в начале выводится текущее состояние датчика. Из вывода можно увидеть название, время последнего изменения (включая микросекунды), идентификатор процесса, который сохранил этот датчик в SM (в данном случае это Imitator1), и текущее значение value (и в виде float — fvalue).



Всё вроде бы готово, выставляем датчик cmdLoad_C=1 и смотрим, как побежал меняться датчик Level_AS.

Для выставления как раз воспользуемся admin-ом.

[pv@pvbook Administrator]$ ./setValue CmdLoad_C=1


и переключившись в консоль, где у нас запущен smonit, смотрим как побежал датчик (от 0 до 100).

Вывод на экран smonit




Значит, увеличение работает. Уменьшение проверяется аналогично… предварительно надо не забыть сбросить предыдущую команду, и мы сделаем это «одним махом»

[pv@pvbook Administrator]$ ./setValue CmdLoad_C=0,CmdUnload_C=1


smonit побежал в обратную сторону (от 100 до 0)

Вывод на экране






Мониторинг внутренних переменных объекта (vmonit)



Теперь я опишу механизм, который позволяет посмотреть внутренние переменные объекта. Вообще, всё очень просто. Зная идентификатор или имя объекта, можно просто запросить у него информацию.

Итак, у нас всё запущено и работает. Давайте посмотрим, что объект Imitator1 нам покажет.

Заходим в src/Services/Administrator и запускаем команду ./oinfo Imitator1

Вывод на экране




Как видно из вывода, команда oinfo позволяет увидеть


  • Состояние всех входов и выходов объекта с привязками к датчикам (внутренних in_, out_ переменных)

  • Текущий список работающих таймеров, с оставшимся временем работы и т.п.

  • Значения всех переменных, с которыми запущен процесс (объявленных в src.xml)

  • Внутреннюю информацию по объекту (размер очереди сообщений, какой был максимум, были ли переполнения)

  • А также пользовательская информация



О пользовательской информации скажу немного подробнее…

У каждого объекта (точнее у скелета класса) есть специальная функция

virtual std::string getMonitInfo() override;


переопределив которую, можно выводить свою информацию, в виде текста (строки). В данном случае имитатор, например, пишет «Текущий режим работы: наполняем» (или «опустошаем»). Можно писать и что-то более сложное.

Пример реализации функции в имитаторе
string Imitator::getMonitInfo()
{
ostringstream s;

s << "Текущий режим работы: " ;

if( in_cmdLoad_c )
s << " наполяем.." << endl;
else if( in_cmdUnload_c )
s << " опустошаем.." << endl;

return std::move(s.str());
}




Добавление в информационный вывод своих переменных


Конечно, когда Вы пишете свой процесс управления, скорее всего у Вас будут, помимо переменных объявленных в xml-файле, ещё какие-то свои поля класса. И конечно захочется так же следить (выводить информацию) о текущем состоянии и своих переменных. Нет ничего проще. Допустим в имитатор мы добавим два счётчика команд.

Добавление в Imitator.h
      ...
private:
unsigned int numCmdLoad = { 0 };
unsigned int numCmdUnload = { 0 };




Тогда, если вы хотите увидеть их в выводе oinfo, просто в конструкторе сделаем два волшебных вызова:

Добавление в Imitator.cc
Imitator::Imitator( UniSetTypes::ObjectId id, xmlNode* cnode, const string& prefix ):
Imitator_SK(id, cnode, prefix)
{
...
vmonit(numCmdLoad);
vmonit(numCmdUnload);
}




Т.е. просто обернули свои переменные в vmonit(xxx). Тут конечно не обошлось без макросной магии, но наверно это не сильно напрягает…

В итоге на экране мы уже увидим и наши переменные (затесавшиеся среди прочих).

Вывод на экран (повторный вызов ./oinfo)




ВАЖНО: поддерживаются пока только стандартные простые типы: bool,int,long и т.п., для всего остального есть универсальная функция getMonitInfo()



Удалённое чтение логов (встроенный LogServer)



Как известно, сколько бы механизмов отладки ни существовало, а любимый cout(или же не любимый printf) всё равно будет использован. Ну что ж, libuniset предоставляет и этот способ. На самом деле, тема очень обширная, если раскрывать все возможности и детали, то это тема для отдельной статьи. Поэтому я покажу применение и расскажу немного деталей…

В сгенерированном скелете класса, есть специальный объект для логов — log. Он по сути имеет интерфейс как cout, только это shared_ptr, поэтому пользоваться им нужно как указателем. Например

log->info() << "......information.." << endl;


или

log->crit() << "......critical" << endl;


У лога есть 15 уровней, включать их можно «параллельно» (т.е. например info,warn,crit), ему можно указать файл, куда писать логи, можно включать и отключать вывод даты и времени в начале каждой строки и т.п. Вообщем много стандартных возможностей. Для каждого объекта можно включать или отключать логи просто указав при запуске аргумент командной строки

Управление логами через аргументы командной строки
--ObjectName-log-add-levels info,warn,crit,level1,... - это добавление логов (к уже включённым)
--ObjectName-log-del-levels info,warn,crit,level1,... - это удаление логов (из включённых)
--ObjectName-log-set-levels info,warn,crit,level1,... - это установка логов (взамен текущих)




Но всё это было бы не так интересно, если бы не наличие такого механизма, как LogServer. В каждом объекте есть встроенный LogServer, который по умолчанию не запускается, соответственно ресурсов не потребляет и вообще не виден никак. Но простым аргументом командной строки

--ObjectName-run-logserver


мы можем его активировать. По умолчанию он запускается на localhost, а в качестве порта использует идентификатор объекта. Но можно и принудительно указать host и port запуска.

Команды для переопределения host и port
--ObjectName-logserver-host  xxx
--ObjectName-logserver-port zzz




После того как у объекта запущен LogServer, мы можем читать его логи, причём удалённо. Просто подключившись по указанному хосту и порту. Для чтения логов существует специальная утилита uniset2-log. При помощи неё можно помимо чтения логов, так же и управлять уровнем вывода логов, запись в файл и т.п., т.е. осуществлять полный контроль над логами объекта. Это очень удобный механизм, т.к. позволяет включать и отключать логи без перезапуска программы (а ведь часто нельзя остановить процесс, но очень нужно посмотреть, что там внутри происходит).

… давайте просто я покажу...

Итак, у нас всё запущено, причём мы добавили в start_fg.sh имитатора строчку

--Imitator1-run-logserver


Кстати в выводе ./oinfo, если кто не заметил, выводится информация о том, запущен ли LogServer. Но давайте я покажу ещё раз (зайдём в каталог src/Services/Administator/ и запустим команду ./oinfo Imitator1).

Вывод информации об объекте (обратите внимание на LogServer)




Итак logserver запущен на localhost и порт 20001. Но по умолчанию (если, конечно, разработчик их принудительно не включит), логи отключены. Соответственно, мы не просто подключимся, а сразу ещё и включим все(any) логи, чтобы сразу начать их видеть. Давайте подключимся (добавим ключик -v, чтобы увидеть отладочную информацию о том, к кому мы подключаемся)

uniset2-log -i localhost -p 20001 -v -a any


Я добавил в функцию таймера лог (уровень 3), для вывода, чтобы продемонстрировать работу.

Добавка в Imitator.cc (mylog3)
void Imitator::timerInfo( const UniSetTypes::TimerMessage* tm )
{
if( tm->id == tmStep )
{
if( in_cmdLoad_c ) // значит наполняем..
{
mylog3 << myname << "(timerInfo): таймер(" << tmStep << ").. наполняем" << endl;
out_Level_s += stepVal;
if( out_Level_s >= maxLevel )
{
out_Level_s = maxLevel;
askTimer(tmStep,0); // останавливаем таймер (и работу)
}
return;
}

if( in_cmdUnload_c ) // значит опустошаем
{
mylog3 << myname << "(timerInfo): таймер(" << tmStep << ")... опустошаем" << endl;
out_Level_s -= stepVal;
if( out_Level_s <= minLevel )
{
out_Level_s = minLevel;
askTimer(tmStep,0); // останавливаем таймер (и работу)
}
return;
}
}
}




Тогда подключаемся (как указано выше) и в другой консоли (заходим в src/Services/Administrator) выставляем команду
./setValue CmdLoad_C=1,CmdUnload_C=0
… а через некоторое время наоборот
./setValue CmdLoad_C=0,CmdUnload_C=1


А вот что мы увидим в логах (удалённо читаемых)

Чтение логов




Пользуясь возможностью удалённо читать логи, важно не забывать, что если вы их включили, то неплохо бы и уходя, отключать, потому что в реальной системе логи не должны работать, ввод/вывод — дорогое удовольствие. И ещё, я немного укажу возможности, которые не раскрыл ранее


  • LogAgregator — объект, позволяющий агрегировать в себе логи от нескольких объектов и управлять ими «централизованно»

  • Поддержка в LogAgregatore регулярных выражений (C++11), позволяющих более гибко выбирать какие логи (от каких объектов) мы хотим читать

  • Возможность в uniset2-log указать сразу несколько команд для включения одних логов, отключения других и, например, чтения третьих. Всё это одной командой.



В реальном применении LogServer конечно запускается один на все объекты (в рамках одного запускаемого файла), которые при этом выстраиваются в иерархию при помощи LogAgregator и можно ими гибко управлять.



Небольшой итог



Каждый раз рассказывая о каких-то механизмах, я пытаюсь соблюсти баланс между кучей подробностей внутреннего функционирования и простотой внешнего применения. Т.е. «вот готовые команды, берите и пользуйтесь — они работают из коробки». Поэтому я многое не рассказал, и может что-то осталось не очевидным… Постараюсь ответить на ваши вопросы.

В целом, если не считать, что нормальное тестирование — это гораздо больше всяких «тестов» (граничные случаи, задание max, min, одновременное выставление команд и т.п.), то с наладкой имитатора мы закончили. Главное было продемонстрировать инструменты для наладки, входящие в libuniset2:


  • утилиты для работы с датчиками и мониторинга их состояния

  • механизм для удалённого просмотра состояния внутренних переменных объекта

  • механизм удалённого чтения и управления логированием (у каждого объекта)



Примерно таким же способом можно наладить и работу нашего процесса управления, но лучше я покажу наладку алгоритма управления, на примере использования более продвинутого способа наладки — написания функциональных тестов с использованием uniset2-testsuite. Об этом в следующей части…



Ну и в конце как обычно ссылочки:





Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/278589/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество

Следующие 30  »

<автоматизация - Самое интересное в блогах

Страницы: [1] 2 3 ..
.. 10

LiveInternet.Ru Ссылки: на главную|почта|знакомства|одноклассники|фото|открытки|тесты|чат
О проекте: помощь|контакты|разместить рекламу|версия для pda