Страницы

Поиск по вопросам

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

четверг, 5 марта 2020 г.

Как правильно деплоить проект?

#golang #docker #развертывание #bitbucket


Здравствуйте, есть restful сервис написанный на golang.
Раньше работал на локальном хосте, сейчас же появилась потребность деплоить все на
сервер.
Не могу понять как лучше осуществить деплой.
Создал репозиторий на бакете, а от дальше туплю.
Каждое изменение(А их будет много) копировать, билдить, потом закрывать процесс с
активным приложением go и запускать новый. Так как изменения будут очень частые и очень
интересует как можно автоматизировать этот процесс.
    


Ответы

Ответ 1



Есть такой подход, под названием Continuous Delivery (Непрерывное развертывание), который предлагает решение описанной вами проблемы. Что это за зверь и с чем его едят, описано в книге Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation / Непрерывное развертывание ПО. Автоматизация процессов сборки, тестирования и внедрения новых версий программ Небольшая выжимка о CD (цитата отсюда): Основная идея CD в том, чтобы построить конвейер (Deployment Pipeline), позволяющий каждому изменению в системе контроля версий попасть в боевое окружения стандартным и полностью автоматизированным способом. Приблизительно это может выглядеть следующим образом: Изменения вносятся в систему контроля версий (СКВ). Запускается система непрерывной интеграции (Continuous Integration, CI), собирается билд (если это компилируемый язык), прогоняются все необходимые тесты. В случае успешности предыдущего шага, билд выкатывается на окружение тестирования (QA). После успешного тестирования билд выкатывается на stage окружение (pre-production), которое максимально приближено к боевому окружению. Если все прошло хорошо, то билд попадает в боевое окружение. Тут встает в полный рост вопрос, как сделать так, чтобы все окружения, начиная с окружения разработчиков, максимально соответствовали друг другу. Для этого существуют инструменты управления конфигурацией (Configuration management system). Самое главное, что конфигурация окружений — это такой же код, и к нему точно также применимы все вышеперечисленные подходы: хранение в СКВ, CI, тестирование. Так вот, если этот процесс отлажен, все изменения проходят по нему, и, потенциально, каждое изменение может быть выкачено в продакшен, то это и называется процессом непрерывной поставки ПО.

Ответ 2



Вам в любом случае нужны решения для CI (Continuous Integration) и CD (Continuous Deployment). Вот список, из которого вы можете выбрать(ссылка). Например, как это работает с Drone: Через веб морду Drone, вы настраиваете Drone для получения проекта с репозитория Git и выполнение "запуска". Что конкретно происходит при запуске описано в следующем шаге. Вместе с кодом приложения в репозитории должен лежать .drone.yml файл, который говорит Drone как устанавливать и запускать ваше приложение. Далее вы делаете git push в ваш репозиторий, Drone проверяет репозиторий на недавно залитый Docker образ (по вашему выбору), а затем стартует его. На основе вашей конфигурации результатом успешного запуска может быть уведомление («Сборка выполнена успешно!»), создание бинарной версии или даже развертывание. Наконец, Drone удаляет Docker контейнер и переустанавливает его так, чтобы он был в исходном и известном состоянии для следующей сборки. P.S. по связке Drone + Docker есть неплохая статья на Хабре.

пятница, 14 февраля 2020 г.

После перезагрузки сервера Tomcat приложения не запускаются до передеплоя

#tomcat #centos #развертывание


На севере CentOS установлен сервер приложений Tomcat. В нем развернут проект в корневой
папке webapps/ROOT как описано здесь: Tomcat 9 deploy into ROOT

После физической перезагрузки сервера поднимается служба Tomcat, но приложение в
корневой папке webapps/ROOT остается недоступно.

Если заново скопировать {name-of-the-app}.war в папку myapps, то Tomcat заново разворачивает
архив, и приложение становится доступно.



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

Что я делаю не так?



UPD: - Логи сервера приложений

catalina.out - после перезапуска сервера

