Черные дыры во вселенной

Эта статья является конспектом книги «Маленькая книга о черных дырах». Материал посвящен таким астрономическим объектам, как рентгеновские двойные и квазары.

В 1960-е и 1970-е годы в понимании черных дыр произошла настоящая революция. Современное теоретическое представление о черных дырах было в целом построено именно тогда благодаря математическим достижениям и глубоким прозрениям многих исследователей. В то же самое время астрономы все глубже и дальше вглядывались во Вселенную, используя все более чувствительные оптические и радиотелескопы. Были открыты два новых класса астрономических объектов: квазары и рентгеновские двойные системы. Именно там, как сейчас думают ученые, и находятся черные дыры.

Рентгеновская двойная

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

Но если не видно второго объекта, откуда ученые знают, что он там есть? Ответ на этот вопрос дает вызванное орбитальным движением доплеровское смещение длины волны фотонов, рождающихся в атмосфере наблюдаемой звезды. Атомы и молекулы поглощают и излучают фотоны только на определенных длинах волн. Так образуются спектральные линии; каждый атом или молекула отличаются уникальным набором таких линий, при помощи которого присутствие этих атомов можно распознать. Когда астрономы получают спектры звезд, они видят в этих спектрах множество линий поглощения и излучения, порожденных атомами и молекулами в атмосферах этих звезд. Если звезда входит в двойную систему, линии будут периодически демонстрировать попеременно то красное, то голубое смещение, причиной которого является орбитальное движение звезды относительно общего со второй звездой центра масс.

Итак, теперь мы знаем, что рентгеновские двойные – это действительно двойные, хоть и видно в них лишь одну звезду. Но откуда известно, что в некоторых случаях, таких, например, как Cyg X-1, компаньоном оптической звезды является черная дыра? Для тусклой звезды невидимый компаньон имеет слишком большую массу. Чтобы обосновать этот ответ, понадобится привлечь и связать друг с другом некоторые другие наблюдения, законы орбитального движения Кеплера и теорию звездной эволюции. Начнем с наблюдений. Из доплеровских смещений спектральных линий можно вывести не только сам факт двойственности звезды, но и подробные свойства ее орбиты. Период колебаний спектральных линий в точности воспроизводит орбитальный период двойной системы. Точные измерения доплеровских смещений в течение одного периода позволяют вычислить эллиптичность орбиты. Амплитуда сдвигов линий дает нижний предел максимальной скорости звезды. Соединяя все эти наблюдательные данные с кеплеровскими законами движения по орбите, можно оценить нижний предел суммарной массы обоих компаньонов двойной системы. И если получиться определить массу видимой звезды, то можно вычислить и массу ее невидимого компаньона. Звездная эволюция говорит, что если знать температуру поверхности и светимость звезды, то представления о звездной эволюции позволяют довольно точно оценить ее массу.

Жизнь звезды определяется противодействующими друг другу силами: направленной к ее центру силой тяготения и направленной вовне силой давления раскаленного газа. Это, вообще-то, верно и для холодных планет, в том числе и для нашей Земли, но в отличие от планет звезды слишком массивны для того, чтобы давление, создаваемое холодным веществом, уравновесило тяготение, по крайней мере на ранних стадиях их жизни.

Можно было бы возразить, что Земля не холодная; ее ядро раскалено почти до 6000 кельвинов. Это правда, но твердой Земле не нужно тепловое давление, чтобы удерживать ее массу от коллапса. Если бы мы могли представить себе, что Земля охладилась до температуры абсолютного нуля, оставшегося у нее электростатического давления и давления вырожденных электронов все равно было бы достаточно, чтобы уравновесить силу тяжести.

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

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

Так удалось установить, что в системе CygX-1 находится звезда с температурой поверхности 30 000 кельвинов и массой 20 солнечных масс. При такой высокой температуре эта звезда выглядит голубой. По размеру она по крайней мере вдесятеро больше Солнца и классифицируется как голубой сверхгигант. По этим данным и по наблюдаемым доплеровским сдвигам спектральных линий астрономы смоделировали орбиту двойной и вычислили из этой модели массу невидимого компаньона: она оказалась равной примерно 15 массам Солнца. Почему же это непременно должна быть черная дыра? Ответ снова дает теория строения звезд. За время своей эволюции массивная звезда проходит различные стадии выгорания своего ядерного топлива, и выделяемая при этом энергия обеспечивает давление, необходимое для уравновешивания силы тяжести. Термоядерные реакции идут до тех пор, пока в недрах звезды не образуется ядро из атомов группы железа. Такие ядра наиболее устойчивы; любые дальнейшие процессы ядерного синтеза или распада требуют поступления энергии. Для маломассивных звезд типа Солнца давления достаточно, чтобы поддерживать равновесие ядра, когда прекращается термоядерный синтез. Такие звезды заканчивают жизнь, превращаясь в белые карлики.

Как только масса железного ядра становится больше предела Чандрасекара, составляющего примерно 1,4 массы Солнца, давление становится недостаточным для поддержания равновесия ядра звезды, и оно коллапсирует – обрушивается к центру. Температура и плотность растут с огромной скоростью, и высокоэнергетические фотоны начинают разрушать атомы железа. В этой крайне плотной среде свободные электроны и протоны быстро объединяются, образуя нейтроны, – формируется нейтронный газ. Нейтроны создают давление достаточно большое, чтобы остановить коллапс ядра. Происходит это довольно быстро и бурно, в результате чего сквозь всю толщу звезды наружу распространяется мощная ударная волна. Именно так начинается то, что в конце концов наблюдается как взрыв сверхновой II типа. В ходе него внешние слои звезды выбрасываются в пространство, но некоторая часть вещества падает обратно на ядро, которое теперь можно назвать нейтронной звездой.

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

Вернемся к CygX-1. Масса компаньона составляет около 15 солнечных. Так как компаньон невидимый, его равновесие не может поддерживаться за счет тепловыделения, как у обычных звезд. Однако 15 солнечных масс – это намного выше предела TOV. И поэтому заключаем, что компаньон не может быть ни обычной звездой, ни белым карликом, ни нейтронной звездой, ни вообще каким-либо звездообразным объектом, состоящим из обычного (барионного) вещества. Возможно, это «темная звезда», образовавшаяся из темного вещества? Это вещество должно состоять из гипотетических частиц, которые очень слабо взаимодействуют (или вообще не взаимодействуют) с обычным веществом. Поэтому мы и не можем видеть ее. Если основываться на этом допущении, то можно пойти дальше и предположить, что темное вещество может конденсироваться и образовывать темные компактные объекты, один из которых и мог бы быть невидимым компаньоном в двойной системе CygX-1. Однако сама по себе гипотеза темного вещества не противоречит возможности существования черных дыр (некоторые даже предполагали, что черные дыры и есть форма темного вещества). Чтобы показать, что «темная звезда» теоретически возможна и действительно может претендовать на роль невидимого компонента в системе CygX-1, придется принимать еще больше допущений, чем для черной дыры.

