Задать вопрос
  • Установка php в Docker?

    Vamp
    @Vamp
    RUN DEBIAN_FRONTEND=noninteractive apt-get install -y php php-pgsql php-mbstring php-xml php-apcu composer php-mongodb php-curl php-memcached
    Ответ написан
    Комментировать
  • Почему не работает List-Unsubscribe?

    Vamp
    @Vamp
    Спамеры пользуются этой фичей как подтверждением доставки. Раз отписался, значит точно живой и начнут спамить в три раза сильнее.

    Раз кнопка не появилась, значит ваша репутация рассыльщика недостаточно хороша или вообще отсутствует. Соблюдайте требования почтовых сервисов и кнопка появится рано или поздно.
    Ответ написан
    Комментировать
  • Как организовать monorepo с привязкой к версии maven?

    Vamp
    @Vamp
    Вы можете собрать весь проект целиком, тогда в maven reactor будут добавлены сразу все модули и dependency resolver сможет разобраться в зависимостях от соседних модулей. Но если собирать один конкретный модуль, то мавен уже не разберётся и полезет во внешние репозитории. В таком случае необходимо передать дополнительный ключ -am (--also-make):

    mvn -am -pl модуль package
    Ответ написан
    Комментировать
  • Как данные перемещаются в сети интернет, всегда конвертируются в кадры Ethernet или остаются в пакетах IP?

    Vamp
    @Vamp
    1. Пакеты не конвертируются друг в друга, а вкладываются. То есть в типичном пакете имеются сразу три заголовка - Ethernet, IP и TCP. И когда маршрутизатор решает куда отправить пакет дальше, смотрит только на заголовок IP. У маршрутизатора существует таблица маршрутизации, которая указывает какие IP адреса на какой интерфейс отправлять. Непосредственно перед отправкой маршрутизатор перезапишет ethernet заголовок и вставит в него свой MAC в поле "source MAC address", а MAC выбранного следующего получателя в поле "destination mac address".

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

    2. Упаковка в Ethernet может быть пропущена только если источник пакета по каким-то своим внутренним соображениям решает не отправлять его. Например, если сработало запрещающее правило фаервола. Очевидно, что такой пакет не покинет своего места рождения. И, кстати, Ethernet - это ещё не физический уровень.

    3. Ethernet используется в локальных сетях. И топология LAN на это не влияет - с маршрутизатором или без него.

    4. Если есть чисто локалка на свиче, то сетевой уровень по-любому используется?
    Да, сетевой уровень используется и здесь.

    Допустим с датаграммы udp упаковка в ip пакет, затем только в кадр ethernet?
    Да, UDP заворачивается сначала в IP, а затем в Ethernet.

    И по-любому отрабатывают dhcp и arp?
    DHCP не является обязательным для применения (он, кстати, работает поверх UDP). ARP тоже может не использоваться, если в этой сети не используется IP адресация (а вот ARP уже самостоятельный протокол канального уровня, который упаковывается только в Ethernet).

    5. Во времена до изобретения Ethernet использовались другие протоколы. Соответственно, и оборудование было другое, поддерживающее данные протоколы.
    Ответ написан
    3 комментария
  • Почему поток не останавливается?

    Vamp
    @Vamp
    Тут есть две проблемы.

    Первая очевидная проблема в том, что main поток на первой же итерации впадает в сон на методе wait(), а в программе больше нет потоков, которые могли бы вызвать notify() и разбудить main. Поэтому main бесконечно ждёт и не может остановить liche и sude.

    Вторая совсем неочевидная в том, что синхронизация некорректно используется. У вас синхронизируется только запись в переменную isRun. Чтение этой переменной так же должно быть синхронизировано. Иначе это приведет к странным неуловимым багам.
    Ответ написан
    2 комментария
  • Как запустить майнкрафт через коммандную строку?

    Vamp
    @Vamp
    Для 1.17.1 нужна java версии 17. Судя по ошибкам у вас 8 версия.
    Ответ написан
    Комментировать
  • DNAT. Где ошибка?

    Vamp
    @Vamp
    Нужно ещё указать таблицу nat

    iptables -t nat -A PREROUTING -d 4.4.4.100 -p tcp -m tcp --dport 2222 -j DNAT --to-destination 192.168.100.100:22
    Ответ написан
    Комментировать
  • Методы или инструменты на python для построения маршрута на схематичной карте в игре?

    Vamp
    @Vamp
    Вам необходимо разбить карту на тайлы и воспользоваться одним из алгоритмов поиска пути.

    Например, A*. Это популярный алгоритм с большим количеством примеров по всему интернету. Наверняка найдется и готовая библиотека с его реализацией.
    Ответ написан
    1 комментарий
  • Как на PHP при OAuth-авторизации в Яндекс.Почте работать по протоколам IMAP и SMTP, используя не пароль, а OAuth-токен?

    Vamp
    @Vamp
    Стандартный модуль php_imap не поддерживает XOAUTH2. И, вероятно, никогда не будет поддерживать. Существует план поддержки XOAUTH2, но работа по нему не ведётся.

    Вам следует воспользоваться альтернативными реализациями IMAP протокола, поддерживающие XOAUTH2. Например, webklex/php-imap.

    С SMTP так же - берите любую библиотеку с поддержкой XOAUTH2.
    Ответ написан
    Комментировать
  • Технический нейминг серверов. По какому принципу называть сервера?

    Vamp
    @Vamp
    Я использую нейминг по физическому расположению сервера.

    {имя дц}-{номер стойки}-{номер юнита в стойке}

    Получается что-то типа:

    miran-8-40
    itsoft-1-1

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

    m-08-40
    i-01-01

    Если серверов не так много чтобы арендовать стойки целиком, то просто порядковый номер сервера:

    m-01
    i-15

    Ну или два/три ведущих нуля, если количество серверов 1000/10000:

    m-001
    i-015

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

    Почему не 1 символ?
    Ответ написан
    3 комментария
  • Платформа/движок для сбора обращений граждан?

    Vamp
    @Vamp
    Подойдёт любая тикетница. Например, OTRS или osTicket. Каждое обращение - новый тикет. Тикетам можно настраивать напоминания, если они не закрыты какое-то время (sla), приоритеты.
    Ответ написан
    Комментировать
  • Как в терминале открыть путь до папки?

    Vamp
    @Vamp
    Выполнить один раз на сервере команду:
    echo 'cd /papka' >> ~/.bashrc
    Ответ написан
    Комментировать
  • Как правильно написать свой обработчик ошибок php?

    Vamp
    @Vamp
    Как правило, обычные ошибки не обрабатывают в таком обработчике, а конвертируют в ErrorException.

    function error_handler(
        $error_code,
        $error_message,
        $error_file_name,
        $error_line
        // $error_context - не объявляйте этот аргумент. Он не существует.
      ){
    
        throw new ErrorException($error_message, 0, $error_code, $error_file_name, $error_line);
    
      }
    
      set_error_handler('error_handler', -1);

    Ну а дальше ловите исключения как обычно.

    // some code...
    
    $host_db = '127.0.0.1';
    $login_db = 'root';
    $password_db = '';
    $database_db = 'some_db';
    
    $DB = new PDO('mysql:host=' . $host_db . ';dbname=' . $database_db, $login_db, $password_db);
    $DB -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    try {
        $DB -> beginTransaction();
    
        // some code...
    
        $DB -> commit();
    } catch (\Throwable $e) {
        $DB->rollback();
    }
    // some code...
    Ответ написан
    6 комментариев
  • Как происходит связывание с предыдущим узлом в LinkedStack?

    Vamp
    @Vamp
    1. Просто чтобы продемонстрировать использование паттерна sentinel value. В данном конкретном примере можно было обойтись просто null.

    2. В присваивании сначала выполняется правая часть - создаётся объект Node, которому в аргументы конструктора передается item и текущее значение, хранящееся в переменной top. После этого переменной top присваивается ссылка на этот новый объект.

    Это более короткий вариант следующего кода:
    Node<T> oldTop = top;
    top = new Node<T>(item, oldTop);
    Ответ написан
    4 комментария
  • Какие из бекенд фреймворков наиболее "самодостаточные"?

    Vamp
    @Vamp
    Ответ написан
    Комментировать
  • ООП: Правильно ли архитектурно так делать?

    Vamp
    @Vamp
    Возможно, это нормально, так и должно быть ? или как архитектурно правильно решать подобное?

    Это нормально. Безликие массивы становятся осмысленными сущностями. Такой код становится проще понимать и поддерживать.

    Используемый вами подход называется data transfer object (DTO). Широко распространенная практика. DTO отлично сочетается с иммутабельностью, которая присутствует в ваших классах.

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

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

    Называется ORM. Находится в ответственности ORM слоя/фреймворка.
    Ответ написан
    4 комментария
  • Как настроить xdebug для докера на vps?

    Vamp
    @Vamp
    У вас сложности с тем, что xdebug является инициатором коннекта на ваш домашний ip. И если домашний провайдер выдаёт вам не белый IP, то напрямую такой коннект сделать не удастся.

    Выходом может быть проброс порта через ssh.

    ssh -R 9003:172.17.0.2:9003 user@vpsaddr
    Данная команда установит ssh соединение с логином user на ваш vps по адресу vpsaddr и откроет на этом сервере порт 9003, который сквозь ssh соединение будет прозрачно проксироваться на 9003 порт уже на вашем локальном компьютере.

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

    Узнать его можно командой
    docker inspect ваш-контейнер | grep IPAddress
    Этот ip адрес нужно прописать в xdebug.client_host и в опцию -R вместо 172.17.0.2.
    Ответ написан
    8 комментариев
  • Что за фигурные скобки в Java?

    Vamp
    @Vamp
    Эта конструкция называется блоком статической инициализации. Есть ещё точно такой же блок динамической инициализации, только без ключевого слова static.

    Блоки инициализации нужны для задания начальных значений полям класса.
    class Initable2 {
        static int staticNonFinal;
    
        public static void main(String[] args) {
            System.out.println(staticNonFinal);
        }
    }

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

    class Initable2 {
        static int staticNonFinal;
    
        // Вот этот блок будет добавлен к
        // вашему классу во время компиляции.
        static {
            staticNonFinal = 0;
        }
    
        public static void main(String[] args) {
            System.out.println(staticNonFinal);
        }
    }


    Разумеется, вы можете инициализировать переменные своими значениями:
    class Initable2 {
        static int staticNonFinal = 42;
    
        static String a = "hello";
    
        static Cache<String, Integer> b = CacheBuilder.newBuilder()
            .maximumSize(100)
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .build();
    }

    И тогда компилятор в блоке инициализации будет подставлять ваши значения вместо нулей:
    class Initable2 {
        static int staticNonFinal;
    
        static String a;
    
        static Cache<String, Integer> b;
    
        static {
            staticNonFinal = 42;
            a = "hello";
            b = CacheBuilder.newBuilder()
                .maximumSize(100)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .build();
        }
    }

    А если вашей переменной требуется какая-то сложная инициализация, которую одной строкой не представить (как в примере с Cache), то тогда вам придется написать блок инициализации явным образом вручную:
    class Initable2 {
        static int staticNonFinal = 42;
    
        static Map<Integer, String> statusCodes = new HashMap<>();
    
        static {
            statusCodes.put(200, "OK");
            statusCodes.put(404, "Not Found");
            statusCodes.put(418, "I'm a teapot");
        }
    }

    И тогда компилятор сгенерирует вам такой код:
    class Initable2 {
        static int staticNonFinal;
    
        static Map<Integer, String> statusCodes;
    
        static {
            staticNonFinal = 42;
            statusCodes = new HashMap<>()
            statusCodes.put(200, "OK");
            statusCodes.put(404, "Not Found");
            statusCodes.put(418, "I'm a teapot");
        }
    }


    Точно таким же способом инициализируются и нестатические поля при помощи блока динамической инициализации (перед таким блоком отсутствует ключевое слово static и выглядит как просто фигурные скобки в теле класса). Каждый раз при создании объекта класса сначала выполняется блок динамической инициализации, а затем конструктор. Именно в таком порядке. Блок статической инициализации выполняется один раз при загрузке класса в память.

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

    Вот эти все блоки инициализации были придуманы создателями языка java чтобы исключить целый класс лютых ошибок, связанных с доступом к неинициализированным переменным, характерный для языков си и си++.
    Ответ написан
    Комментировать
  • Как сделать свою mvn dependency?

    Vamp
    @Vamp
    Для этого нужно создать maven project. В pom.xml этого проекта прописать group, artifact и version. Затем собрать проект командой mvn install

    Maven скомпилирует код вашего проекта, упакует в jar и скопирует этот jar вместе с pom.xml в ваш локальный maven репозиторий.

    Далее в другом проекте подключаете свою зависимость как любую другую зависимость, указывая group, artifact и version, которые прописали ранее.
    Ответ написан
    Комментировать
  • Как мониторить работу скрипта PHP?

    Vamp
    @Vamp
    Начните с настройки директив slowlog в конфиге fpm.

    request_slowlog_timeout mixed
    The timeout for serving a single request after which a PHP backtrace will be dumped to the 'slowlog' file. A value of '0' means 'Off'. Available units: s(econds)(default), m(inutes), h(ours), or d(ays). Default value: 0.

    slowlog string
    The log file for slow requests. Default value: #INSTALL_PREFIX#/log/php-fpm.log.slow.

    Как только какой-либо скрипт работает дольше request_slowlog_timeout, снимается стек трейс данного скрипта и записывается в текстовый файл по пути, указанному в slowlog. Если тормозит какое-то конкретное место, то в стек трейсе будет видно какое. Например, если тормозит база, то в slow логе в топе стек трейса будет, например, вызов PDOStatement::execute.
    Ответ написан
    Комментировать