13-Sep-2018 22:09:11.152 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Server version:        Apache Tomcat/9.0.12
13-Sep-2018 22:09:11.155 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Server built:          Sep 4 2018 22:13:41 UTC
13-Sep-2018 22:09:11.155 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Server number:         9.0.12.0
13-Sep-2018 22:09:11.156 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
OS Name:               Linux
13-Sep-2018 22:09:11.156 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
OS Version:            3.10.0-862.11.6.el7.x86_64
13-Sep-2018 22:09:11.156 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Architecture:          amd64
13-Sep-2018 22:09:11.156 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Java Home:             /usr/java/jdk1.8.0_181-amd64/jre
13-Sep-2018 22:09:11.156 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
JVM Version:           1.8.0_181-b13
13-Sep-2018 22:09:11.156 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
JVM Vendor:            Oracle Corporation
13-Sep-2018 22:09:11.156 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
CATALINA_BASE:         /opt/apache-tomcat-9.0.12
13-Sep-2018 22:09:11.156 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
CATALINA_HOME:         /opt/apache-tomcat-9.0.12
13-Sep-2018 22:09:11.157 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Command line argument: -Djava.util.logging.config.file=/opt/tomcat/conf/logging.properties
13-Sep-2018 22:09:11.159 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
13-Sep-2018 22:09:11.159 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Command line argument: -Djava.library.path=/usr/local/apr/lib
13-Sep-2018 22:09:11.159 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
13-Sep-2018 22:09:11.159 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
13-Sep-2018 22:09:11.159 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Command line argument: -Dorg.apache.catalina.security.SecurityListener.UMASK=0027
13-Sep-2018 22:09:11.159 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Command line argument: -Dignore.endorsed.dirs=
13-Sep-2018 22:09:11.160 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Command line argument: -Dcatalina.base=/opt/tomcat
13-Sep-2018 22:09:11.160 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Command line argument: -Dcatalina.home=/opt/tomcat
13-Sep-2018 22:09:11.160 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log
Command line argument: -Djava.io.tmpdir=/opt/tomcat/temp
13-Sep-2018 22:09:11.160 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent
Loaded APR based Apache Tomcat Native library [1.2.17] using APR version [1.4.8].
13-Sep-2018 22:09:11.160 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent
APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
13-Sep-2018 22:09:11.160 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent
APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
13-Sep-2018 22:09:11.166 INFO [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL
OpenSSL successfully initialized [OpenSSL 1.0.2k-fips  26 Jan 2017]
13-Sep-2018 22:09:11.338 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing
ProtocolHandler ["http-nio-8080"]
13-Sep-2018 22:09:11.355 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector
Using a shared selector for servlet write/read
13-Sep-2018 22:09:11.367 INFO [main] org.apache.coyote.http11.AbstractHttp11Protocol.configureUpgradeProtocol
The ["https-openssl-apr-8443"] connector has been configured to support negotiation
to [h2] via ALPN
13-Sep-2018 22:09:11.367 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing
ProtocolHandler ["https-openssl-apr-8443"]
13-Sep-2018 22:09:11.428 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing
ProtocolHandler ["ajp-nio-8009"]
13-Sep-2018 22:09:11.429 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector
Using a shared selector for servlet write/read
13-Sep-2018 22:09:11.430 INFO [main] org.apache.catalina.startup.Catalina.load Initialization
processed in 902 ms
13-Sep-2018 22:09:11.476 INFO [main] org.apache.catalina.core.StandardService.startInternal
Starting service [Catalina]
13-Sep-2018 22:09:11.477 INFO [main] org.apache.catalina.core.StandardEngine.startInternal
Starting Servlet Engine: Apache Tomcat/9.0.12
13-Sep-2018 22:09:11.489 INFO [main] org.apache.catalina.startup.HostConfig.deployDescriptor
Deploying deployment descriptor [/opt/apache-tomcat-9.0.12/conf/Catalina/localhost/ROOT.xml]
13-Sep-2018 22:09:11.517 WARNING [main] org.apache.catalina.startup.HostConfig.deployDescriptor
The path attribute with value [] in deployment descriptor [/opt/apache-tomcat-9.0.12/conf/Catalina/localhost/ROOT.xml]
has been ignored
13-Sep-2018 22:09:11.527 WARNING [main] org.apache.catalina.startup.HostConfig.deployDescriptor
Deployment of deployment descriptor [/opt/apache-tomcat-9.0.12/conf/Catalina/localhost/ROOT.xml]
with an external docBase means the directory [/opt/apache-tomcat-9.0.12/webapps/ROOT]
in the appBase will be ignored
13-Sep-2018 22:09:12.431 INFO [main] org.apache.jasper.servlet.TldScanner.scanJars
At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for
this logger for a complete list of JARs that were scanned but no TLDs were found in
them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation
time.


catalina.out - после передеплоя

13-Sep-2018 22:12:42.714 WARNING [main] org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom
Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [210,235]
milliseconds.
13-Sep-2018 22:12:42.786 INFO [main] org.apache.catalina.startup.HostConfig.deployDescriptor
Deployment of deployment descriptor [/opt/apache-tomcat-9.0.12/conf/Catalina/localhost/ROOT.xml]
has finished in [211,297] ms
13-Sep-2018 22:12:42.792 INFO [main] org.apache.coyote.AbstractProtocol.start Starting
ProtocolHandler ["http-nio-8080"]
13-Sep-2018 22:12:42.804 INFO [main] org.apache.coyote.AbstractProtocol.start Starting
ProtocolHandler ["https-openssl-apr-8443"]
13-Sep-2018 22:12:42.815 INFO [main] org.apache.coyote.AbstractProtocol.start Starting
ProtocolHandler ["ajp-nio-8009"]
13-Sep-2018 22:12:42.825 INFO [main] org.apache.catalina.startup.Catalina.start Server
startup in 211395 ms
13-Sep-2018 22:12:52.791 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]]
org.apache.catalina.startup.HostConfig.reload Reloading context []
13-Sep-2018 22:12:52.794 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]]
org.apache.catalina.core.StandardContext.reload Reloading Context with name [] has started
13-Sep-2018 22:12:53.966 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]]
org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs
yet contained no TLDs. Enable debug logging for this logger for a complete list of
JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during
scanning can improve startup time and JSP compilation time.
13-Sep-2018 22:12:53.994 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]]
org.apache.catalina.core.StandardContext.reload Reloading Context with name [] is completed

    


Ответы

Ответ 1



Как выяснилось, Tomcat на самом деле запускался и поднимал приложение, но делал это очень медленно, а передеплой просто ускорял этот процесс. В некоторых случаях загрузка Tomcat вместе со всеми приложениями может длиться ~17 МИНУТ Проблема связана с ошибкой JDK-4705093 при генерации SecureRandom для SHA1PRNG. // Неочевидно, правда.. !! Но такое тоже бывает.. Решение: Открываем файл $JAVA_PATH/jre/lib/security/java.security Находим строку securerandom.source=file:/dev/random Заменяем ее на строку securerandom.source=file:/dev/./urandom Дополнительно: Более подробное описание ошибки можно найти здесь: Tomcat 7 starts too late on Ubuntu 14.04 x64 | stackoverflow.com

четверг, 13 февраля 2020 г.

Сборка проекта

#c_sharp #развертывание


Доброго времени суток, не знаю, правильно ли я назвал вопрос, но суть такова:
Есть WPF проект, заходу в папку с проектом, там есть папки: bin, obj, Properties,
Resourses и все мои исходники. В папке bin есть папка Debug, там есть exe к моей программе. 
Как мне в кучу собрать весь этот проект? Я имею ввиду, собрать все нужные для работы
файлы в одну папку. Какие файлы нужные, какие нет?(звучит глупо,но иначе не знаю как
сформулировать).    


Ответы

Ответ 1



Офигенная статья в самом MSDN: http://msdn.microsoft.com/en-us/library/e2444w33.aspx В подробностях расписано, какие виды инсталлеров можно сделать, и в чем их отличия друг от друга. Если в общем, то есть 2 пути: ClickOnce Application Windows MSI Installer Первый - очень классный, легкий, быстрый установщик, да ещё и с автообновлялкой приложения при выходе новой версии. Второй - позволяет гораздо больше всегда впихивать в установочный проект, да ещё и имеет более широкие возможности настройки. На опыте развертывания в организации могу сказать, что использую ClickOnce, так как для небольших проектов оно подходит очень классно (кстати, GitHub и Google Chrome тоже его используют).

Ответ 2



Обычно всё нужное лежит в папке /bin/{конфигурация(обычно Debug | Release)} Но тут надо понимать, что туда могут не попадать dll которые установлены на девелоперской машине, поэтому, очень простой путь предложил @olter - создайте визардом installer - он для простых проектов сам сможет разобраться что надо а что нет.

пятница, 24 января 2020 г.

Туториал для распростронения SQL CLR приложений

#visual_studio #sql_server #развертывание #sqlclr


Создал некоторые SQL CLR Функции и процедуры в Visual Studio 2013.

Теперь нужно подготовить скрипт sql для распростронения функционала.
При этом скрипт должен обновлять assemblies в базе или добавлять их, если они в базе
данных не присутствуют. То же самое с CLR функциями и процедурами.

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