Есть еще одно, и, может быть, самое убедительное подтверждение предположения, что невидимый компаньон системы CygX-1 – черная дыра. Это яркое рентгеновское излучение из окрестностей системы. Хотя видимые звезды тоже излучают некоторое количество рентгеновских фотонов, их недостаточно, чтобы объяснить наблюдаемую рентгеновскую светимость CygX-1. Если компаньон – черная дыра, то он расположен достаточно близко к звезде, чтобы захватывать большое количество газа и пыли, переносимых ее звездным ветром. Это вещество обращается вокруг черной дыры в виде толстого аморфного диска. Благодаря вязкости и магнитным эффектам, часть его постоянно мигрирует в направлении черной дыры, пока не достигает самой внутренней устойчивой круговой орбиты (ISCO). Это ближайшая к черной дыре орбита, на которой любая частица, движущаяся по геодезической, может обращаться вокруг черной дыры, не падая в нее. После достижения ISCO-орбиты газ быстро падает в черную дыру, которая, таким образом, постоянно подпитывается аккрецией вещества. Диск вокруг черной дыры называется аккреционным. В процессе продолжительной миграции на внутреннюю орбиту газ разогревается – источником энергии для этого служит гравитационная потенциальная энергия, высвобождающаяся по мере приближения газа к черной дыре.

Кинетическая энергия, которую молекулы газа приобретают за счет уменьшения их потенциальной энергии при переходе на более близкую к черной дыре орбиту, равномерно распределяется по всей массе газа благодаря столкновениям соседних молекул. Этот процесс в результате регистрируется как соответствующий рост температуры газа. Гравитационная потенциальная энергия представляет собой тот тип энергии, который мы ассоциируем с объектами, находящимися на разных высотах относительно Земли.

Чем ближе газ к черной дыре, тем больше он разогревается, а это означает, что излучаемые им фотоны имеют в среднем более высокие энергии. Самые высокоэнергетические фотоны, следовательно, приходят из окрестностей ISCO-орбиты. Размер этой орбиты связан с массой черной дыры, а это значит, что энергия фотонов, излученных аккреционным диском, несет информацию о размере черной дыры. Для черных дыр с массой в несколько солнечных масс, таких как та, что предположительно находится в системе CygX-1, эта энергия соответствует рентгеновскому диапазону. Более того, нерегулярный приток вещества в диск может обусловить изменения яркости рентгеновского потока, называемые квазипериодическими осцилляциями, и самая короткая шкала времени этих осцилляций соответствует орбитальному периоду частиц на ISCO-орбите. Для черных дыр звездной массы эта переменность имеет порядок величины в несколько сотен герц, что и наблюдается в системе CygX-1 и многих других рентгеновских двойных системах, где, предположительно, тоже есть черные дыры.

Как ни прост ответ на вопрос, почему компаньон в системе CygX-1 является черной дырой, этот ответ, как мы уже видели, опирается на длинную цепь теоретических аргументов. Некоторые из них довольно хорошо подтверждаются наблюдениями и экспериментами. Более консервативным утверждением было бы то, что наблюдаемые свойства рентгеновских двойных больших масс наподобие CygX-1 хорошо описываются моделью с черной дырой и что никто пока не предложил альтернативного объяснения свойств таких систем в рамках общепринятых и хорошо проверенных теорий. И до 14 сентября 2015 года это был, пожалуй, самый хороший аргумент в пользу физической реальности черных дыр, какой только можно было придумать. Но в тот день все изменилось: установка LIGO зарегистрировала слияние двух черных дыр. Наука никогда не может дать стопроцентно однозначного толкования явлений такого рода, но наблюдение гравитационных волн от этого слияния с очевидностью лишает силы все негравитационные теоретические аргументы, которые могли бы использоваться для объяснения случая CygX-1 и может основываться только на свойствах общей теории относительности в вакууме.

Квазары

Во Вселенной есть и другая популяция черных дыр, свидетельства существования которой постепенно накапливались с конца 1960-х. Это черные дыры, вначале ассоциировавшиеся с квазарами. Слово «квазар» появилось незадолго до этого. Оно происходит от термина «квазизвездный объект», что в то время просто значило: «мы не знаем, что это такое, – какая-то очень яркая штуковина, похожая на звезду». Сейчас считается, что квазар – это разновидность активного галактического ядра (AGN). Эта область заполнена веществом, которое испускает мощные потоки излучения, вливаясь по спирали в черную дыру. Считается, что черные дыры в центрах квазаров имеют массу от нескольких миллионов до нескольких миллиардов масс Солнца, поэтому их называют сверхмассивными. Таким образом, можно сказать, что квазары – явление гораздо более грандиозное, чем даже первое зарегистрированное приемником LIGO слияние черных дыр, в результате которого черные дыры с общей массой всего около 65 солнечных выплеснули в ходе своего столкновения энергию, эквивалентную всего-навсего трем солнечным массам. Правда, эта энергия выделилась всего за несколько десятых долей секунды. Вообразите, что могло бы случиться, если бы слились две сверхмассивных черных дыры!

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

Источник этой энергии – гравитационная потенциальная энергия вещества, обращающегося по орбите вокруг черной дыры. Это та самая потенциальная энергия, с которой мы каждый день сталкиваемся на Земле. Например, именно ее преобразуют в электрический ток гидроэлектростанции. Вода, падающая с большой высоты, отдает свою гравитационную потенциальную энергию, которую электростанции преобразуют в то самое электричество. В квазарах происходит нечто похожее, только энергия, которую они производят, в миллион триллионов триллионов раз больше той, которую вырабатывает крупная гидроэлектростанция. Когда говорим о черных дырах, количество потенциальной энергии, которая может превращаться в другие формы энергии при падении вещества с большого расстояния на ISCO-орбиту, удобно характеризовать как долю потенциальной энергии от общей энергии, соответствующей массе покоя (E = mc²) этого вещества. Эта величина зависит от вращения черной дыры, так как от него зависит положение ISCO-орбиты. Для невращающейся черной дыры она составляет 6 %, возрастая до 42 % для максимально быстро вращающейся. Это огромный процент! Ведь, например, потенциальная энергия воды, падающей с высоты 100 метров, составляет триллионную долю процента от ее общей энергии, соответствующей массе покоя.

Когда концепция черных дыр окрепла, и астрономы начали соглашаться с тем, что эти объекты могут объяснить природу квазаров, возник естественный вопрос: не могут ли сверхмассивные черные дыры находиться в центрах и тех галактик, которые не имеют активного ядра? Такие черные дыры можно было бы назвать «спящими» в том смысле, что вокруг них нет большого количества газа для формирования мощного аккреционного диска, и поэтому они не могут быть такими же яркими, как AGN. В близлежащих галактиках можно измерить доплеровские смещения линий в спектрах звезд, расположенных близ ядер этих галактик. Полученные из этих измерений данные о динамике орбитального движения звезд показывают, что в центральных областях практически всех крупных галактик действительно есть сверхмассивные черные дыры. Это, конечно, верно и для нашего Млечного Пути, центр которого находится достаточно близко к нам, чтобы в его окрестности можно было измерить движение звезд. Из этих измерений получается, что черная дыра в центре нашей Галактики имеет массу примерно в четыре миллиона масс Солнца.

В отличие от механизма происхождения черных дыр звездных масс, механизм образования сверхмассивных черных дыр пока неясен – на этот счет не существует общепринятой теории. Одна из возможностей заключается в том, что они зародились в результате коллапса первого поколения массивных звезд, образовавшихся спустя несколько сотен миллионов лет после Большого взрыва. Первоначальная масса этих черных дыр, должно быть, достигала от десяти до ста солнечных. Но после того как они оказывались в центрах новообразованных галактик, они должны были расти за счет аккреции газа и слияний с другими черными дырами. Трудность этой гипотезы вот в чем: как объяснить наблюдения некоторых очень далеких квазаров, свет от которых, регистрируемый сейчас, был излучен всего примерно через миллиард лет после Большого взрыва? Из этих наблюдений следует, что в эту эпоху сверхмассивные черные дыры уже существовали, и значит, гипотеза аккреции/слияния каким-то образом должна объяснить, как они успели вырасти до таких размеров за столь космологически короткое время: каких-то несколько сотен миллионов лет. Другая гипотеза предполагает, что зародыши современных сверхмассивных черных дыр появились во Вселенной в гораздо более раннюю эпоху. Этот гипотетический класс черных дыр называется первичными черными дырами. В настоящее время нет убедительных теоретических механизмов их образования.

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

