Заметки

Позднее Ctrl + ↑

Фред

Игорь Сахаров перепел «Фреда» Короля и Шута на английском языке:

Роцк! Ро-о-оцк! :-)

Если серьёзно, я уже как-то писал про это, но мне ни разу не лень повторить: такие штуки — один из самых простых и приятных способов запомнить кучу слов и оборотов.

Да, вокруг хватает крутанов с цепкими мозгами, которым этот трюк не нужен; он, скорее, для обычных ребят вроде меня самого. У нас все эти what a good match you and I и spellbound by your beauty pure and true в других обстоятельствах порой улетучиваются из головы, ну… Секунд через десять?

А так — смотришь ролик, невольно подпеваешь и не замечаешь, как текст намертво оседает в памяти.

2020-05-24 английский

Об идеальном балансе

Хочу поделиться парой классных текстов о современном софте. Они не особенно свежие (первый-то уж точно), но наверняка ведь кто-то пропустил:

К чему я это вспомнил? На прошлой неделе участвовал в хакатоне среди программистов нашей компании. Узнал кучу клевых штук, а по итогам даже занял первое место (вместе с ещё двумя участниками, у которых получились очень похожие решения).

(если вы — тоже сотрудник «Первого БИТа», то итоги хакатона лежат на портале; там же — отзыв другого победителя, Димы Лещенко)

В процессе нужно было развернуть и настроить целую гору софта: EDT, RabbitMQ, Docker, GitLab, JIRA, SonarQube и ещё вагон инструментов поменьше и попроще. Ладно, к RabbitMQ у меня претензий нет: легкий и быстрый, но вот остальное… Про хороший аппетит EDT я знал и раньше, а вот прожорливость GitLab и JIRA по-настоящему удивила.

Да, в моём случае всё запускалось в докере; да, конфигурация не была оптимальной (например, было развернуто несколько серверов PostgreSQL вместо одного); да, докер был для Windows, а его реализация под эту платформу — тема для едких шуток у всех сисадминов, с которыми я знаком. Но потратить 12 гигабайт ОЗУ прямо со старта?! Про процессор вообще молчу — нагрузка была такая, будто компьютер просчитывал ядерный взрыв в реальном времени.

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

У меня нет ответа. Думаю, ни у кого нет. Это такой вечный холивар внутри профессии: какую сторону не займи, на деле все равно балансируешь между двумя крайностями — с одной стороны, надо писать хороший, быстрый код, с другой — надо не свалиться в преждевременную оптимизацию. Первое в итоге дает чистое удовольствие от хорошо сделанной работы: вспоминаешь, что ты, черт побери, неплох! Второе — просто позволяет не нажить бед с башкой в поисках идеального алгоритма сортировки пузырьком :-)

2020-05-20 работа

Просмотр таблицы значений

Закинул на GitHub короткую функцию, с помощью которой произвольную таблицу значений можно превратить в табличный документ.

Для чего? Чтобы посмотреть её содержимое. Саму таблицу на клиент передать нельзя, а вот табличный документ на её основе — можно. Кроме того, у табличного документа есть клиентский метод Show(), который отображает его в отдельном окне.

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

2020-05-16 готово

Самодокументируемый код

Всем привет! С вами снова Джонни Кэтсвилл и передача «Самодокументируемый код»!

Сегодня мы переберем строки таблицы значений с Н по Й:

:|

Вроде и мелочь совсем, но когда в пределах одного модуля в пятый раз натыкаешься на такой подход к именованию переменных — глаз невольно начинает дергаться :-)

Дело даже не в том, что этот участок труднее разобрать — просто он неплохо говорит о качестве модуля в целом. Скорее всего, писавший его программист был вымотан, и поблизости можно встретить что-нибудь вроде отважной выгрузки справочника номенклатуры в таблицу значений, чтения кучи объектов «через точку» и прочего тяп-ляп.

2020-05-03 код с запашком

Управление службами через PowerShell