Как привильно настроить студию на необходимый вывод?
    


Ответы

Ответ 1



Простое решение - при генерации скрипта указывать студии в качестве цели пустую базу данных. Это приведет к генерации скрипта для создания базы с нуля. Править имя базы в свойствах проекта каждый раз неудобно, так что проще генерировать скрипт деплоя через MSBuild - из консоли или из билд-скрипта. Пример proj-файла: Создание чистой базы: Деплой с генерацией скрипта: Configuration=Debug;Platform=AnyCPU;TargetConnectionString=$(TargetConnectionString);TargetDatabaseName=$(TargetDatabase);UpdateDatabase=False;

GIT - настройка автоматического деплоя

#git #развертывание #bitbucket


Пытаюсь настроить автоматический деплой ветки с bitbucket. 
Указал url на сайте

http://site.ru/filename.php


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

exec('cd /../project && git pull');


Обновления файлов не происходит, только владелец меняется с root на www-data, а вот
если вызвать файл через консоль 

php filename.php


то обновления успешно пройдут.
Если у кого-то уже был подобный опыт, прошу совета! У всех файлов сейчас полные права:
rwxrwxrwx
    


Ответы

Ответ 1



Проблема решилась, git требовал наличие ключей не только в root-директории, а также в var/www

Mysql entity framework - Не удалось найти запрошенного поставщика данных

#mysql #сервер #entity_framework #развертывание


Имеется Web API приложение использующее сервер баз данных MySQL. На девелоперской
машине работает прекрасно. Перенёс приложение на сервер и после обращения к странице
вылетает исключение:

{
    ClassName: "System.ArgumentException",
    Message: "Указанный поставщик хранилища не найден в конфигурации или недопустим.",
    Data: null,
    InnerException: - {
    ClassName: "System.ArgumentException",
    Message: "Не удалось найти запрошенного поставщика данных .Net Framework. Возможно
он не установлен.",
    Data: null,
    InnerException: null,
    HelpURL: null,
    StackTraceString: " в System.Data.EntityClient.EntityConnection.GetFactory(String
providerString)",
    RemoteStackTraceString: null,
    RemoteStackIndex: 0,
    ExceptionMethod: "8 GetFactory System.Data.Entity, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089 System.Data.EntityClient.EntityConnection System.Data.Common.DbProviderFactory
GetFactory(System.String)",
    HResult: -2147024809,
    Source: "System.Data.Entity",
    WatsonBuckets: null,
    ParamName: null
    },
    HelpURL: null,
    StackTraceString: " в System.Data.EntityClient.EntityConnection.GetFactory(String
providerString) в System.Data.EntityClient.EntityConnection.ChangeConnectionString(String
newConnectionString) в System.Data.Entity.Internal.LazyInternalConnection.TryInitializeFromAppConfig(String
name, AppConfig config) в System.Data.Entity.Internal.LazyInternalConnection.Initialize()
в System.Data.Entity.Internal.LazyInternalConnection.CreateObjectContextFromConnectionModel()
в System.Data.Entity.Internal.LazyInternalContext.InitializeContext() в System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type
entityType) в System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() в System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
в System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider()
в System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate)
в MMSBDWebApplication.Models.UserModel.Login(String login, String password) в MMSBDWebApplication.Controllers.v1.UserController.Test()",
    RemoteStackTraceString: null,
    RemoteStackIndex: 0,
    ExceptionMethod: "8 GetFactory System.Data.Entity, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089 System.Data.EntityClient.EntityConnection System.Data.Common.DbProviderFactory
GetFactory(System.String)",
    HResult: -2147024809,
    Source: "System.Data.Entity",
    WatsonBuckets: null,
    ParamName: null
}


Конфигурационный файл:




  
    
    
Структура файлов полностью идентичны, как на сервере так и на девелоперской машине. Все библиотеки на месте. В чём может быть еще проблема?


Ответы

Ответ 1



Проблему решил, установив MySql Connector

суббота, 4 января 2020 г.

Синхронизация проекта на сервере Linux с github

#linux #nodejs #git #развертывание


Всем привет! Подскажите может уже есть готовое решение моей проблемы. Ситуация такая,
есть у меня локально проект NodeJS допустим я сделал изменения и закомитил на гитхаб,
хотелось бы что бы мой амазоновский сервер на Linux автоматически перекачал изменённые
файлы и перезапустил проект. Такую систему я видел на OpenShift.
    


Ответы

Ответ 1



Когда вы делаете git push и на гитхабе появляется новый коммит, где-то должен выполниться код, который сделает всю работу. Исполнители Есть следующие варианты «исполнителей»: Использовать сервер непрерывной интеграции. Это приложение, которое реагирует на коммиты и выполняет какие-либо задачи с содержимым каждого коммита. Обычно эти задачи описываются в определенном файле проекта, который версионируется как любой другой код. Для того, чтобы его «уведомить» о появлении нового коммита, нужно будет использовать веб-хуки — HTTP POST запросы с заданным содержимым, которые отправляет GitHub. Документация к конкретному серверу расскажет вам, как интегрировать его с GitHub. Сервер CI – это современный, хорошо поддерживаемый и масштабируемый путь. Рекомендую. Примеры: облачные: Travis CI, Circle CI. Я также люблю GitLab CI, но он работает только с GitLab (т.е. не GitHub). Во всех трех есть бесплатные подписки для opensource-проектов. self-hosted: Jenkins, TeamCity, Bamboo. Сервер с приложением может сам выкачивать изменения, собирать и разворачивать проект, получая уведомление через веб-хук. Для этого понадобится держать на нём: Всё сборочное окружение, git и репозиторий с проектом, Открытый порт для получения команд. Этот способ плох по множеству причин: уязвимость, лишнее окружение, замусоренный сервер, плохо масштабируется, труднее восстанавливать «с чистого листа». Знайте, что так можно, но, пожалуйста, не делайте так. git hooks. Скрипты, которые запускает git на сервере при определенных условиях, например при получении коммитов. Хуки можно установить на свой сервер, например, если у вас self-hosted GitHub. На github.com, насколько я знаю, их установить нельзя. Вырожденный случай, наследующий всё плохое от последних двух вариантов, — когда один сервер используется как git-сервер для командной работы, с помощью гит-хуков сам на себе собирает код и публикует его сам себе куда-нибудь в /srv/www/project. Это отличный способ потерять всё и сразу. Задачи А работа состоит из следующих основных этапов: Сборка проекта из исходного кода. Так же, как вы обычно собираете сайт на своей машине. Артефакты сборки — это различные «полезные» файлы, которые являются результатом сборки. Например, папка с файлами сайта — это артефакт, а папка node_modules — не артефакт. Развертывание проекта в каком-либо окружении. Доставка артефактов и, если необходимо, операции администрирования. Развертывание в боевом окружении должно производиться из одной установленной стабильной ветки с осмысленным названием: master, production и т.п. Из других веток код разворачивается в тестовые окружения либо никуда. Тут подробнее про конкретные задачи и различные способы их выполнения: Деплой на мастер сервер. Вот очень устаревший ответ, описывающий доставку артефактов с помощью rsync и c помощью git (тот самый вырожденный случай). Из ценного там — про rsync. Настройка и развертывание проекта c помощью Git.