ссылка на оригинал статьи https://habr.com/ru/post/540010/

Настраиваем Restic с systemd на Linux

Restic — хорошо известная программа для резервного копирования. Она достаточно проста, чтобы переноситься на любую ОС, и, вероятно, поэтому с ней не прилагается полноценный пример настройки на среднестатистической Linux-системе. Исправим это данным постом.

Поставим задачу следующим образом:

  1. Автоматический бэкап запускается ежедневно.
  2. Бэкап хранит только важные файлы и данные.
  3. Бэкап также включает в себя содержимое баз PostgreSQL, которое можно восстановить psql -f.

TL;DR поста

Пишем два юнита / таймера для systemd, запускаем restic под выделенным пользователем с CAP_DAC_READ_SEARCH, для PostgreSQL архивируем результат pg_dumpall.

Здесь предполагается, что бэкап производится на машине с Ubuntu Server 20.04 и выполняется на rest-server, работающий на 192.168.1.200. Тем не менее, конфигурация тривиально адаптируется к любому облачному провайдеру. Также предполагается, что репозиторий уже проинициализирован командой restic -r rest:http://192.168.1.200/your-repo/ init.

Бэкапим файлы/директории

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

# useradd -m -N -s /usr/sbin/nologin restic

Нам понадобится следующий сервис systemd с параметром и таймер к нему:

/etc/systemd/system/restic@.service:

[Unit] # юнит активируется с параметром после @, то есть в #   systemctl start restic@your-repo.service # %I означает "your-repo" Description=Restic backup on %I After=syslog.target After=network-online.target  [Service] Type=oneshot User=restic # читать список файлов к бэкапу будем из /etc/restic/your-repo.files ExecStart=/usr/local/bin/restic backup --files-from /etc/restic/%I.files # считаем репозиторий и пароль из /etc/restic/your-repo.env EnvironmentFile=/etc/restic/%I.env # выполняем restic с capability DAC_READ_SEARCH, дающей право # обходить права доступа ФС в Linux, это нужно для бэкапа # директорий, которые могут читать только другие пользователи # или суперпользователь AmbientCapabilities=CAP_DAC_READ_SEARCH  [Install] WantedBy=multi-user.target

/etc/systemd/system/restic@.timer:

[Unit] # таймер, будучи запущенным с параметром после @ # (restic@your-repo.timer), запустит restic@your-repo.service Description=Run Restic at 12:00 AM  [Timer] # запускаем restic ежедневно в 12 часов ночи OnCalendar=*-*-* 12:00:00  [Install] WantedBy=timers.target

Адрес репозитория и пароль от него подаются на вход через файл с переменными среды в /etc/restic/your-repo.env. systemd читает их при старте юнита с правами root, поэтому имеет смысл задать разрешения директории /etc/restic/ соответствующим образом (т.е. 700 и владельцем установить root):

RESTIC_PASSWORD=your_repo_password RESTIC_REPOSITORY=rest:http://192.168.1.200/your-repo/

Нам также понадобится список файлов/директорий к бэкапу в /etc/restic/your-repo.files:

/var/lib/docker /etc/postgresql /etc/restic ...

Бэкап PostgreSQL

Restic позволяет подачу данных для бэкапа через стандартный вход, так что мы можем скормить ему дамп, полученный pg_dumpall. Так как systemd запускает указанное директивой ExecStart вызовом execve(3), для использования перенаправления вывода и сжатия нам понадобится отдельный скрипт /usr/local/bin/pgdump.sh:

#!/usr/bin/env bash  set -euo pipefail  /usr/bin/sudo -u postgres pg_dumpall --clean \     | gzip --rsyncable \     | /usr/local/bin/restic backup --host $1 --stdin \         --stdin-filename postgres-$1.sql.gz

Сервис /etc/systemd/system/restic-pg@.service достаточно тривиален:

[Unit] Description=Restic PostgreSQL backup on %I After=syslog.target After=network-online.target After=postgresql.service Requires=postgresql.service  [Service] Type=oneshot User=restic ExecStart=/usr/local/bin/pgdump.sh %I EnvironmentFile=/etc/restic/%I.env  [Install] WantedBy=multi-user.target

Таймер /etc/systemd/system/restic-pg@.timer не отличается от виденного выше:

[Unit] Description=Run Restic on PostgreSQL at 12:00 AM  [Timer] OnCalendar=*-*-* 0:00:00  [Install] WantedBy=timers.target

Завершаем

Запустим таймеры и включим их автозагрузку:

# systemctl enable --now restic@your-repo.timer restic-pg@your-repo.timer

Проверим, работает ли построенная система:

# systemctl start restic@your-repo.service # systemctl start restic-pg@your-repo.service

Данный набор юнитов позволяет бэкапиться в неограниченное количество репозиториев, нужно лишь создать соответствующие /etc/restic/repo-name.{env,files}.

Ссылки

ссылка на оригинал статьи https://habr.com/ru/post/540096/

Вы всё ещё ловите исключения? Тогда мы к вам

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

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


Но с другой стороны, обрабатывать ошибки всегда лениво и напряжно. Поэтому существует много инструментов для облегчения этой задачи. Стандартный механизм обработки ошибок в Java — Exceptions. Я не буду сейчас расписывать скучные описания, как бы отвечая на скучные вопросы со многих собеседований. Скажу лишь, что Исключение — это на мой взгляд, неправильный перевод понятия Exception. Я считаю, что исключение, то есть исключительная ситуация — это про другого представителя летающих монстров, java.lang.Error.

А Exception — это не исключение, это часть правила. Это всегда один из возможных исходов. Я бы перевёл этот класс не иначе как Отклонение (Отступление, Отвод). В смысле отклонение от прямого курса. Потому как перехватив это отклонение, можно курс выправить и продолжить работу. А Исключение — это для безответственных разработчиков.

Так вот. Давайте теперь перехватывать эти отклонения. Как можно это сделать?

В современной разработке существует тенденция наследовать все Exception от непроверяемых исключений. Это позволяет не заботиться о написании кода обработки ошибок. Я считаю этот подход расхлябанным и безответственным. И сам всегда пропагандирую использование явно заданных и объявленных отклонений с жёсткой обязанностью их обработать, т.е. настаиваю на использовании только проверяемых исключений/отклонений в любом бизнес-коде.

Это вносит неудобства, да. Надо их везде ловить. Как упростить задачу? Обычно советуют тупо оборачивать исключение в java.lang.RuntimeException. Но такой подход чреват тяжёлыми последствиями, когда приложение выходит в релиз и на бой. Я как человек, имеющий ещё и плюсовый бэкграунд, прекрасно знаю, что некоторые ситуации невозможно предугадать даже очень внимательно вглядываясь в код. А потом искать их причины днями, неделями, иногда месяцами. Потому что кто-то в самом начале, в месте возникновения ошибки не объявил о возможности их возникновения.