На днях набросал себе несколько скриптов на PowerShell'е для запуска и остановки служб на рабочем ПК. Наработки в итоге не пригодились, так что зафиксирую себе пару примеров на будущее, чтобы не потерять:

get-service -Name 1C:Enterprise* | Where-Object {$_.status -eq 'running'} | stop-service -pass
get-service -Name *SQL* | Where-Object {$_.status -eq 'running'} | stop-service -pass

Обе строки выше делают одно и то же: ищут службы с определенным именем, проверяют их состояния и, если службы запущены — останавливают их. Имена служб удобно задавать через шаблоны — например, у Microsoft SQL Server целый выводок служб с разным назначением и их удобно пристрелить одной строкой. Или, скажем, служба сервера 1С:Предприятия — она одна, зато её длиннющее название просто лень писать полностью :-)

Примерно тот же подход, кстати, работает и с обычными процессами. Так, строка ниже ищет процесс obs64; если находит — останавливает.

get-process -Name obs64 | stop-process -pass

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

2020-04-28 PowerShell рабочее место

Black Mesa

Легендарный, но уже откровенно постаревший Half-Life тщательно отретушировали и дополнили кучей новых задумок. Вышло здорово; прям видно, что фанаты старались :-) Особенно Зену пошло на пользу — разве что завод, по-моему, стоило сделать покороче. Впрочем, бой с Нихилантом переделали так, что он с лихвой окупает все страдания.

Есть мелкие косяки с музыкой, оптимизацией и переводом, но ничего особо критичного. Учитывая, сколько шла разработка — удивительно, что вообще дошло до релиза сквозь типичные для долгих проектов проблемы вроде усталости и выгорания команды. И это не считая титанической работы по переделке проекта двадцатилетней давности на современные рельсы! Quite a nasty piece of work you managed over there, guys. I am impressed.

Болото Кристаллическая пещера Пылающее небо Мухоловка

2020-04-13 видеоигры

Пустая() или ЗначениеЗаполнено()?

Несколько дней назад обсуждал с коллегой, какой способ проверки заполнения ссылки лучше. С одной стороны, время назад на каком-то курсе я слышал авторитетное мнение, что функцию ЗначениеЗаполнено() нужно использовать с осторожностью, так как её логика — сопоставлять переменную всем возможным пустым значениям, которые есть в конфигурации. И это, мол, огромная тормозная лапша. Как альтернативу автор курса советовал использовать метод ссылки Пустая(), а композитные реквизиты проверять примерно так:

СсылкаЗаполнена = Ссылка <> Неопределено И Не Ссылка.Пустая();

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

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

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

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

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

2020-04-11 готово

Запись видео в ShareX

Прежде чем приспособить OBS Studio для записи видео (писал о ней в предыдущей заметке), я пробовал использовать ShareX. Программа поначалу неплохо справлялась, однако от неё пришлось отказаться из-за неприятного бага: иногда при попытке завершить запись софт портил полученное видео.

Я гуглил, но причину понять так и не смог. Впрочем, неудивительно — ShareX использует ffmpeg для записи видео, а это дитя опенсорца вместо адекватной диагностики невозмутимо вываливает целый рулон логов. Разбирать его без соответствующего опыта — занятие для клинического оптимиста.

Впрочем, как инструмент для создания скриншотов ShareX почти безупречна. Обилие опций слегка напоминает замотанного человека в приступе гиперактивности :-)

Настраиваем скриншоты

— Протестирую сам! Сам все протестирую! И полы вымою!

Эффективность не работает. Илья Якямсев

2020-04-08 рабочее место

Запись видео

Я работаю удалённо и с коллегами общаюсь через Zoom и Slack. В основном в чатах, но многие темы по-прежнему проще обсудить голосом. И вот тут-то возникают проблемы: приходится забыть про индексацию и поиск по сообщениям, а главное — нет никакого архива разговоров. Иногда очень нужно вспомнить: кто говорил? Что конкретно? Когда?