среда, 25 декабря 2019 г.

Как временно “приглушить” monit на период развертывания сервиса через ansible?

#linux #развертывание #ansible #monit


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

Есть ansible playbook, который переустанавливает сервис, конфигурирует и перезапускает.
И monit тоже конфигурирует и перезапускает при необходимости. Работает это отлично,
но плохо то, что при этом monit шлет пачку писем:


service instance пропал
service instance появился
service instance сменил PID
monit перезагрузился


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

- name: monit не наблюдает за myservice
  shell: monit unmonitor myservice

- name: monit наблюдает за myservice
  shell: monit monitor myservice


Можно перезапускать сервис из самого monit'a. Тогда письма приходят с менее угрожающими
заголовками, вроде Action done myservice. Но всё равно одно или два письма + одно про
релоад монита.

- name: Перезапуск myservice через monit
  shell: monit restart myservice


Я беспокоюсь о том, что это всё сработает как у мальчика, который кричал «Волки!».
Все привыкнут, что с почты постоянно валится куча писем и что это нормальный процесс,
волноваться не о чем. Поэтому хочу, чтобы штатные работы не приводили ни к каким тревогам
вообще.

Можно ли это как-то реализовать на этом стеке технологий? Или я категорически неправ
в своих опасениях?
    


Ответы

Ответ 1



Решение monit config: /etc/monit/monitrc set alert {{mail_recipient}} but not on { action, instance } ansible: Во всех командах параметр -I нужен, почему — смотри ниже. В начале установки через monit останавливаем сервис, это считается action - name: Остановка myservice через monit shell: monit -I stop myservice Потом производим всю необходимую установку и настройку. Убеждаемся, что сам monit запущен. Перезагружаем конфиги через сам monit, это событие типа instance - name: Убедиться, что monit запущен service: name=monit state=started - name: Перезагрузка конфигов monit shell: monit -I reload Потом перезагружаем сервис, это считается action - name: Перезапуск myservice через monit shell: monit -I restart myservice Конфигурация monit Получать только определенные события set alert foo@bar only on { timeout, nonexist } Получать все события кроме некоторых: set alert foo@bar but not on { instance } Подробнее про фильтрацию событий в monit: https://mmonit.com/monit/documentation/monit.html#Setting-an-event-filter Оставшиеся проблемы monit "забывает" команды, отданные после перезагрузки — решено. Разобрано в отдельном вопросе, здесь я просто добавляю -I к командам. C такой конфигурацией monit перестает сообщать об изменениях собственного instance не только на период развертывания, а вообще. То есть, если он был перезагружен вручную, либо если упал а потом был поднят при развертывании — то сообщения не будет. Можно оставить только такой конфиг: set alert {{mail_recipient}} but not on { action } Но тогда при развертывании все равно будет одно сообщение на почту про sudo monit reload. Безуспешно пробовал такую схему, она не работает. name: monit - приостановить мониторинг shell: monit unmonitor all name: monit - перезагрузка конфигов shell: monit reload name: monit - возобновить мониторинг shell: monit monitor all

суббота, 14 декабря 2019 г.

Как упростить схему деплоя?

#git #развертывание


Первый раз работаю в небольшой команде на внутрикорпоративном проекте. Изучить гит
более-менее осилил. Теперь мучаюсь с деплоем. Суть такова:

Используем стандартную схему веток (master, develop, topic). Программируем и верстаем
у себя на локалке. Есть боевой сервер. Он же и git-сервер. Он же и тестовый сервер
:) Сервер содержит 2 веб-приложения. Первое мы пуллим из master-ветки — релиз готов,
второе — из develop — тестируем, прежде чем мастер пулить.

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


Переключиться с feature на develop, обновить ветку.
Смержить feature, запушить develop
Переключиться на master, обновить её
Смержить develop, запушить master
Подключиться к боевому серверу сделать пулл на develop-приложении
Подключиться к боевому серверу сделать пулл на master-приложении
??? 
"А тут ещё букву поправьте, пожалуйста"
goto 1


Это можно ли как-то всё упросить? Я уверен, что-то делаю неправильно.
    


Ответы

Ответ 1



Пункты 1-2 - это очень упрощенный (где убрано к примеру тестирование) процесс, который делает каждый разработчик. Это его обычный цикл. Пункт 3-4 - это релиз. Он не должен делать обычным разработчиком. Он делается релиз-менеджером (или ответственным человеком, назначенным на этом). Он не делается на каждый чих, а по процессу - раз в две недели или два раза в день. Пункты 5-8 делаются нажатием одной (максимум двух кнопок) или запуском одного скрипта. Он запускается на специальном билд сервере (для маленькой такой компании это может быть одна машина и для сборки, и для тестов и для репозитория). Сам скрипт сборки обычно делает следующее git clone / git archive прогон скрипта, который фиксит конфиги, шаблоны (вы же не хотите показывать всем программистам пароли к базе на проде?) запуск скрипта, который процессит css, минимизирует js и тому подобное. прогон юнит тестов (они здесь, так как после минимизации могут быть проблемы:) ) архивирование и занесение архива в надежное место подключаемся к прод серверу(серверам) и заливаем туда архив. архив распаковывается на сервере в отдельную папку, правится конфиг nginx/apache или симлинка и сервер рестартует. (можно конечно остановить сервер, перетереть файлы и запустить сервер, но если что то пошло не так...). на проде проганяются минимальные тесты (к примеру, что главная страница возвращает 200 код, а не 500). и в git добавляется тег с ссылкой на релиз. Этот скрипт пишеться один раз и потом подганяется по мере надобности. также этот скрипт следует дополнить, что бы он мог работать и с develop веткой. Теперь упрощаем жизнь. В хуки на гит сервере добавляем этот скрпит, что бы при пуше в девелом/мастер автоматом запускалось и, как результат, деплоилось на тестовый сервер/прод. Мердж в мастер обычным программистам запрещается. Теперь все выглядит так. Разработчик взял фичу, сделал под нее ветку, сделал. После мержда в девелом (или через мердж реквест) его код автоматом выливается на тестовое окружение. Если вдруг так случилось, что он все сломал - он должен фиксить. Если так не подходит, можно скрипт запускать на CI - один с самых популярных - jenkins. В результате деплой - это просто нажать одну кнопку. Q/A а почему не пулить прямо на боевом сервере? Если кто то уведет сервер, у него будет доступ к полной истории разработки. Это нужно? у меня никто не уведет историю гита, поэтому я буду пулить. уже было зачем сколько сложностей с скриптом? А представьте, что багу нашли среди ночи и нужно срочно фиксить. Наличие такого скрипта сильно упрощает жизнь. а можно без тестов? можно. Но лучше сделать какие-то минимальные.

