• Что означает ошибка 40: Too many levels of symbolic links?

    AlexanderTsymbal
    @AlexanderTsymbal
    tsymbal.su
    Посмотрите, кто автор симлинков. Вероятно, автор симлинков - один пользователь, а автор каталогов, на которые они ссылаются - другой. Пересоздайте симлинки, авторизовавшись тем же пользователем, который создал каталоги.
    Если не поможет, то попробуйте то, что посоветовал Антон Артёмов Антон Артёмов . Но disable_symlinks if_not_owner может быть не просто так там установлена.
    Ответ написан
    Комментировать
  • Есть ли какие-то best practices как организовывать файлы веб-проекта с докером?

    Уж не так все и просто, комрад ;)

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

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

    /project-group (organization):
        /api - сюда можно вынести api вашего проекта.
        /desktop - здесь ваш web-проект для desktop на php, например.
        /mobile - здесь ваш web-проект для мобильной версии сайта, на той-же node.js.
        /admin - здесь ваша админка.
        /infrastructure - ну, или назовите проще, "server". Здесь ваши Dockerfile, docker-compose, ci/cd скрипты и т.п.


    Чтобы моч варировать вашу инфраструктуру в зависимости от окружения, вы должны разделить репозиторий инфраструктуры на отдельные сервисы. Например, не все сервисы проекта должны запускаться в test окружении или на сервере тестовых веток на поддоменах, когда вы делаете домены вида "feature-1.test.project.com", чтобы ваши тестировщики могли тестировать фичи параллельно и независимо друг от друга. Так же, на dev и/или test окружениях может потребоваться сделать сервисы-заглушки на внешние api которые вы используете. Ну, например, на сервисы онлайн оплаты товаров на вашем сайте, которые будут отвечать всегда "OK" или не "OK".

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

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

    /infrastructure
       /api
           service.yml
           build.yml
           deploy.yml
       /mobile
           service.yml
           build.yml
           deploy.yml
       /desktop
           service.yml
           build.yml
           deploy.yml
       /admin
           service.yml
           build.yml
           deploy.yml
       /mysql
           mysql.cnf
           service.yml
       /redis
           redis.conf
           service.yml
       /php-fpm
           Dockerfile
           www-conf
           php.ini
           service.yml
       /nginx
           nginx.conf
           /prod
                site.conf
           /test
                site.conf
           /dev
                site.conf
       /cron
           Dockerfile
           crontab
           service.yml
    mobile-dev.sh
    desktop-dev.sh
    prod.sh
    test.sh


    В этих самых *.sh файлах, что указаны выше, вы производите запуск нужного состава сервисов. К примеру, разработчику мобильной версии на react не обязательно покупать мощный ПК, чтобы на его машине запускать вообще весь проект, с mysql, redis, admin и другими сервисами. Вам будет достаточно собрать образ мобильного приложения, и написать в mobile-dev.sh примерно следующее:

    docker-compose -f mobile/service.yml pull;
    docker-compose -f mobile/service.yml down;
    docker-compose -f mobile/service.yml up --detach;


    Ну а в mobile/service.yml может быть что-то следующее:

    version: "3.7"
    
    services:
      mobile:
        image: keymetrics/pm2:10-alpine
        environment:
          APP_ENV: ${APP_ENV}
          APP_LANG: ${APP_LANG}
          API_URL: ${API_URL}
          BASIC_TOKEN: ${BASIC_TOKEN}
        working_dir: /app
        command: pm2-runtime start config.js --env $APP_ENV
        volumes:
          - /etc/timezone:/etc/timezone:ro
          - /etc/localtime:/etc/localtime:ro
          - ${APP_DIR}:/app
        restart: always
        container_name: mobile


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

    Ваш сайт - так же, должен запускаться отдельным service.yml файлом. Service.yml - можно поменять на docker-compose.yml в директории каждого сервиса, но, service здесь смотрится красивее.

    Если требуется поднять все сервисы, необходимо передать последовательно все service.yml файлы через -f флаг вашему docker-compose. Это будет громоздкая команда, поэтому и делаются отдельные *.sh файлы для запуска.

    Требуется понимать, что не следует хранить Dockerfile в репозитории каждого проекта, если наличие образа потребуется для этого проекта. Не каждый разработчик умеет делать Dockerfile и, например, устанавилвать расширения для PHP в рамках этих Dockerfile. Делегировав ответственность по сборке Dockerfile разработчикам проекта, вы рискуете получить неработающий сервис. Лучшее место для Dockerfile - в нашем примере, это репозиторий infrastructure, находящийся в распоряжении ваших DevOps-инженеров.

    Та же история и с описанием build-процессов и процессов CI/CD. Не следует доаверять разработчику сборку его приложения в рамках целой огромной инфраструктуры проекта. Для этого в примере репозитория infrastructure - есть файлы build.yml/deploy.yml, в которых описана сборка и доставка сервисов. Любые CI/CD средства могут подключать фрагменты pipeline с внешних репозиториев, поэтому, когда у вас возникнет потребность сделать автобилд и автодеплой - проблем не будет, вы ведь уже учли все подводные камни совместной работы специалистов в вашей компании.

    Прошу учесть следующее.

    Выше описано, как правильно реализовать ваш проект на docker + docker-compose. Здесь не учтено наличие swarm-mode или kubernetes, тем не менее, данную структуру будет гораздо проще использовать в режиме swarm или c использованием kubernetes.

    ЗЫ. Конечно, есть и другие рабочие практики на эту тему ;) Эта нравится мне больше всего, и работает универсальней остальных.
    Ответ написан
    3 комментария
  • Приём данных от Arduino в Linux-консоли. Как?

    @howeal
    Не забывайте про stty и настройку COM порта. У меня настройка идёт такой командой.
    stty -F /dev/ttyACM0 cs8 9600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts raw

    код для Arduino:
    Serial.begin(9600);
    Serial.println("START");

    Демон, читающий каждые 3 секунды команды с Arduino и выводящий всё на консоль (на sh). Текст от Arduino попадает в переменную $LINE:

    #!/bin/sh
    insmod usbserial
    insmod ftdi_sio
    insmod cdc-acm
    
    while [ true ]
    do
    
    stty -F /dev/ttyACM0 cs8 9600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts raw
    
    	while read LINE
    	do
    	
    	echo $LINE
    			
    	done < /dev/ttyACM0
    /bin/sleep 3
    done
    
    


    Таким образом, при запуске демона Arduino сама перезагружается и пишет в консоль, при подключении/отключении производится повторная настройка порта и всё продолжает работать дальше.
    Ответ написан
    Комментировать
  • Закрепление строки и столбцов в phpexcel - как?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега PHP
    Копайте в сторону официальной документации, там это есть.
    Нет, вру, нет этого в доках, только в примерах.
    $objPHPExcel->getActiveSheet()->freezePane('A2');
    Обратите внимание, что аргумент функции - это адрес ячейки, выше и левее которой будут закрепляться области. То есть A2 закрепит первую строку, а B1 - первый столбец.
    Ответ написан
    3 комментария
  • Почему программы на ассемблере работают быстрее?

    Decadal
    @Decadal
    Любое преобразование языка высокого уровня в машинный код приводит к издержкам. Ассемблер работает быстрее, потому что программист не пишет ничего лишнего, а чтобы обеспечить универсальность применения языковых конструкций, все машинные коды, созданные трансляторами, избыточны.
    Ответ написан
    6 комментариев
  • Как обстоят дела с API WhatsApp сегодня (Юриспруденция)?

    bro-dev
    @bro-dev
    Занимался такой же фигней, самый рабочий и практичный способ это написать постоянно работающий сервис, по рест апи принимает запросы, а внутри эмулятор браузера с открытой веб версией вотсапа.
    Ответ написан
    3 комментария
  • За что отвечает require-dev в Composer?

    @harmoxyne
    Отвечает за те зависимости, которые необходимы только для dev-окружения.
    К примеру, Вы точно знаете, что библиотека phpunit нужна для разработки, а на проде будет лишней, тогда phpunit попадает в require-dev.
    Когда выполняется простой
    composer install
    устанавливаются и dev-зависимости.
    Когда выполняется
    composer install --no-dev
    устанавливаются только те зависимости, что в основном блоке require.

    Источник
    Ответ написан
    Комментировать
  • Разработка Qt - структура Qt-приложения.?

    @tugo
    Посмотрите это видео. Вот так, для начала, должна выглядеть структура вашего приложения.
    1. Для построения графического интерфейса пользуйтесь Qt Designer (а не размещая врукопашную виджеты, как это делаете вы).
    2. В первом, самом простом приложении, должно быть 4 файла исходных кодов.
    main.cpp
    MainWindow.h
    MainWindow.cpp
    MainWindow.ui
    // MainWindow.h
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget * parent = 0);
        ~MainWindow();
    
    signals:
    
    protected:
    
    private:
        Ui::MainWindow * ui;
    };


    3. Если количество элементов в MainWindow становится слишком большим, выделяйте элементы в отдельные классы, наследники класса QWidget.
    Допустим, у вас в MainWindow расположен элемент Tab Widget, в котором 2 вкладки.
    Логично вынести логику работы элементов в каждой вкладке в свой класс, т.е. у вас в проекте должно появиться еще 6 файлов:
    MyTabWidget1.h
    MyTabWidget1.cpp
    MyTabWidget1.ui

    MyTabWidget2.h
    MyTabWidget2.cpp
    MyTabWidget2.ui

    // MyTabWidget1.h
    #pragma once
    
    #include <QWidget>
    
    namespace Ui {
    class MyTabWidget1;
    }
    
    class MyTabWidget1: public QWidget
    {
        Q_OBJECT
    
    public:
        explicit MyTabWidget1(QWidget * parent = 0);
        ~MyTabWidget1();
    
    private:
        Ui::MyTabWidget1* ui;
    };


    В классе MainWindow используются объекты классов MyTabWidget1 и MyTabWidget2.
    Логика работы MainWindow резко похудеет, все перенесется в MyTabWidget1 и MyTabWidget2.

    4. Дальше. Избегайте реализации логики работы класса GUI. Эти классы (MyTabWidget1 и MyTabWidget2, MainWindow) должны быть простыми прокладками, трансляторами сигналов от пользователя в логику работы приложения и визуализаторами состояния приложения пользователю.
    Начинаете логику работы приложения реализовывать в отдельном классе.
    Обмен информацией между Logic <--> MainWindow возложите на сигналы-слоты.
    Ответ написан
    Комментировать
  • Yii2: Как вывести input hidden?

    Frostealth
    @Frostealth
    Backend Developer
    <?= $form->field($doctorSearch, "specialization_id")->hiddenInput()->label(false) ?>
    Ответ написан
    Комментировать
  • Composer дает ошибку "Your requirements could not be resolved to an installable set of packages". Как разрешить?

    @krlljs Автор вопроса
    Нашел поднятую тему тут и тут, там и же и подсказка к разрешению:

    1. Проверить наличии расширения ext-xsl

    $ composer show --platform | grep ext-x
    $ composer show --platform | grep ext-xsl

    2. если в списки ext-xsl не будет, установи
    $ sudo apt-get install php5-xsl
    3. и добавляй зависимость в composer.json как require-dev, читай Require inline alias
    composer require --dev phpdocumentor/phpdocumentor dev-master

    4. чтоб ошибка больше не тревожила, следует так же добавлять зависимость на расширения, читай Platform packages
    composer require --dev ext-xsl "*"
    Ответ написан
    4 комментария
  • Как сделать интерактивную карту?

    @imhuman
    SVG карту с нужным оформлением и маркерами можно сгенерировать тут pixelmap.amcharts.com
    Ответ написан
    Комментировать
  • Как сделать доступ к серверу только из России в iptables без geoip?

    martin74ua
    @martin74ua Куратор тега Linux
    Linux administrator
    man ipset

    иначе ваш следующий вопрос будет - почему все так тормозит.
    Потому что каждый пакет проходит 62к проверок....
    Ответ написан
    5 комментариев
  • Как получить данные по шаблону с помощью preg_match?

    @karminski
    Senior React.JS Developer
    php.net/manual/ru/function.preg-match-all.php

    $source = "Разыгрывает карту @67@, @6@ или @168@, затем удаляет себя из игры.";
    preg_match_all("/@(\d+)@/", $source, $matches);


    На выходе:
    array (size=2)
      0 => 
        array (size=3)
          0 => string '@67@' (length=4)
          1 => string '@6@' (length=3)
          2 => string '@168@' (length=5)
      1 => 
        array (size=3)
          0 => string '67' (length=2)
          1 => string '6' (length=1)
          2 => string '168' (length=3)
    Ответ написан
    1 комментарий
  • Как защитить свою верстку от рипа?

    bingo347
    @bingo347
    Crazy on performance...
    Не работать без предоплаты минимум 50% и не цепляться за таких вот заказчиков
    (в голове мысли "что то тут не чисто)
    абсолютно правильные мысли
    Даже если Вы защитите свою работу от "угона", велик риск что просто проработаете за бесплатно, а Ваш заказчик обломавшись с Вами пойдет искать себе другую жертву, ибо сроки у него не жмут, так как когда сроки жмут заказчики готовы к предоплате не то что 50%, а даже 120% (20% - надбавка за переработки)
    Ответ написан
    12 комментариев
  • Как правильно оформить условие?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега PHP
    Во-первых, если вам нужно, чтобы проверки были независимыми, сделайте их независимыми. Сейчас ваш код читается как "если 1 то, иначе если 2 то, иначе если 3 то". Иными словами, уберите из логики "иначе".

    Во-вторых, это хрень полная: $data['dopvopsuvsid'] == 3 || 4 || 5. Это условие всегда будет срабатывать, потому что 4 и 5 всегда будут приводиться к true. Либо пишите полное сравнение каждый раз, либо используйте in_array.
    Ответ написан
    4 комментария
  • Как начать использовать технологию WebSocket?

    bagau
    @bagau
    Фронтент разработчик
    На прошлой работе я писал онлайн-консультанта с использованием веб-сокетов. На сервере php с вебсокетом, на клиенте javascript. Комментировал код, можете посмотреть здесь на Github.
    Файл websocket.php - логика самого вебсокета, с комментариями. Я ничего не понимал в вебсокетах, поэтому комментировал каждую строку, чтобы понять.
    файл start_socket.php - работа с вебсокетом.
    Написано без использования фреймворков.
    Онлайн консультант в принципе рабочий, но я его не смог доделать, ушел с работы
    Ответ написан
    Комментировать
  • Какими опциями ini_set в php рекомендуете пользоваться для упрощения работы и увеличения защищенности сайта?

    mahoho
    @mahoho
    Full stack certified PHP developer.
    Начните с документации: php.net/manual/ru/security.php. там очень подробно описано, на что следует обращать внимание, уделяя внимание безопасности в PHP, не только насчет ini_set(). Там и XSS, и SQL Injection, и session highjacking и все-все-все.
    Ответ написан
    Комментировать
  • Как сделать редирект некоторых страниц в ngninx?

    isqua
    @isqua
    Научу HTML, CSS, JS, BEM и Git
    Нужно писать location внутри секции server, которая слушает 80-й порт. В location нужно проверить гет-параметр.

    server {
        listen 80;
    
        location ~* /component/content/article.html {
            if ($args ~ "^id=(71|72)") {
                return 301 https://мойсайт$request_uri;
            }
        }
        # всякие ваши настройки
    }


    Интересно, почему вдруг эти две страницы, которые отличаются от других только id, понадобилось вынести? Может, лучше вынести их в отдельный путь? Типа /private/component/content/article.html и уже для /private всегда делать редирект на HTTPS?
    Ответ написан
    3 комментария