Ну да ладно. Не будем о грустном. Лучше попробует сделать нашу жизнь проще, написав утилитку, которая с одной стороны, позволяет обрабатывать ошибки. А с другой стороны не привносит глобальных неудобств и не захламляет код бесконечными (часто вложенными друг в друга) блоками try-catch-finally.

Что предлагается?

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

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

  3. Во-вторых, надо бы упростить синтаксис обработки ошибок. Тут я поймал себя на мысли, что необходимость в этом возникает, так как мэйнстрим постепенно, медленно, но всё-таки верно потихоньку уползает от практик процедурного программирования. А блоки try-catch, по-моему, являются наследием именно этой парадигмы. И ООП , и тем более функциональщина и даже стримы Java-8 как-то плохо сочетаются с этими блоками, фигурными скобками.

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

Здесь я попробовал сразу около трёх подходов реализовать.

Первый — просто статичная обёртка над небезопасным кодом, которая напечатает в лог и в случае чего прокинет ошибку своего местного разлива. Это метод errorToWarn.

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

И затем я решил пойти ещё дальше и сделать описание ошибок в удобном формате, одновременно предлагая ленивую логику и флюент (как по-русски это?) интерфейс. Это вылилось в вызов, который уже возвращает своеобразный билдер, который затем можно настраивать по типу jmock или spring security api. Выглядеть это стало примерно как табличка состояний, примерно вот так:

К слову первый подход вылился во что-то наподобие

Надеюсь мои лирические рассуждения покажутся вам полезными. Возможно вам понравится использованный мной подход и вы захотите развить утилиту советом / личным вкладом.

ссылка на оригинал статьи https://habr.com/ru/post/540102/

Основы Bash-скриптинга для непрограммистов. Часть 2

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

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

Скрипты

Для выполнения нескольких команд одним вызовом удобно использовать скрипты. Скрипт – это текстовый файл, содержащий команды для shell. Это могут быть как внутренние команды shell, так и вызовы внешних исполняемых файлов.

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

Перейдем в домашнюю директорию командой cd ~ и создадим в ней с помощью редактора nano (nano script.sh)файл, содержащий 2 строки:

#!/bin/bash echo Hello!

Чтобы выйти из редактора nano после набора текста скрипта, нужно нажать Ctrl+X, далее на вопрос «Save modified buffer?» нажать Y, далее на запрос «File Name to Write:» нажать Enter. При желании можно использовать любой другой текстовый редактор.

Скрипт запускается командой ./<имя_файла>, т.е. ./ перед именем файла указывает на то, что нужно выполнить скрипт или исполняемый файл, находящийся в текущей директории. Если выполнить команду script.sh, то будет выдана ошибка, т.к. оболочка будет искать файл в директориях, указанных в переменной среды PATH, а также среди встроенных команд (таких, как, например, pwd):

test@osboxes:~$ script.sh script.sh: command not found

Ошибки не будет, если выполнять скрипт с указанием абсолютного пути, но данный подход является менее универсальным: /home/user/script.sh. Однако на данном этапе при попытке выполнить созданный файл будет выдана ошибка:

test@osboxes:~$ ./script.sh -bash: ./script.sh: Permission denied

Проверим права доступа к файлу:

test@osboxes:~$ ls -l script.sh -rw-rw-r-- 1 test test 22 Nov  9 05:27 script.sh

Из вывода команды ls видно, что отсутствуют права на выполнение. Рассмотрим подробнее на картинке:

Права доступа задаются тремя наборами: для пользователя, которому принадлежит файл; для группы, в которую входит пользователь; и для всех остальных. Здесь r, w и x означают соответственно доступ на чтение, запись и выполнение.

В нашем примере пользователь (test) имеет доступ на чтение и запись, группа также имеет доступ на чтение и запись, все остальные – только на чтение. Эти права выданы в соответствии с правами, заданными по умолчанию, которые можно проверить командой umask -S. Изменить права по умолчанию можно, добавив вызов команды umask с нужными параметрами в файл профиля пользователя (файл ~/.profile), либо для всех пользователей в общесистемный профиль (файл /etc/profile).

Для того, чтобы установить права, используется команда chmod <параметры> <имя_файла>. Например, чтобы выдать права на выполнение файла всем пользователям, нужно выполнить команду:

test@osboxes:~$ chmod a+x script.sh

Чтобы выдать права на чтение и выполнение пользователю и группе:

test@osboxes:~$ chmod ug+rx script.sh

Чтобы запретить доступ на запись (изменение содержимого) файла всем:

test@osboxes:~$ chmod a-w script.sh

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

test@osboxes:~$ chmod 754 script.sh

Будут выданы права -rwxr-xr--:

test@osboxes:~$ ls -la script.sh -rwxr-xr-- 1 test test 22 Nov  9 05:27 script.sh

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

Символ перед наборами прав доступа указывает на тип файла ( означает обычный файл, d – директория, l – ссылка, c – символьное устройство, b – блочное устройство, и т. д.). Соответствие числа, его двоичного представления и прав доступ можно представить в виде таблицы:

Число

Двоичный вид

Права доступа

0

000

Нет прав

1

001

Только выполнение (x)

2

010

Только запись (w)

3

011

Запись и выполнение (wx)

4

100

Только чтение (r)

5

101

Чтение и выполнение (rx)

6

110

Чтение и запись (rw)

7

111

Чтение, запись и выполнение (rwx)

Выдав права на выполнение, можно выполнить скрипт:

test@osboxes:~$ ./script.sh Hello!

Первая строка в скрипте содержит текст #!/bin/bash. Пара символов #! называется Шеба́нг (англ. shebang) и используется для указания интерпретатору, с помощью какой оболочки выполнять указанный скрипт. Это гарантирует корректность исполнения скрипта в нужной оболочке в случае, если у пользователя будет указана другая.

Также в скриптах можно встретить строку #!/bin/sh. Но, как правило, /bin/sh является ссылкой на конкретный shell, и в нашем случае /bin/sh ссылается на /bin/dash, поэтому лучше явно указывать необходимый интерпретатор. Вторая строка содержит команду echo Hello!, результат работы которой мы видим в приведенном выводе.

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

Для того, чтобы обеспечить некоторую универсальность, существует возможность при вызове передавать скрипту параметры. В этом случае вызов скрипта будет выглядеть так: <имя_скрипта> <параметр1> <параметр2> …, например ./script1.sh Moscow Russia.

Для того, чтобы получить значение первого параметра, необходимо в скрипте указать $1, второго — $2, и т.д. Существует также ряд других переменных, значения которых можно использовать в скрипте:
$0 – имя скрипта
$# – количество переданных параметров
$$ – PID(идентификатор) процесса, выполняющего скрипт
$? – код завершения предыдущей команды

Создадим файл script1.sh следующего содержания:

#!/bin/bash echo Hello, $USER! printf "Specified City is: %s, Country is: %s\n" $1 $2

Выдадим права на выполнение и выполним скрипт с параметрами:

test@osboxes:~$ chmod u+x script1.sh test@osboxes:~$ ./script1.sh Moscow Russia Hello, test! Specified City is: Moscow, Country is: Russia

Мы передали 2 параметра, указывающие город и страну, и использовали их в скрипте, чтобы сформировать строку, выводимую командой printf. Также для вывода в строке Hello использовали имя пользователя из переменной USER.

Для того, чтобы передать значения параметров, состоящие из нескольких слов (содержащие пробелы), нужно заключить их в кавычки:

test@osboxes:~$ ./script1.sh "San Francisco" "United States" Hello, test! Specified City is: San Francisco, Country is: United States

При этом нужно доработать скрипт, чтобы в команду printf параметры также передавались в кавычках:

printf "Specified City is: %s, Country is: %s\n" "$1" "$2"

Из приведенных примеров видно, что при обращении к переменной для получения её значения используется символ $. Для того, чтобы сохранить значение переменной просто указывается её имя:

COUNTRY=RUSSIA echo $COUNTRY

Операторы условного выполнения, выбора и циклы

Так же, как и в языках программирования, в bash существуют операторы условного выполнения – выполнение определенных действий при определенных условиях. Кроме того, существует возможность повторного выполнения определенного блока команд пока выполняется заданное условие – операторы цикла. Рассмотрим каждый из них подробнее.

Оператор условного выполнения представляет собой конструкцию вида:

if [ <условие> ] then   <команда1> else   <команда2> fi

Создадим скрипт, проверяющий длину введенной строки (например, для проверки длины пароля), которая должна быть не меньше (т.е. больше) 8 символов:

#!/bin/bash echo Hello, $USER! echo -n "Enter string: " read str if [ ${#str} -lt 8 ] then   echo String is too short else   echo String is ok fi

Выполним 2 теста, с длиной строки 5 и 8 символов:

test@osboxes:~$ ./script2.sh Hello, test! Enter string: abcde String is too short test@osboxes:~$ ./script2.sh Hello, test! Enter string: abcdefgh String is ok