Ответ 2



Давайте для начала разделим сущности. В процессе задействованы: Боевой сервер. Тестовый сервер. Сервер git Некоторый "агент деплоя". Сейчас вы развёртываете (деплоите) руками, хорошо бы делегировать эту задачу серверу непрерывной интеграции (continuous integration server, CI server). В простейшей версии это реализуется хуками на сервере git. Исходный код приложения Дистрибутив приложения — в вашем случае это минимизированные с помощью Gulp файлы. В данный момент задачи всех серверов выполняет один, а дистрибутив хранится вместе с кодом. Давайте тем не менее рассматривать их как отдельные и стремиться к низкой связности между ними (как в ООП между классами). Это даст нашей системе гибкость и гораздо большую масштабируемость. В частности, не будем полагаться на то, что что-то лежит рядом на одном диске или доступно по локальной сети. Что нужно сделать: Отделить дистрибутив от кода. При коммите запускаем gulp, получаем минимизированные файлы, (опционально) пакуем их в архив, перемещаем на сервер и там разворачиваем. Минимизированный код хранить не нужно, т.к. мы всегда можем его получить из исходного. Реализовать в коде сценариий развёртывания. Хотя бы предусмотреть место для действий, производимых на сервере: заполнение конфигов, перезагрузка сервисов и т.п. Как говорилось выше, это делается через git-hook и/или сервер CI. Автоматизировать реакцию на изменения в репозитории: при пуше в определённые ветки должно происходит развёртывание в определённом окружении. Поскольку сценарий развёртывания у нас теперь в коде, мы можем его. И в организации работы: Пересмотреть порядок релизов. Сейчас вы как будто бы релизите каждую опечатку и релизить может каждый. Стоит так же подумать о защите ветки master (в том числе от своих неосторожных действий). Работающий пример Предлагаю проводить эксперимент на примере GitLab.com (т.е. будем использовать облачный сервис). Выбор субъективный, вот аргументы за: Есть возможность создавать бесплатные приватные репозитории. (Т.е. ваш коммерческий код в относительной безопасности.) В комплекте есть GitLab CI, тесно интегрированный с репозиторием. Доступны (в том числе для приватных репозиториев) бесплатные раннеры — условно, виртуальные машины, на которых мы будем выполнять наши задачи. Аргумент против: если проект будет расти, когда-нибудь бесплатной лицензии не будет хватать для всех задач. Рабочий пример с конвейерами и логами выложен на GitLab.com. Основной файл, описывающий выполняемый сценарий, лежит в корневой папке проекта и называется .gitlab-ci.yml. image: alpine stages: - gulp - test - package - deploy cache: paths: - node_modules/ gulp: stage: gulp image: node:latest before_script: - npm install script: node_modules/.bin/gulp compress artifacts: paths: - dist expire_in: 10 minutes test: stage: test script: ls dist script: echo 'run tests here' package: stage: package script: tar -czvf packaged.tar.gz dist artifacts: paths: - packaged.tar.gz deploy_prod: stage: deploy script: echo 'deploy on master' only: - master deploy_test: stage: deploy script: echo 'deploy on develop' only: - develop Зависимости мы вынесем в конфиг для npm — package.json. В файле gulpfile.js описана задача compress, обеспечивающая минимизацию. Скриншот окна конвейеров CI: Результат работы: архив packaged.tar.gz, в нём dists/hello.js, в нём !function(t,e,i){t.title="New title"}(window,document);

воскресенье, 24 ноября 2019 г.

Настройка и развертывание проекта c помощью Git


Есть рабочий сайт, на этом же сервере есть гит-сервер (gitstack).

Как создать на сервере репозиторий с данным рабочим сайтом? 

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

Ясно что лучше иметь отдельно сервер для разработки, отдельно или автоматом деплоить все, но увы - такие условия как я изложил.
    


Ответы

Ответ 1