Zoom и Slack сами по себе эту проблему не решают. Первый умеет записывать только те конференции, которые организуешь ты или которые тебе разрешили писать (короче, далеко не все), а второй писать видео не умеет вообще.

Решение проблемы

Я закрыл вопрос какое-то время назад, поставив себе OBS Studio — популярный среди стримеров софт для записи экрана. С записью конференций он прекрасно справляется. Настройка минимальная: пишем весь экран, звук с микрофона и все звуки, которые воспроизводятся. В микшере по результатам тестовых записей можно натыкать фильтры — усиление, шумоподавление и так далее.

Настройка OBS Studio

В настройках нужно указать папку, куда будут складываться записанные видео (Вывод → Запись → Путь записи). Поскольку мы пишем звонки и файлов будет много, лучше сразу разложить их в папки по дням — для этого идем в расширенные настройки и в поле «Формат имени файла» указываем нечто вроде %CCYY-%MM-%DD/%hh-%mm-%ss.

Быстрое управление записью

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

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

С оборудованием всё было просто: у меня эргономичная клавиатура от Microsoft, программируемых кнопок на ней — вагон. Хуже с софтом: OBS Studio понимает некоторые параметры запуска, но список откровенно бедноват — даже остановки записи нет. Хотелось бы побольше.

В итоге решил задачу через плагин к OBS Studio, который дает порулить запущенным экземпляром программы. Он придуман для удаленного управления записью (например, со смартфона), но никто не мешает использовать его локально.

Схема получилась такая:

  1. Ставим OBS Studio и плагин obs-websocket к ней. Снимаем галку «Enable System Tray Alerts» в настройках (Tools → WebSockets Server Settings), не то программа примется сообщать о каждом чихе.
  2. Кладем куда-нибудь утилиту, с помощью которой этим плагином можно рулить из командной строки.
  3. Вешаем на одну кнопку OBSCommand.exe /startrecording, а на другую — OBSCommand.exe /stoprecording.
  4. Готово, вы великолепны!

При вызове на долю секунду видно консоль (OBSCommand запускается, связывается с obs-websocket и ждет ответа). Сначала хотел как-нибудь скрыть это окно, но, поразмыслив, передумал — если OBS Studio не будет запущен или возникнет какая-то проблема, консоль не закроется и я хотя бы узнаю, что запись не началась.

2020-04-03 рабочее место

Неразрешимые ссылки

Чаще всего неразрешимые ссылки на объекты метаданных образуются в ходе удаления объектов (и, иногда, при объединении конфигураций). На ИТС есть статья по этой теме, там хорошо описаны детали.

На работе программы битые ссылки сказываются далеко не всегда. Конечно, поле без привязки к данным заметить несложно, но вот удалили вы, допустим, функциональную опцию — что с того, что ссылка на неё осталась где-нибудь в команде на форме? Она будет просто лежать, как обрезанный провод, инертный и безвредный. Ничего по нему не идет.

Однако такие штуки постепенно захламляют конфигурацию, и от них правильно избавляться, и на ИТС предложена не больно-то эффективная методика (последовательный перебор всех возможных мест, где может быть битая ссылка). Представьте себе сложную форму документа с множеством элементов; сколько времени придется потратить на поиск? Еще не факт, что успешный.

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

Проблема, кстати, может быть не в элементах, а в самой форме — но там её куда проще найти (хранилище настроек, условное оформление, команды; в общем, кандидатов немного).

Ещё можно сделать выгрузку конфигурации в файлы и порыться в полученных XML-ках. Это неплохая идея ещё и потому, что сам по себе внешний вид элементов может вас обмануть: если, например, речь идет о ссылке на функциональную опцию в команды формы, то при проверке свойств команды вы даже не заметите, что есть какая-то проблема. А вот в XML-ке будет болтаться какой-то подозрительный GUID вместо наименования опции — считай, явка с повинной :-)

2020-03-10

Фильтрация стандартных реквизитов