Командой read str мы получаем значение, введенное пользователем и сохраняем его в переменную str. С помощью выражения ${#str} мы получаем длину строки в переменной str и сравниваем её с 8. Если длина строки меньше, чем 8 (-lt 8), то выдаем сообщение «String is too short», иначе – «String is ok».

Условия можно комбинировать, например, чтобы указать, чтоб длина должна быть не меньше восьми 8 и не больше 16 символов, для условия некорректных строк нужно использовать выражение [ ${#str} -lt 8 ] || [ ${#str} -gt 16 ]. Здесь || означает логическое «ИЛИ», а для логического «И» в bash используется &&.

Условия также могут быть вложенными:

#!/bin/bash echo Hello, $USER! echo -n "Enter string: " read str if [ ${#str} -lt 8 ] then   echo String is too short else   if [ ${#str} -gt 16 ]   then     echo String is too long   else     echo String is ok   fi fi

Здесь мы сначала проверяем, что строка меньше 8 символов, отсекая минимальные значения, и выводим «String is too short», если условие выполняется. Если условие не выполняется(строка не меньше 8 символов) — идем дальше(первый else) и проверяем, что строка больше 16 символов. Если условие выполняется — выводим «String is too long», если не выполняется(второй else) — выводим «String is ok».

Результат выполнения тестов:

test@osboxes:~$ ./script2.sh Hello, test! Enter string: abcdef String is too short test@osboxes:~$ ./script2.sh Hello, test! Enter string: abcdefghijklmnopqrstuv String is too long test@osboxes:~$ ./script2.sh Hello, test! Enter string: abcdefghijkl String is ok

Оператор выбора выглядит следующим образом:

case "$переменная" in  "$значение1" )  <команда1>;;  "$значение2" )  <команда2>;; esac

Создадим новый скрипт, который будет выводить количество спутников для указанной планеты:

#!/bin/bash echo -n "Enter the name of planet: " read PLANET echo -n "The $PLANET has " case $PLANET in   Mercury | Venus ) echo -n "no";;   Earth ) echo -n "one";;   Mars ) echo -n "two";;   Jupiter ) echo -n "79";;   *) echo -n "an unknown number of";; esac echo " satellite(s)."

Тест:

test@osboxes:~$ ./script3.sh Enter the name of planet: Mercury The Mercury has no satellite(s). test@osboxes:~$ ./script3.sh Enter the name of planet: Venus The Venus has no satellite(s). test@osboxes:~$ ./script3.sh Enter the name of planet: Earth The Earth has one satellite(s). test@osboxes:~$ ./script3.sh Enter the name of planet: Mars The Mars has two satellite(s). test@osboxes:~$ ./script3.sh Enter the name of planet: Jupiter The Jupiter has 79 satellite(s). test@osboxes:~$ ./script3.sh Enter the name of planet: Alpha555 The Alpha555 has an unknown number of satellite(s).

Здесь в зависимости от введенного названия планеты скрипт выводит количество её спутников.
В case мы использовали выражение Mercury | Venus, где | означает логическое «ИЛИ» (в отличие от if, где используется ||), чтобы выводить «no» для Меркурия и Венеры, не имеющих спутников. В case также можно указывать диапазоны с помощью []. Например, скрипт для проверки принадлежности диапазону введенного символа будет выглядеть так:

#!/bin/bash  echo -n "Enter key: " read -n 1 key echo case "$key" in   [a-z]   ) echo "Lowercase";;   [A-Z]   ) echo "Uppercase";;   [0-9]   ) echo "Digit";;   *       ) echo "Something else";; esac

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

test@osboxes:~$ ./a.sh Enter key: t Lowercase test@osboxes:~$ ./a.sh Enter key: P Uppercase test@osboxes:~$ ./a.sh Enter key: 5 Digit test@osboxes:~$ ./a.sh Enter key: @ Something else

Цикл может задаваться тремя разными способами:

Выполняется в интервале указанных значений (либо указанного множества):

for [ <условие> ] do <команды> done

Выполняется, пока соблюдается условие:

while [ <условие> ] do <команды> done

Выполняется, пока не перестанет соблюдаться условие:

until [ <условие> ] do <команды> done

Добавим в скрипт с планетами цикл с условием while и будем выходить из скрипта, если вместо имени планеты будет введено EXIT

#!/bin/bash PLANET="-" while [ $PLANET != "EXIT" ] do   echo -n "Enter the name of planet: "   read PLANET   if [ $PLANET != "EXIT" ]   then.     echo -n "The $PLANET has "     case $PLANET in       Mercury | Venus ) echo -n "no";;       Earth ) echo -n "one";;       Mars ) echo -n "two";;       Jupiter ) echo -n "79";;       *) echo -n "an unknown number of";;     esac   echo " satellite(s)."   fi done

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

test@osboxes:~$ ./script4.sh Enter the name of planet: Earth The Earth has one satellite(s). Enter the name of planet: Jupiter The Jupiter has 79 satellite(s). Enter the name of planet: Planet123 The Planet123 has an unknown number of satellite(s). Enter the name of planet: EXIT

Нужно отметить, что условие while [ $PLANET != "EXIT" ] можно заменить на until [ $PLANET == "EXIT" ]. == означает «равно», != означает «не равно».

Приведем пример циклов с указанием интервалов и множеств:

#!/bin/bash  rm *.dat  echo -n "File count: " read count  for (( i=1; i<=$count; i++ )) do   head -c ${i}M </dev/urandom >myfile${i}mb.dat done ls -l *.dat  echo -n "Delete file greater than (mb): " read maxsize  for f in *.dat do   size=$(( $(stat -c %s $f) /1024/1024))   if [ $size -gt $maxsize ]   then.     rm $f     echo Deleted file $f   fi done ls -l *.dat  read

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

В первом цикле (for (( i=1; i<=$count; i++ ))) мы генерируем несколько файлов, количество которых задано в переменной count, которую введет пользователь. В команду head передаем количество мегабайт, считываемых из устройства /dev/random, чтение из которого позволяет получать случайные байты.

Символ < указывает перенаправление входного потока (/dev/urandom) для команды head.

Символ > указывает перенаправление выходного потока (вывод команды head -c ${i}M ) в файл, имя которого мы генерируем на основе постоянной строки с добавлением в неё значения переменной цикла (myfile${i}mb.dat).

Далее мы запрашиваем размер, файлы больше которого необходимо удалить.

Во втором цикле (for f in *.dat) мы перебираем все файлы .dat в текущей директории и сравниваем размер каждого файла со значением, введенным пользователем. В случае, если размер файла больше, мы удаляем этот файл.

В конце скрипта выводим список файлов .dat, чтобы отобразить список оставшихся файлов (ls -l *.dat). Результаты теста:

test@osboxes:~$ ./script5.sh File count: 10 -rw-rw-r-- 1 test test 10485760 Nov  9 08:48 myfile10mb.dat -rw-rw-r-- 1 test test  1048576 Nov  9 08:48 myfile1mb.dat -rw-rw-r-- 1 test test  2097152 Nov  9 08:48 myfile2mb.dat -rw-rw-r-- 1 test test  3145728 Nov  9 08:48 myfile3mb.dat -rw-rw-r-- 1 test test  4194304 Nov  9 08:48 myfile4mb.dat -rw-rw-r-- 1 test test  5242880 Nov  9 08:48 myfile5mb.dat -rw-rw-r-- 1 test test  6291456 Nov  9 08:48 myfile6mb.dat -rw-rw-r-- 1 test test  7340032 Nov  9 08:48 myfile7mb.dat -rw-rw-r-- 1 test test  8388608 Nov  9 08:48 myfile8mb.dat -rw-rw-r-- 1 test test  9437184 Nov  9 08:48 myfile9mb.dat Delete file greater than (mb): 5 Deleted file myfile10mb.dat Deleted file myfile6mb.dat Deleted file myfile7mb.dat Deleted file myfile8mb.dat Deleted file myfile9mb.dat -rw-rw-r-- 1 test test 1048576 Nov  9 08:48 myfile1mb.dat -rw-rw-r-- 1 test test 2097152 Nov  9 08:48 myfile2mb.dat -rw-rw-r-- 1 test test 3145728 Nov  9 08:48 myfile3mb.dat -rw-rw-r-- 1 test test 4194304 Nov  9 08:48 myfile4mb.dat -rw-rw-r-- 1 test test 5242880 Nov  9 08:48 myfile5mb.dat

Мы создали 10 файлов (myfile1mb.dat .. myfile10mb.dat) размером от 1 до 10 мегабайт и далее удалили все файлы .dat размером больше 5 мегабайт. При этом для каждого удаляемого файла вывели сообщение о его удалении (Deleted file myfile10mb.dat). В конце вывели список оставшихся файлов (myfile1mb.dat .. myfile5mb.dat).

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

ссылка на оригинал статьи https://habr.com/ru/post/540076/

Цифровая трансформация завода (ч. 3): волшебные интерфейсы и оживление железа

Часть 1: CRM для ERP

Часть 2: Роботизация бизнес-процессов

Часть 3: Волшебные интерфейсы и оживление железа (в этой публикации)

Часть 4: Личные кабинеты, чат-боты и dream team

Влияние рабочего места диспетчера на пропускную способность отгрузки на заводе

Цифровизация предприятия — это не только процесс внедрение новых систем и сервисов. Этому предшествуют поиски узких мест в рабочих процессах и на конкретных рабочих местах пользователей.

Рекомендация: Не айтишные книги, которые полезно прочитать айтишнику
  1. Принципы. Жизнь и работа. Рэй Далио

  2. Цель. Процесс непрерывного совершенствования. Элияху Голдратт

  3. Гемба Кайдзен. Путь к снижению затрат и повышению качества. Масааки Имаи

Какие идеи обычно возникают, когда нужно увеличить пропускную способность отгрузки на заводе:

  • Увеличить количество точек для одновременной отгрузки на заводе.

  • Увеличить количество КПП для одновременного въезда/выезда на завод.

На первый взгляд ответы правильные и логичные. Остается только найти пару 10 или 100 млн. руб. на инвестиционный проект и реализовать его.

Узкое горлышко найдено, дело за малым
Узкое горлышко найдено, дело за малым
Личный опыт: Не верьте программистам и консультантам

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

  • У пользователя действительно все хорошо и прекрасно.

  • Пользователь не знает к кому обращаться со своими проблемами.

  • Пользователь много раз обращался, никто не решил проблему, потерял надежду и перестал обращаться.

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

  • У пользователя нет возможности обратиться из-за отсутствия времени, так как оно полностью занято оперативной работой.

Еще одна причина:

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

Общий счет 5:1 в пользу того, чтобы не верить программистам и консультантам, что у пользователей нет вопросов и проблем.

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

Выявленные на месте явные проблемы (без погружения в детали):

  • 3 рукописных журнала для оперативной работы (при наличии рабочего места в ERP).

  • 2 монитора, чтобы вывести нужную информацию (изображение с 2-х видеокамер, данные с 2-х промышленных весов, программы для вывода текста на Led-табло, монитор для работы в ERP).

  • Настольный калькулятор (для вычисления max. веса к погрузке по каждой машине).

  • Ручки и фломастеры (для заполнения настольных журналов).

  • Поток жалоб от диспетчера на ошибки в рабочем месте ERP и постоянные проблемы со вторым монитором, куда выводятся данные с промышленных весов.

Лайфхак #1: Фотографируйте рабочие места пользователей

Так выглядело рабочее место диспетчера, когда я приехал и это было нормой с 2016 года.

Часть рабочего места диспетчера, вид сверху
Часть рабочего места диспетчера, вид сверху
Монитор 1 - данные с 2-х камер, данные с 2-х весов, программа для led-табло
Монитор 1 — данные с 2-х камер, данные с 2-х весов, программа для led-табло
Монитор 2 - интерфейс рабочего места в ERP, беспощадный и жестокий
Монитор 2 — интерфейс рабочего места в ERP, беспощадный и жестокий
Настольный калькулятор и журналы на столе диспетчера
Настольный калькулятор и журналы на столе диспетчера
Журнал прибывших машин на погрузку с отметками плановых точек погрузки на заводе
Журнал прибывших машин на погрузку с отметками плановых точек погрузки на заводе
Журнал с очередью машин (кто и во сколько приехал, когда и кого грузить, кто отгружен)
Журнал с очередью машин (кто и во сколько приехал, когда и кого грузить, кто отгружен)
Журнал выданных номерных пломб (учет по сериям) по сменам диспетчеров
Журнал выданных номерных пломб (учет по сериям) по сменам диспетчеров

Лайфхак #2: Наблюдайте, слушайте диалоги, задавайте вопросы

Это помогло за одну 12-часовую смену понять суть работы диспетчера:

  • Регистрация прибытия водителей на погрузку.

  • Планирование времени отгрузки в журнале (формирование очереди).

  • Вызов водителей на погрузку по журналу (по очереди из числа прибывших)

  • Выдача номерных номерных пломб и магнитных карт, их регистрация в ERP (для погрузки).

  • Ручная отправка задания на промышленные весы (для взвешивания машины до погрузки).

  • Ручное вычисление max. веса к погрузке (по каждой машине с учетом грузоподъемности и веса пустой машины).

  • Ручная отправка на промышленные весы задания на погрузку (max. вес к погрузке).

  • Печать отгрузочных накладных (после окончания погрузки).

Простые замеры времени операций показали, что на заводе высокая скорость погрузки (одна машина грузится ~ 10 минут), но есть простои до 3-х минут между погрузкой машин , потому что диспетчер физически не успевает «обслужить» весь трафик.

Диалоги диспетчера с водителями обнажили бюрократию на рабочем месте и предвзятое отношение к водителям:

  • У одних водителей ничего не спрашиваем и не проверяем, у других — проверяем каждую букву в ФИО и гос. номерах.

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

  • Одним водителям всё подробно рассказываем, других — игнорируем и не отвечаем на элементарные вопросы.

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

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

Нарисовались следующие задачи, которые были решены
  1. Ускорить регистрацию прибывших на погрузку водителей.

  2. Ускорить выдачу диспетчером номерных пломб и магнитных карт для водителей.

  3. Развести машины по времени прибытия на завод.

  4. Упорядочить очередь прибывших на погрузку машин.

  5. Ускорить взвешивание машин до и после погрузки.

  6. Привести в порядок интерфейс рабочего место диспетчера в ERP.

  7. Убрать у диспетчера второй монитор, журналы, калькулятор и фломастеры.

На решение задач и автоматизации, которые дали наибольший эффект ~ 2 месяца с учетом покупки и настройки оборудования, закупки партий номерных пломб со штрихкодами, написания ТЗ и других связанных процессов.

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

На гифке сразу виден результат преобразований (автоматическая очередь машин в новом рабочем месте диспетчера в ERP).

Волшебное рабочее место диспетчера в ERP - маленький мир больших машин
Волшебное рабочее место диспетчера в ERP — маленький мир больших машин
Время «обслуживания» диспетчером одной машины сократилось в 10 раз
  • Автоматическая очередь машин через 1 КПП для 3-х точек отгрузки на заводе.

  • Автоматическое управление из ERP взвешиванием на промышленных весах.

  • Вся информация выведена на 1 экран 1 монитора пользователя.

  • Выдача номерных пломб и магнитной карты водителю с помощью сканера штрихкодов за 5 секунд.

  • Печать комплекта отгрузочных накладных диспетчером за 5 секунд.

  • Рабочее место диспетчера без журналов, калькулятора и фломастеров.

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

Так выглядят номерные пломбы для выдачи водителю:

  • Приходят в коробках по 10 тыс. шт. и соединены друг с другом пластиковыми «ножками» (особенность изготовления).

  • Изначально был только номер, затем мы заказали с нанесением штрихкодов.

  • Штрихкод просто кодирует номер самой пломбы.

Пластиковые номерные пломбы со штрихкодами
Пластиковые номерные пломбы со штрихкодами

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

Примерка штрихкода для наклеивания на магнитную карту
Примерка штрихкода для наклеивания на магнитную карту

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

  • Чтобы сканер различал штрихкоды, мы кодируем первый знак: 1 — штрихкод номерной пломбы, 2 — штрихкод магнитной карты.

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

ГЛАВНЫЙ РЕЗУЛЬТАТ: пропускная способность отгрузки продукции автотранспортом на заводе увеличена в 2 раза без капитальных затрат.

Подробнее, о том, что для этого было сделано, читайте далее…

Электронная очередь для грузового автотранспорта

Фактически очередь начинает формироваться на этапе приема заказов:

> с нашей доставкой, клиент указывает только дату и время выгрузки по адресу доставки.

> на самовывозе, клиент указывает только дату и время погрузки на заводе.

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

Конкурентное преимущество: мы поддерживаем такой высокий уровень сервиса, чтобы клиенты могли получить продукцию завода: «день в день» — для регионов до 300 км, на следующий день — для регионов до 600 км, и через день — для регионов свыше 600 км.

Существующие ограничения на заводе при отгрузке в автотранспорт
  1. Разная продукция завода отгружается в разные часы в течение суток.

  2. Скорость отгрузки продукции на заводе не более 6 машин в час на 1 точку погрузки.

  3. Один вид продукции отгружается с 2-х точек погрузки, второй — с одной точки.

  4. Одновременно на заводе могут находиться не более 8 грузовых машин на всех точках погрузки.

  5. Все машины заезжают на завод и выезжают с завода через 1 КПП и одного диспетчера в смену.

Пример настроек в ERP по действующим ограничениям
Настройки пропускной способности отгрузки в ERP
Настройки пропускной способности отгрузки в ERP
Настройки вариантов подбора свободного времени отгрузки продукции в ERP
Настройки вариантов подбора свободного времени отгрузки продукции в ERP

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

Для некоторых видов продукции учитывается суточный лимит объема отгрузки вместо ограничения по количеству машин в час.

Автоматический подбор свободного часа погрузки на заводе (по заказу в ERP) для доставки клиенту ко времени
Автоматический подбор свободного часа погрузки на заводе (по заказу в ERP) для доставки клиенту ко времени
В какой момент формируются 3 разные очереди в ERP
  1. Заказ клиента принят 21.01.2021 в 11:14.

  2. Расстояние от завода до пункта разгрузки у клиента 630 км.

  3. Чтобы доставить заказ клиенту 22.01.2021 к 8:00, машина должна приехать на завод для погрузки 21.01.2021 не позднее 15:00 — это плановая очередь погрузки.

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

  5. По плановому времени погрузки по заказу и фактическому времени прибытия машин на завод строится реальная очередь на отгрузку.

Способы регистрация прибытия водителей на заводе:

  • через диспетчера

  • через уличный терминал

  • через чат-бот Telegram (подробнее в четвертой части)

  • через распознавание гос. номера машины (в планах на этот год)

Пример регистрации водителей через диспетчера в ERP
Диспетчер отмечает прибытие водителей правой кнопкой мыши в своем рабочем месте в ERP
Диспетчер отмечает прибытие водителей правой кнопкой мыши в своем рабочем месте в ERP
  1. Машины, которые фактически находятся на погрузке на заводе.

  2. Очередь машин на погрузку по статусам:

    — кто еще не прибыл на завод (НЕ ПРИБЫЛ).

    — кто прибыл и ожидает своей очереди (В ОЧЕРЕДИ).

    — кто прибыл и автоматически приглашен к погрузке (К ПОГРУЗКЕ).

  3. Динамические данные двух промышленных весов (показ только у диспетчера).

  4. Изображение с двух камер на точках погрузки на заводе.

Пример регистрации водителей через уличный терминал на заводе
  • Сенсорный антивандальный монитор 24″ российского производства (широкоформатный 16:9, TFT TN, 1920х1080, углы обзора 160/160), установлен на КПП завода.

  • Монитор без собственного ПО для подключения к любому ПК, с особыми характеристиками яркости (1000 кд/м2) и температурного режима (-30/+30), в защищенном корпусе (сталь 2 мм) c закаленным стеклом (4 мм) и весом ~ 20 кг.

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

Начальный экран - крупные шрифты, большие кнопки, не промахнешься
Начальный экран — крупные шрифты, большие кнопки, не промахнешься
Шаг 1: Быстрый поиск по водительскому удостоверению - водитель не найден
Шаг 1: Быстрый поиск по водительскому удостоверению — водитель не найден
Шаг 2: Быстрый поиск по цифрам гос. номера автомобиля
Шаг 2: Быстрый поиск по цифрам гос. номера автомобиля
Шаг 3: Найденные по гос. номеру автомобили - выбор и подтверждение
Шаг 3: Найденные по гос. номеру автомобили — выбор и подтверждение
Шаг 4: Проверка данных и регистрация прибытия на погрузку
Шаг 4: Проверка данных и регистрация прибытия на погрузку

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

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

Пример регистрации водителей через чат-бот Telegram
Водитель отмечает прибытие на завод для погрузки в чат-боте Telegram
Водитель отмечает прибытие на завод для погрузки в чат-боте Telegram
  1. Команда прибытия на погрузку в чат-боте Telegram.

  2. Уведомление водителя с подтверждением времени прибытия.

Чат-бот для водителей в Telegram интегрирован с ERP в режиме онлайн и работает автоматически по заданным сценариям (подробнее в четвертой части).

Как происходит автоматический вызов водителя на погрузку из очереди:

Способ регистрации прибытия

Канал вызова на погрузку

через диспетчера

уличное LED-табло и SMS

через уличный терминал

уличное LED-табло и SMS

через чат-бот Telegram

уличное LED-табло и чат-бот Telegram

через распознавание гос.. номера (в плане)

уличное LED-табло и SMS (в плане)

Пример приглашения водителей на погрузку по SMS
Автоматическое приглашение водителей на погрузку по SMS
Автоматическое приглашение водителей на погрузку по SMS

Пример приглашения водителя на погрузку в чат-боте Telegram
1 - водитель отметил прибытие на завод, 2 - чат-бот автоматически пригласил на погрузку
1 — водитель отметил прибытие на завод, 2 — чат-бот автоматически пригласил на погрузку

На скриншоте ниже видно историю взаимодействия водителей с чат-ботом Telegram в интерфейсе ERP (подробнее в четвертой части).

Автоматическое приглашение водителей на погрузку в чат-боте Telegram
Автоматическое приглашение водителей на погрузку в чат-боте Telegram

Пример приглашения водителей через уличное Led-табло
Автоматическое приглашение водителей на LED-табло по гос. номеру автомобиля
Автоматическое приглашение водителей на LED-табло по гос. номеру автомобиля
  • Размер каждой LED-панели примерно 1,5 х 2 метра.

  • LED-панели развернуты на 2 стороны стоянки грузовых автомобилей перед заводом.

И если SMS или уведомление в чат-бот Telegram отправляется однократно, то приглашение на уличное LED-табло может выводиться несколько раз в соответствии с тем, как меняется автоматическая очередь в ERP:

  • Первый вызов и ожидание водителя в течение 5 минут.

  • Второй и последующие вызовы через каждые 5 минут, после вызова на погрузку следующего по очереди водителя и окончания погрузки очередной машины на заводе.

Таким образом, очередь на LED-табло постоянно автоматически обновляется и к погрузке вызываются разные водители из числа прибывших на завод.

Оживление LED-табло и автоматическое управление из ERP

Уличные LED-панели были куплены еще до начала работ по комплексной автоматизации рабочего места диспетчера, взамен старого (с которым раньше работали диспетчеры через программу для ручного вывода строк).

Фото от российского производителя LED-панелей (1,5 х 2 м), готовых к отправке на завод
Фото от российского производителя LED-панелей (1,5 х 2 м), готовых к отправке на завод

Вместе с LED-панелями производитель предоставил программу для вывода строк на табло.

Окно программы для вывода текстовых строк на LED-табло
Окно программы для вывода текстовых строк на LED-табло

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

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

Пример 3-х страниц с описанием протокола
Страница 2 описания протокола
Страница 2 описания протокола
Страница 5 описания протокола
Страница 5 описания протокола
Страница 8 описания протокола
Страница 8 описания протокола

С программистом 1С мы посмотрели протокол и не поняли, как именно управлять выводом очереди машин на табло из ERP.

По нашей просьбе, изготовитель LED-панелей договорился с производителем компонент электроники, из которых оно состоит, чтобы они написали пример кода для программного вывода информации на табло. Пример был написан на языке Pascal, который программист с большим трудом перевел на язык 1С.

Пример кода на языке Pascal (Delphi 10) по использованию протокола
unit ConnTypes;  interface  const      RecBuffSizeByte=1024;  type  TLevel2Pack=packed record   SrcAddr:word; //source address   DstAddr:word; //receiver address   PId:byte;     //Packet id   Cmd:byte;   // Command code   Flags:byte;  //options   Status:byte; //command status   DataLen:word; //length of data   Data:array[0..RecBuffSizeByte-1] of byte;  //data   end;  PLevel2Pack=^TLevel2Pack;  TLevel2Head=packed record   SrcAddr:word; //source address   DstAddr:word; //receiver address   PId:byte;     //Packet id   Cmd:byte;   // Command code   Flags:byte;  //options   Status:byte; //command status   DataLen:word; //length of data   end; PLevel2Head=^TLevel2Head;  TFullPacket=packed record   bSTX:byte;   LenLo:byte;   LenHi:byte;   Data:array[0..RecBuffSizeByte*2-1+32] of byte;   end;    PFullPacket=^TFullPacket;  function MakeFullPacket(Src:PLevel2Pack; Dst:Pointer):integer; function EncodeWord(v:word):word;  implementation  uses CRCUnit;  function CS2word(cslo, cshi:byte):word; var b:PByte; begin Result:=0; b:=@Result; b^:=cslo or $80; inc(b); b^:=$80 or ((cslo shr 7) and $01) or ((cshi and $3F) shl 1); end;  function EncodeWord(v:word):word; begin Result:=((v and $3F80) shl 1) or (v and $7F) or $8080; end;  function DecodeWord(v:word):word; begin Result:=((v and $7F00) shr 1) or (v and $7F); end;  function EncodeDataForComm(Src, Dst:Pointer; SrcSize:integer):integer;  var PS, PD:PByte;      i:integer;      b:byte;   begin   PS:=Src;   PD:=Dst;   Result:=0;   for i:=1 to SrcSize do     begin     b:=PS^ xor $80;     if (b<$20) or (b=$7F)        then begin             PD^:=$7F;             inc(PD);             PD^:=b or $80;             inc(Result);             end        else PD^:=b;     inc(PS);     inc(PD);     inc(Result);     end;   end;  function MakeFullPacket(Src:PLevel2Pack; Dst:Pointer):integer; var cs:word;     PB:PByte;     F:PFullPacket;     PackLen:word;     PackSize:integer;   begin   PB:=Dst;   F:=Dst;   cs:=0;   PackLen:=word(Src^.DataLen+sizeof(TLevel2Head));   CountCSNewW(Src, PackLen, cs);   F^.bSTX:=$02;   PWord(@F^.LenLo)^:=EncodeWord(PackLen);   inc(PB, 3);// add bSTX, LenLo, LenHi   PackSize:=EncodeDataForComm(Src, PB, PackLen);   inc(PB, PackSize);   PWord(PB)^:=EncodeWord(cs);   inc(PB, 2); // add CsLo, CsHi   PB^:=$03;   Result:=PackSize+6;   end; end.

Таким образом, нам удалось реализовать полностью автоматическое управление выводом очереди на LED-табло из ERP.

Мы также реализовали автоматическое управление взвешиванием машин из ERP до и после погрузки на 2-х промышленных весах на заводе. Напишите в комментариях, если вам интересно узнать об этом подробнее.

Спасибо, что дочитали до конца!

ссылка на оригинал статьи https://habr.com/ru/post/539240/