Развертывание напрямую, без удаленного репозитория и Git-сервера Требования: доступ к серверу по SSH на локальной машине установлен git, а также rsync или git-sync на сервере Git не нужен Что делать? Не обязательно устанавливать Git на сервере или копировать туда папку .git. Чтобы обновить сервер из git-репозитория, вы можете использовать вот такую команду: git ls-files -z | rsync --files-from - --copy-links -av0 . user@server.com:/var/www/project Эта команда копирует все файлы. rsync использует ssh (secure shell), который в любом случае установлен на сервере. Но при этом вам, вероятно, придется вручную удалить файлы, которые были удалены из проекта (т.е. не изменились, а перестали существовать в очередном коммите). Вместо rsync можно использовать утилиту git-sync, написанную Яном Бикингом. Как утверждает автор, она работает с Git быстрее, чем rsync. Почему это хороший способ? Чем меньше ПО установлено у вас на сервере, тем более он защищен и тем проще ег администрировать и документировать. Кстати, это еще и исключает небоходимость хранить на сервере полный Git-репозиторий со всей историей. Это только усложнило бы задачу по обеспечению безопасности сервера. (Написано на основе ответа @Christian, блога Ian Bicking) Развертывание через удаленный репозиторий на сервере. Этот способ сопряжен с риском утечки данных! Были получены исходники 3300 глобальных интернет-проектов Требования: доступ к серверу по SSH на сервере установлен Git. на сервере установлен Git-сервер, например Gitlab или Gitstack. на локальной машине установлен Git. Если вы начинаете с сервера с файлами и без репозитория На сервере в папке с проектом выполните: git init git add --all git commit -m'сообщение, описывающее текущее состояние проекта' И переходите к следующему пункту. Если вы начинаете с сервера с файлами и репозиторием Выберите на локальной машине папку, где будет располагаться проект. Выполните там: git clone -o production username@webserver:/path/to/htdocs/.git Если вы начинаете с локального репозитория Скопируйте свою локальную папку .git на сервер. В локальной копии откройте .git/config и добавьте ваш сервер как remote: [remote "production"] url = username@webserver:/path/to/htdocs/.git Общая часть На сервере замените .git/hooks/post-update на код, приведенный ниже в этом ответе. На сервере добавьте этому файлу права на запись: chmod +x .git/hooks/post-update Теперь, когда вы делаете git push с локального репозитория, репозиторий на сервере должен автоматически обновлять рабочую директорию: git push production Полезные ссылки по теме: http://toroid.org/ams/git-website-howto https://www.digitalocean.com/community/tutorials/how-to-set-up-automatic-deployment-with-git-with-a-vps post-update hook: Git-hook нашел на этом сайте. #!/bin/sh # # This hook does two things: # # 1. update the "info" files that allow the list of references to be # queries over dumb transports such as http # # 2. if this repository looks like it is a non-bare repository, and # the checked-out branch is pushed to, then update the working copy. # This makes "push" function somewhat similarly to darcs and bzr. # # To enable this hook, make this file executable by "chmod +x post-update". git-update-server-info is_bare=$(git-config --get --bool core.bare) if [ -z "$is_bare" ] then # for compatibility's sake, guess git_dir_full=$(cd $GIT_DIR; pwd) case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac fi update_wc() { ref=$1 echo "Push to checked out branch $ref" >&2 if [ ! -f $GIT_DIR/logs/HEAD ] then echo "E:push to non-bare repository requires a HEAD reflog" >&2 exit 1 fi if (cd $GIT_WORK_TREE; git-diff-files -q --exit-code >/dev/null) then wc_dirty=0 else echo "W:unstaged changes found in working copy" >&2 wc_dirty=1 desc="working copy" fi if git diff-index --cached HEAD@{1} >/dev/null then index_dirty=0 else echo "W:uncommitted, staged changes found" >&2 index_dirty=1 if [ -n "$desc" ] then desc="$desc and index" else desc="index" fi fi if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ] then new=$(git rev-parse HEAD) echo "W:stashing dirty $desc - see git-stash(1)" >&2 ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT git-update-ref --no-deref HEAD HEAD@{1} cd $GIT_WORK_TREE git stash save "dirty $desc before update to $new"; git-symbolic-ref HEAD "$ref" ) fi # eye candy - show the WC updates :) echo "Updating working copy" >&2 (cd $GIT_WORK_TREE git-diff-index -R --name-status HEAD >&2 git-reset --hard HEAD) } if [ "$is_bare" = "false" ] then active_branch=`git-symbolic-ref HEAD` export GIT_DIR=$(cd $GIT_DIR; pwd) GIT_WORK_TREE=${GIT_WORK_TREE-..} for ref do if [ "$ref" = "$active_branch" ] then update_wc $ref fi done fi Ответ написан на основе ответов с англоязычного StackOverflow. Дополнил, переработал, собрал в один ответ.

вторник, 27 ноября 2018 г.

Как временно “приглушить” monit на период развертывания сервиса через ansible?

Есть сервер на linux, на нем работает некий сервис myservice, за сервисом наблюдает monit. Сообщает на почту обо всех изменениях и при необходимости перезагружает сервис.
Есть ansible playbook, который переустанавливает сервис, конфигурирует и перезапускает. И monit тоже конфигурирует и перезапускает при необходимости. Работает это отлично, но плохо то, что при этом monit шлет пачку писем:
service instance пропал service instance появился service instance сменил PID monit перезагрузился
Можно в роли давать monit задачу приостанавливать мониторинг, но об этой задаче он тоже сообщает. Дважды.
- name: monit не наблюдает за myservice shell: monit unmonitor myservice
- name: monit наблюдает за myservice shell: monit monitor myservice
Можно перезапускать сервис из самого monit'a. Тогда письма приходят с менее угрожающими заголовками, вроде Action done myservice. Но всё равно одно или два письма + одно про релоад монита.
- name: Перезапуск myservice через monit shell: monit restart myservice
Я беспокоюсь о том, что это всё сработает как у мальчика, который кричал «Волки!». Все привыкнут, что с почты постоянно валится куча писем и что это нормальный процесс, волноваться не о чем. Поэтому хочу, чтобы штатные работы не приводили ни к каким тревогам вообще.
Можно ли это как-то реализовать на этом стеке технологий? Или я категорически неправ в своих опасениях?


Ответ

Решение
monit
config: /etc/monit/monitrc
set alert {{mail_recipient}} but not on { action, instance }
ansible:
Во всех командах параметр -I нужен, почему — смотри ниже.
В начале установки через monit останавливаем сервис, это считается action
- name: Остановка myservice через monit shell: monit -I stop myservice
Потом производим всю необходимую установку и настройку.
Убеждаемся, что сам monit запущен. Перезагружаем конфиги через сам monit, это событие типа instance
- name: Убедиться, что monit запущен service: name=monit state=started
- name: Перезагрузка конфигов monit shell: monit -I reload
Потом перезагружаем сервис, это считается action
- name: Перезапуск myservice через monit shell: monit -I restart myservice

Конфигурация monit
Получать только определенные события
set alert foo@bar only on { timeout, nonexist }
Получать все события кроме некоторых:
set alert foo@bar but not on { instance }
Подробнее про фильтрацию событий в monit:
https://mmonit.com/monit/documentation/monit.html#Setting-an-event-filter
Оставшиеся проблемы
monit "забывает" команды, отданные после перезагрузки — решено.
Разобрано в отдельном вопросе, здесь я просто добавляю -I к командам. C такой конфигурацией monit перестает сообщать об изменениях собственного instance не только на период развертывания, а вообще. То есть, если он был перезагружен вручную, либо если упал а потом был поднят при развертывании — то сообщения не будет.
Можно оставить только такой конфиг:
set alert {{mail_recipient}} but not on { action }
Но тогда при развертывании все равно будет одно сообщение на почту про sudo monit reload. Безуспешно пробовал такую схему, она не работает.
name: monit - приостановить мониторинг shell: monit unmonitor all name: monit - перезагрузка конфигов shell: monit reload name: monit - возобновить мониторинг shell: monit monitor all

понедельник, 22 октября 2018 г.

Как упростить схему деплоя?