Короткий фрагмент кода из обработки для настройки механизма истории данных, о которой я только что писал. Эта функция определяет, является ли Attribute стандартным реквизитом с именем StandardAttributeName, принадлежащим объекту метаданных MetadataObject. Где она нужна? Допустим, вы перебираете стандартные реквизиты объекта и по какой-то причине хотите пропустить один из них.

На первый взгляд решение выглядит максимально индусским. Почему бы, например, просто не сравнить два реквизита — проверяемый и тот, что хотим отсеять?

If Attribute = MetadataObject.StandardAttributes.Order Then

Дело в том, что такой код не сработает: результат операции сравнения двух стандартных реквизитов объекта метаданных в платформе 1С — всегда Ложь.

О'кей, скажете вы — может, тогда не будем усложнять и напишем вот так?

If Attribute.Name = "Order" Then

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

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

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

Что до конструкции Try/Catch — она тут на тот случай, если стандартного реквизита с таким именем в конфигурации нет вообще (и попытка обратиться к нему по имени приведет к ошибке).

2020-03-09 готово

Настройки истории данных

Выложил на GitHub обработку для настройки механизма истории данных, который сравнительно недавно появился в платформе. Эта обработка:

  1. Строит дерево объектов, для которых может вестись история данных;
  2. Подсказывает, для каких объектов история данных ведется сейчас;
  3. Дает возможность включить или выключить историю данных для объектов и их реквизитов.

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

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

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

2020-03-09 готово работа

Девятый вал

Покупал вчера утром подарки своим женщинам. Пока флорист собирала букеты, болтал с ней ни о чем и случайно перехватил взгляд в сторону нарастающей толпы покупателей — спокойный такой, с отчетливо читающейся обреченностью. Так моряки, наверное, смотрят на вздымающуюся волну, которая вот-вот похоронит их шлюпку :-)

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

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

2020-03-09 тем временем работа

Топ исключений по ТЖ

Выложил на GitHub скрипт на баше, который по собранному технологическому журналу 1С определяет наиболее частотные исключения.

Скрипт анализирует события EXCP. Это основной источник информации об ошибках, хотя, конечно, не единственный: например, есть EXCPCNTX (событие, которое началось, но не закончилось в тот момент, когда произошла ошибка). Кроме того, если исключение происходит во время серверного вызова, то в поле RetExcp у события CALL будет текст ошибки, которая вернется на клиент.

Впрочем, в большинстве случаев EXCP и, иногда, EXCPCNTX вполне достаточно. Часто их собирают просто по умолчанию — нагрузки это не создает, зато позволяет прогонять собранные логи через какой-нибудь инструмент аналитики (скрипт выше, например) и держать, так сказать, руку на пульсе.

2020-02-16 bash готово

Отладка через HTTP

В конце недели столкнулся с довольно глупой ситуацией: отладка через TCP/IP на сервере 1С перестала работать. То есть сам по себе режим отладки включен, однако конфигуратор «не видит» контекстов отладки на сервере.

Ситуация глупая в том смысле, что понять причину довольно сложно: явных ошибок платформа не выдает. После проверки очевидных вариантов (фаервол, порты и так далее) остается только руками разводить.

Решил проблему, переключившись на отладку через HTTP. Инфрастуктурно это более сложная схема, но настраивается она довольно просто; если вкратце, то нужно:

  • Запустить службу агента сервера с ключами «-debug -http».
  • В параметрах отладки конфигуратором (Сервис → Параметры → Отладка) указать HTTP как протокол отладки и сервер отладки кластера как сервер отладки.

Подробнее процесс настройки описан на ИТС.

2020-01-26

Неподдерживаемый код

Случайно наткнулся на пример запроса в 1С, который считает разницу между двумя датами (в годах, месяцах и днях).

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

И это еще далеко не самый наглядный пример. Взять хотя бы регулярки для проверки e-mail. Хочется выйти подышать, да? :-)

2020-01-18