Первый раз работаю в небольшой команде на внутрикорпоративном проекте. Изучить гит более-менее осилил. Теперь мучаюсь с деплоем. Суть такова:
Используем стандартную схему веток (master, develop, topic). Программируем и верстаем у себя на локалке. Есть боевой сервер. Он же и git-сервер. Он же и тестовый сервер :) Сервер содержит 2 веб-приложения. Первое мы пуллим из master-ветки — релиз готов, второе — из develop — тестируем, прежде чем мастер пулить.
Так вот, чтобы банально выложить малюсенькое изменение feature ветки в продакшн (или хотя бы в тест) мне приходится превозмогать рутину:
Переключиться с feature на develop, обновить ветку. Смержить feature, запушить develop Переключиться на master, обновить её Смержить develop, запушить master Подключиться к боевому серверу сделать пулл на develop-приложении Подключиться к боевому серверу сделать пулл на master-приложении ??? "А тут ещё букву поправьте, пожалуйста" goto 1
Это можно ли как-то всё упросить? Я уверен, что-то делаю неправильно.


Ответ

Пункты 1-2 - это очень упрощенный (где убрано к примеру тестирование) процесс, который делает каждый разработчик. Это его обычный цикл.
Пункт 3-4 - это релиз. Он не должен делать обычным разработчиком. Он делается релиз-менеджером (или ответственным человеком, назначенным на этом). Он не делается на каждый чих, а по процессу - раз в две недели или два раза в день
Пункты 5-8 делаются нажатием одной (максимум двух кнопок) или запуском одного скрипта. Он запускается на специальном билд сервере (для маленькой такой компании это может быть одна машина и для сборки, и для тестов и для репозитория). Сам скрипт сборки обычно делает следующее
git clone / git archive прогон скрипта, который фиксит конфиги, шаблоны (вы же не хотите показывать всем программистам пароли к базе на проде?) запуск скрипта, который процессит css, минимизирует js и тому подобное. прогон юнит тестов (они здесь, так как после минимизации могут быть проблемы:) ) архивирование и занесение архива в надежное место подключаемся к прод серверу(серверам) и заливаем туда архив. архив распаковывается на сервере в отдельную папку, правится конфиг nginx/apache или симлинка и сервер рестартует. (можно конечно остановить сервер, перетереть файлы и запустить сервер, но если что то пошло не так...). на проде проганяются минимальные тесты (к примеру, что главная страница возвращает 200 код, а не 500). и в git добавляется тег с ссылкой на релиз.
Этот скрипт пишеться один раз и потом подганяется по мере надобности.
также этот скрипт следует дополнить, что бы он мог работать и с develop веткой.
Теперь упрощаем жизнь. В хуки на гит сервере добавляем этот скрпит, что бы при пуше в девелом/мастер автоматом запускалось и, как результат, деплоилось на тестовый сервер/прод. Мердж в мастер обычным программистам запрещается.
Теперь все выглядит так. Разработчик взял фичу, сделал под нее ветку, сделал. После мержда в девелом (или через мердж реквест) его код автоматом выливается на тестовое окружение. Если вдруг так случилось, что он все сломал - он должен фиксить.
Если так не подходит, можно скрипт запускать на CI - один с самых популярных - jenkins. В результате деплой - это просто нажать одну кнопку.
Q/A
а почему не пулить прямо на боевом сервере? Если кто то уведет сервер, у него будет доступ к полной истории разработки. Это нужно? у меня никто не уведет историю гита, поэтому я буду пулить. уже было зачем сколько сложностей с скриптом? А представьте, что багу нашли среди ночи и нужно срочно фиксить. Наличие такого скрипта сильно упрощает жизнь. а можно без тестов? можно. Но лучше сделать какие-то минимальные.

понедельник, 1 октября 2018 г.

Настройка и развертывание проекта c помощью Git

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


Ответ

Развертывание напрямую, без удаленного репозитория и Git-сервера
Требования:
доступ к серверу по SSH на локальной машине установлен git, а также rsync или git-sync на сервере Git не нужен
Что делать?
Не обязательно устанавливать Git на сервере или копировать туда папку .git. Чтобы обновить сервер из git-репозитория, вы можете использовать вот такую команду:
git ls-files -z | rsync --files-from - --copy-links -av0 . user@server.com:/var/www/project
Эта команда копирует все файлы. rsync использует ssh (secure shell), который в любом случае установлен на сервере.
Но при этом вам, вероятно, придется вручную удалить файлы, которые были удалены из проекта (т.е. не изменились, а перестали существовать в очередном коммите).
Вместо rsync можно использовать утилиту git-sync, написанную Яном Бикингом. Как утверждает автор, она работает с Git быстрее, чем rsync.
Почему это хороший способ?
Чем меньше ПО установлено у вас на сервере, тем более он защищен и тем проще его администрировать и документировать. Кстати, это еще и исключает небоходимость хранить на сервере полный Git-репозиторий со всей историей. Это только усложнило бы задачу по обеспечению безопасности сервера.
(Написано на основе ответа @Christian, блога Ian Bicking)
Развертывание через удаленный репозиторий на сервере.
Этот способ сопряжен с риском утечки данных!
Были получены исходники 3300 глобальных интернет-проектов
Требования:
доступ к серверу по SSH на сервере установлен Git. на сервере установлен Git-сервер, например Gitlab или Gitstack на локальной машине установлен Git.
Если вы начинаете с сервера с файлами и без репозитория
На сервере в папке с проектом выполните:
git init git add --all git commit -m'сообщение, описывающее текущее состояние проекта'
И переходите к следующему пункту.
Если вы начинаете с сервера с файлами и репозиторием
Выберите на локальной машине папку, где будет располагаться проект. Выполните там:
git clone -o production username@webserver:/path/to/htdocs/.git
Если вы начинаете с локального репозитория
Скопируйте свою локальную папку .git на сервер. В локальной копии откройте .git/config и добавьте ваш сервер как remote
[remote "production"] url = username@webserver:/path/to/htdocs/.git
Общая часть
На сервере замените .git/hooks/post-update на код, приведенный ниже в этом ответе. На сервере добавьте этому файлу права на запись:
chmod +x .git/hooks/post-update Теперь, когда вы делаете git push с локального репозитория, репозиторий на сервере должен автоматически обновлять рабочую директорию:
git push production
Полезные ссылки по теме:
http://toroid.org/ams/git-website-howto https://www.digitalocean.com/community/tutorials/how-to-set-up-automatic-deployment-with-git-with-a-vps
post-update hook:
Git-hook нашел на этом сайте
#!/bin/sh # # This hook does two things: # # 1. update the "info" files that allow the list of references to be # queries over dumb transports such as http # # 2. if this repository looks like it is a non-bare repository, and # the checked-out branch is pushed to, then update the working copy. # This makes "push" function somewhat similarly to darcs and bzr. # # To enable this hook, make this file executable by "chmod +x post-update". git-update-server-info is_bare=$(git-config --get --bool core.bare) if [ -z "$is_bare" ] then # for compatibility's sake, guess git_dir_full=$(cd $GIT_DIR; pwd) case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac fi update_wc() { ref=$1 echo "Push to checked out branch $ref" >&2 if [ ! -f $GIT_DIR/logs/HEAD ] then echo "E:push to non-bare repository requires a HEAD reflog" >&2 exit 1 fi if (cd $GIT_WORK_TREE; git-diff-files -q --exit-code >/dev/null) then wc_dirty=0 else echo "W:unstaged changes found in working copy" >&2 wc_dirty=1 desc="working copy" fi if git diff-index --cached HEAD@{1} >/dev/null then index_dirty=0 else echo "W:uncommitted, staged changes found" >&2 index_dirty=1 if [ -n "$desc" ] then desc="$desc and index" else desc="index" fi fi if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ] then new=$(git rev-parse HEAD) echo "W:stashing dirty $desc - see git-stash(1)" >&2 ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT git-update-ref --no-deref HEAD HEAD@{1} cd $GIT_WORK_TREE git stash save "dirty $desc before update to $new"; git-symbolic-ref HEAD "$ref" ) fi # eye candy - show the WC updates :) echo "Updating working copy" >&2 (cd $GIT_WORK_TREE git-diff-index -R --name-status HEAD >&2 git-reset --hard HEAD) } if [ "$is_bare" = "false" ] then active_branch=`git-symbolic-ref HEAD` export GIT_DIR=$(cd $GIT_DIR; pwd) GIT_WORK_TREE=${GIT_WORK_TREE-..} for ref do if [ "$ref" = "$active_branch" ] then update_wc $ref fi done fi
Ответ написан на основе ответов с англоязычного StackOverflow. Дополнил, переработал, собрал в один ответ.