Тысяча и одна ночь с 1С

Архитектор нашего основного продукта (и, по совместительству, мой тимлид) рассказывает о том, как мы внедряли 1С в Дубае. Погружений в технические детали нет, так что можно смотреть всем, кто хотя бы чуть-чуть в теме.

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

2020-01-16 работа

В пятьдесят раз быстрее

Получил вводную: документ закрытия месяца у заказчика проводится без малого час. База не особенно большая, но такая продолжительность в любом случае не вариант. Даже если учесть, что закрытие месяца — это ни разу не частотная операция и её можно делать, например, ночью.

Лезу в код, делаю замер производительности и вижу, что и почти всё это время платформа тратит на одну-единственную процедуру, выполняя пакет запросов. Смотрю первый из них; ну, думаю, классика — запрос данных через точку от составного типа. Наверняка СУБД пристегивает целый вагон соединений с тяжеленными таблицами документов, вот оптимизатор и не успевает набросать адекватный план.

Проверяю теорию — так, а тип SalesDocument включает всего восемь документов. Это, условно, в пределах допустимого (считается, что оптимизатор в состоянии подобрать адекватный план выполнения запроса, если количество соединений — в пределах восьми).

Смотрю размеры таблиц документов — не особенно-то и большие. Выполняю запрос отдельно от пакета — да, работает не мгновенно (читает около 350 000 записей и отбирает примерно 200 000), но никак не час.

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

Проверил — именно тут платформа и проводит большую часть времени, ожидая ответа от СУБД.

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

Это тот случай, когда общая рекомендация 1С сработала идеально — вместо 50 минут документ стал проводиться за три, а после дополнительной оптимизации кода — за минуту. То есть, в пятьдесят раз быстрее того, что я имел вначале.

Такой результат я счел достаточным (минута для закрытия месяца — это в общем случае нормально) и остановился.

2019-12-05 готово оптимизация работа

Зачем нужен ЦУП?

ЦУП нужен, чтобы:

  1. Найти в системе узкое место (медленный код, тяжелый запрос);
  2. Расследовать конкретные блокировки или взаимоблокировки.

В первом случае можно включить анализ запросов и, допустим, серверных вызовов. По результатам можно понять, что в системе грузит сервер приложений, а что — сервер СУБД. Часто так делают даже не решая конкретную проблему, а просто чтобы устранить узкие места и увеличить запас прочности системы на будущее.

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

В обеих случаях мониторинг запускают только в периоды основной нагрузки и минут на десять-пятнадцать. Массив исходных данных получается сравнительно небольшим (ЦУП'у нужно его обработать перед выдачей результата, чем больше данных — тем больше времени потребуется). Кроме того, не будет собрано лишних данных — например, не будет анализа нагрузки от регламентных работ, которые вы проводите ночью.

Кроме того, это снижает влияние сбора данных на работу системы. Дело в том, что ЦУП может собирать очень тяжелый ТЖ, способный заметно нагрузить железо (на 30% медленнее? подержи мое пиво). С этим лучше быть осторожным.

Для всего, что перечислено выше, достаточно аналитических показателей ЦУП'а: анализа запросов, ожиданий на блокировках, анализа взаимоблокировок 1С и MS SQL. Что до оперативных показателей — количества выполняемых запросов, суммарного времени их выполнения и так далее — то популярностью они не пользуются. Польза от них обычно не стоит времени на настройку, и ЦУП по большому счету никогда не проектировался для того, чтобы постоянно собирать их.

2019-11-24

Поиск методов с параметром

Задача: нужно найти в общих модулях конфигурации методы с определенным параметром (в этом примере — с параметром DecimalPlacesFor).

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

Первая часть скрипта (до пайпа) выполняет сам поиск, вторая — отрезает лишнее, чтобы на вывод уходили только названия модулей и найденных в них методов. Получится, например, так:

Скриншот консоли

Профит? Профит!

2019-11-18 bash готово

Ранее Ctrl + ↓