Настройка и развертывание проекта c помощью Git

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


Ответ

Развертывание напрямую, без удаленного репозитория и Git-сервера
Требования:
доступ к серверу по SSH на локальной машине установлен git, а также rsync или git-sync на сервере Git не нужен
Что делать?
Не обязательно устанавливать Git на сервере или копировать туда папку .git. Чтобы обновить сервер из git-репозитория, вы можете использовать вот такую команду:
git ls-files -z | rsync --files-from - --copy-links -av0 . user@server.com:/var/www/project
Эта команда копирует все файлы. rsync использует ssh (secure shell), который в любом случае установлен на сервере.
Но при этом вам, вероятно, придется вручную удалить файлы, которые были удалены из проекта (т.е. не изменились, а перестали существовать в очередном коммите).
Вместо rsync можно использовать утилиту git-sync, написанную Яном Бикингом. Как утверждает автор, она работает с Git быстрее, чем rsync.
Почему это хороший способ?
Чем меньше ПО установлено у вас на сервере, тем более он защищен и тем проще его администрировать и документировать. Кстати, это еще и исключает небоходимость хранить на сервере полный Git-репозиторий со всей историей. Это только усложнило бы задачу по обеспечению безопасности сервера.
(Написано на основе ответа @Christian, блога Ian Bicking)
Развертывание через удаленный репозиторий на сервере.
Этот способ сопряжен с риском утечки данных!
Были получены исходники 3300 глобальных интернет-проектов
Требования:
доступ к серверу по SSH на сервере установлен Git. на сервере установлен Git-сервер, например Gitlab или Gitstack на локальной машине установлен Git.
Если вы начинаете с сервера с файлами и без репозитория
На сервере в папке с проектом выполните:
git init git add --all git commit -m'сообщение, описывающее текущее состояние проекта'
И переходите к следующему пункту.
Если вы начинаете с сервера с файлами и репозиторием
Выберите на локальной машине папку, где будет располагаться проект. Выполните там:
git clone -o production username@webserver:/path/to/htdocs/.git
Если вы начинаете с локального репозитория
Скопируйте свою локальную папку .git на сервер. В локальной копии откройте .git/config и добавьте ваш сервер как remote
[remote "production"] url = username@webserver:/path/to/htdocs/.git
Общая часть
На сервере замените .git/hooks/post-update на код, приведенный ниже в этом ответе. На сервере добавьте этому файлу права на запись:
chmod +x .git/hooks/post-update Теперь, когда вы делаете git push с локального репозитория, репозиторий на сервере должен автоматически обновлять рабочую директорию:
git push production
Полезные ссылки по теме:
http://toroid.org/ams/git-website-howto https://www.digitalocean.com/community/tutorials/how-to-set-up-automatic-deployment-with-git-with-a-vps
post-update hook:
Git-hook нашел на этом сайте
#!/bin/sh # # This hook does two things: # # 1. update the "info" files that allow the list of references to be # queries over dumb transports such as http # # 2. if this repository looks like it is a non-bare repository, and # the checked-out branch is pushed to, then update the working copy. # This makes "push" function somewhat similarly to darcs and bzr. # # To enable this hook, make this file executable by "chmod +x post-update". git-update-server-info is_bare=$(git-config --get --bool core.bare) if [ -z "$is_bare" ] then # for compatibility's sake, guess git_dir_full=$(cd $GIT_DIR; pwd) case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac fi update_wc() { ref=$1 echo "Push to checked out branch $ref" >&2 if [ ! -f $GIT_DIR/logs/HEAD ] then echo "E:push to non-bare repository requires a HEAD reflog" >&2 exit 1 fi if (cd $GIT_WORK_TREE; git-diff-files -q --exit-code >/dev/null) then wc_dirty=0 else echo "W:unstaged changes found in working copy" >&2 wc_dirty=1 desc="working copy" fi if git diff-index --cached HEAD@{1} >/dev/null then index_dirty=0 else echo "W:uncommitted, staged changes found" >&2 index_dirty=1 if [ -n "$desc" ] then desc="$desc and index" else desc="index" fi fi if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ] then new=$(git rev-parse HEAD) echo "W:stashing dirty $desc - see git-stash(1)" >&2 ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT git-update-ref --no-deref HEAD HEAD@{1} cd $GIT_WORK_TREE git stash save "dirty $desc before update to $new"; git-symbolic-ref HEAD "$ref" ) fi # eye candy - show the WC updates :) echo "Updating working copy" >&2 (cd $GIT_WORK_TREE git-diff-index -R --name-status HEAD >&2 git-reset --hard HEAD) } if [ "$is_bare" = "false" ] then active_branch=`git-symbolic-ref HEAD` export GIT_DIR=$(cd $GIT_DIR; pwd) GIT_WORK_TREE=${GIT_WORK_TREE-..} for ref do if [ "$ref" = "$active_branch" ] then update_wc $ref fi done fi
Ответ написан на основе ответов с англоязычного StackOverflow. Дополнил, переработал, собрал в один ответ.