- PVSM.RU - https://www.pvsm.ru -
Добрый день, уважаемый галактический сенат! На связи снова Денис Мельский, и сегодня на повестке дня — определение теоретического минимума познания *nix систем для юного падавана web-мастерства.
Хотелось бы начать с того, что все мы прекрасно знаем: на 67.4 % наши любимые интернеты крутятся на *nix-based-серверах, а в жизни среднестатистического web-разработчика в вакууме — так и на все 90 %.
Для любителей пруфов — welcome [1].
Т. ч. в нашем ремесле без знания *nix-систем никак. Давайте проведем экскурс в мир *nix и поймем, какими знаниями должен обладать юный падаван.
Предлагаю рассмотреть три юниорских степени познания дзена управлением шайтан-машиной ака *nix-сервак на примере всеми любимой ubuntu.
Начнем с самых азов — забудьте про GUI, только консоль, только хардкор ^_^!
Несколько красивых консолей в xmonad для повышения мотивации.
Наше приключение начинаем с того, что надо добраться до консоли (в случае SSH-подключения мы там будем сразу). Кстати, если вы windows user, вам поможет волшебная программка putty [2].
Если же вы уже в линуксе и вы его поставили, верю, что сможете найти там консоль и как в нее попасть. Если же нет, вот мануал [3] на примере ubuntu с самыми популярными DWM. Там же найдете описание базовых команд консоли. Рассмотрим сей список поподробнее и немного сгруппируем.
Давайте посмотрим на структуру файловой системы.
Да, не пугайтесь, привычных C: и D: тут нету, всё идет от корня (/).
/ | Корневая директория, содержащая всю файловую иерархию. |
/bin/ | Основные системные утилиты, необходимые и в однопользовательском режиме, и при обычной работе всем пользователям (cat, ls, cp). |
/boot/ | Загрузочные файлы (в том числе, файлы загрузчика, ядро и т. д.). Часто выносится в отдельный раздел. |
/dev/ | Основные файлы устройств системы (например, физические устройства: sata-винчестеры /dev/sda, видеокамеры или TV-тюнеры /dev/video или псевдоустройства, например, «черные дыры» /dev/null, /dev/zero). |
/etc/ | Общесистемные конфигурационные файлы и файлы конфигурации установленных программ (имя происходит от et cetera). |
/home/ | Содержит домашние директории пользователей, которые, в свою очередь, содержат персональные настройки и данные пользователя. Часто размещается на отдельном разделе. |
/lib/ | Основные библиотеки, необходимые для работы программ из /bin/ и /sbin/. |
/media/ | Точки монтирования для сменных носителей (CD-ROM, DVD-ROM, flash-диски). |
/opt/ | Дополнительное ПО. |
/proc/ | Виртуальная файловая система, представляющая состояние ядра операционной системы и запущенных процессов в виде каталогов файлов. |
/root/ | Домашняя директория пользователя root. |
/sbin/ | Основные системные программы для администрирования и настройки системы, например, init, iptables, ifconfig. |
/tmp/ | Временные файлы (см. также /var/tmp). |
/usr/ | Вторичная иерархия для данных пользователя; содержит большинство пользовательских приложений и утилит, используемых в многопользовательском режиме. Может быть смонтирована по сети только для чтения и быть общей для нескольких машин. |
/var/ | Изменяемые файлы: файлы регистрации (log-файлы), временные почтовые файлы, файлы спулеров. |
/var/cache/ | Данные кэша приложений. Сюда скачиваются пакеты перед установкой в систему, здесь же они какое-то время хранятся. |
/var/lib/ | Информация о состоянии. Постоянные данные, изменяемые программами в процессе работы (базы данных, метаданные пакетного менеджера и т. п.). |
/var/log/ | Различные файлы регистрации (log-файлы). |
/var/www/ | Директория веб-сервера Apache, всё, что находится внутри, транслируется им в интернет (конфигурация по умолчанию) |
Теперь мы узнали, как выглядит файловая система *nix.
Потом рекомендую узнать, как перемещаться в пространстве (cd — www.linfo.org/cd.html [4]), создавать файлы (touch — www.linfo.org/touch.html [5]) редактировать и удалять тоже (понять шутку про sudo rm -rf / — настойчиво рекомендую загуглить тем, кто не в курсе), познакомиться, как работает консольный текстовый редактор (например, Nano) — да-да, не надо пугать новичков Vim и Emacs. Еще есть симпатичный вариант mcedit.
Nano
MCEdit
Чип и Дейл спешат на помощь! В любой непонятной ситуации вводите man %commandName%, и восхитительная утилита man в *nix-системах вам расскажет как работает та или иная команда (программа) в bash.
Если вы потерялись в файловой системе, поможет команда pwd.
Теперь давайте обозначим еще некоторые особенности этого семейства OS.
*nix-системы отличаются регистрозависимостью т. е. file.txt и File.txt — разные файлы. И директории /uploads и /Uploads — тоже разные директории.
Еще несколько важных отличий:
В PHP-разработке для ликвидации этих проблем кроссплатформености рекомендуется использовать PHP_EOL для новой строки в консоли и DIRECTORY_SEPARATOR для правильных слешей.
В контексте обсуждения файловой системы и фич linux давайте рассмотрим интересную фичу — симлинки (symlinks). Если объяснить по-простому — это ярлыки, как в всем известной windows, только тут ярлык может быть и на другой сервер, и на директорию, и на файл. Отличие от ярлыков в windows в том, что тут ярлыки используют не только на рабочем столе, а во всей файловой системе. По поводу этого есть хорошая статья на вики en.wikipedia.org/wiki/Symbolic_link [7] и немного синтаксиса с вики debian вдогонку: wiki.debian.org/SymLink [8].
Почему многие developer-ы любят *nix-системы? Да потому что они стандартизированы системой стандарта POSIX, что их все роднит и помогает спокойно мигрировать из одной стандартизированной OS в другую (и разработчику, и юзеру. Тема раскрыта тут: en.wikipedia.org/wiki/POSIX [9].
Продолжаем знакомство.
Основное отличие *nix-систем — их многопользовательский подход. Из этого следует логический вывод: если есть много пользователей, надо разграничивать их сферы влияния. Один из основных инструментов для этого — права к файлам и директориям.
Обозначения прав идут в буквенном или цифровом формате.
Увидеть права мы можем через команды ls -l или ls -la, а поменять — через chmod.
Нашел потрясающую картинку, которая объясняет всю суть происходящего.
Добавлю, что в жизни веб-разработчика всегда нужно помнить о правах в linux, поскольку имеет место обыденная ситуация: разрабатывали под windows, задеплоили и внезапно (!) ничего не работает. В целом ничего страшного в них нету, но keep in mind.
P. S. Советую хорошо разобраться в этом моменте, поскольку ставить 777 на весь проект тоже не очень секьюрно.
Для пользователей системы существует режим стандартных правил для создаваемых ими файлов — umask. От него зависит, с какими правами будут создаваться файлы этого пользователя по умолчанию.
Почитать здесь: ru.wikipedia.org/wiki/Umask [10].
Я вскользь упомянул о наличии пользователей и групп в *nix-системах, но еще есть административный пользователь — root.
Root-юзер помогает вам делать многое: инсталлить софт, маунтить (https://help.ubuntu.com/community/Mount) разделы, разруливать права на файлы и папки где вашего обычного юзера не хватает, и т. п.
Для этого есть волшебная команда sudo. Более подробно предлагаю ознакомиться здесь: help.ubuntu.ru/wiki/ [11].
Под рутом надо быть очень аккуратными. Особенно на лайв-серверах. Особенно удаляя что-то через консоль.
Раз уж мы вспомнили о лайв-серверах, у них бывает такое свойство — заканчивается память.
Сначала проверяем, что у нас с ОЗУ, для этого подойдет top/htop.
Давайте также вспомним замечательную тулзу — ps. Она выводит отчет о работающих процессах. Удобна еще и несколькими триками:
Для проверки, сколько свободного места у нас на харде, есть команды: df -h и df –k.
Если проблема в ОЗУ, смотрим, что у нас потребляет больше, чем надо, и делаем kill, или же, если это нужные процессы, — думаем дальше :).
Если же заканчиваются ресурсы харда и нечего удалить, на помощь приходят архиваторы. Основной архиватор в мире linux — tar. Вот небольшой гайд по сабжу, которого в повседневной жизни вам должно хватить с головой: help.ubuntu.ru/wiki/tar [12].
Стоит добавить, что в консоли есть варианты работы с несколькими программами одновременно — утилита GNU Screen: help.ubuntu.ru/wiki/screen [13].
В целом на этом можно и закончить первую степень посвящения, но обрадую немного тех, кто очень боится консоли: есть консольный 2-панельный классический файловый менеджер — Midnight commander.
Продолжим рубрикой «Что делать не надо» :).
Это dotfiles — спрятанные файлы, просто по ls их не видно, можно увидеть через ls –la. Зачастую это системные файлы или файлы программ (иногда — настройки). И тут тоже вики хорошо раскрывает тему: en.wikipedia.org/wiki/Hidden_file_and_hidden_directory [14].
Первый юниорский нам поможет сделать что-то, но для повседневных задач web-developer’а этого мало, так что давайте пойдем дальше осваивать уровень, которого нам хватит для резолва ежедневных задач.
Первое, о чём надо упомянуть на этом уровне — пакетный менеджер aptitude (разбираем на примере ubuntu, да и в целом debian-based systems).
С его помощью можем устанавливать и удалять программы в й системе, подробнее рекомендую почитать, как говорится, на сайте производителя: help.ubuntu.ru/wiki/apt [15].
Следующая повседневная задача — установка lamp (linux apache php mysql)-сервера.
Вы не поверите, но после установки сервера на Windows в Ubuntu это делать просто и приятно, буквально в несколько команд: help.ubuntu.com/community/ApacheMySQLPHP [16]
Конечно же, нам пригодятся Virtual Hosts. Файл хостов находится по адресу /etc/hosts, а хосты надо редактировать под рутом.
Пришло время упомянуть базовые команды Apache.
Включаем модули в apache, в том числе, модуль PHP (если ставим руками) — a2enmod %moduleName%.
Рестарт сервера — sudo service apache2 restart.
Вернемся к хостам. В apache, да и в nginx система хостов не очень сложная, но, как показывает практика, лучше рассказать, чтобы не видеть потом огромные и ужасные httpd.conf/nginx.conf.
Хосты, которые настроены и существуют (но не факт, что включены!) лежат отдельными файликами в папке /etc/apache2/sites-available. А хосты, которые используются и активны в данный момент, лежат симлинками в папке /etc/apache2/sites-enabled.
In real life выглядит все так: мы создаем файл конфига для нового хоста в sites-available, потом командой a2ensite %hostName% apache создает симлинк в папке sites-enabled, тем самым активируя хост. Обратная процедура — a2dissite.
Когда вы делаете это руками или просто пишете в файл основнового конфига, где-то плачет один котик, ну, или собачка — кому кого больше жаль :).
Ещё распространенная задача — поднять https. Хороший мануал здесь:
help.ubuntu.ru/wiki/apache_%D0%B8_https [17].
Картинка, обьясняющая суть того, зачем нам https.
Если вас всё ещё терзает вопрос зачем эта вся секьюрность, советую почитать на тему секьюрности для разработчиков хороший мануал: www.owasp.org/index.php/PHP_Security_Cheat_Sheet [18] — тут на примере PHP, но многое актуально для всех Web разработчиков.
Также при работе с lamp старайтесь закрывать использование exec (выполнение команд в консоли OS через php) www.php.net/manual/ru/function.exec.php [19].
На уровне php это потенциальный пробел в вашей защите.
Добавлю часто встречающуюся задачу — закрытие сервера для незалогиненных пользователей методами веб-сервера, как на этом скрине.
Сделать так очень просто через htpasswd, вот пример: doc.norang.ca/apache-basic-auth.html [20].
Пришло время упомянуть о базах данных. В нашем юниорском забеге будем рассматривать MySql. В целом по вопросам Database Administration написано очень много книг и очень многое появляется с опытом, но некоторые базовые вещи просто необходимы.
Первое — конфиг живет по адресу /etc/mysql/my.cnf, заходить в гости, как обычно, под рутом.
Перезапустить «моську» можно командой sudo service mysql restart.
Если вы что-то не то сделали с правами своего рута или просто потеряли пароль рута от mysql, сбросить его и задать новый можно командой sudo dpkg-reconfigure mysql-server-5.5 (или 5.6), в общем, подставите нужную версию :).
Хоббит SQL-дампы — туда и обратно.
Для бекапа базы в sql-файл используется прекрасная команда mysqldump со следующим синтаксисом:
mysqldump —opt -u [uname] -p[pass] [dbname] > [backupfile.sql]
[uname] Имя юзера
[pass] Пароль (Будьте внимательны между параметром p и паролем нет пробела)
[dbname] Название нашей базы
[backupfile.sql] Как мы называем файл дампа (можно так же указать путь к нему если вы не в той папке где хотите создать его)
[--opt] Дополнительные опции
Пример: mysqldump -u root -p Tutorials > tut_backup.sql
А если база большая и VPN-коннект не самый быстрый, можно сразу сжать в архив наш дамп следующей командой:
mysqldump -u [uname] -p[pass] [dbname] | gzip -9 > [backupfile.sql.gz]
Теперь давайте разберем накатку базы (условие: базы не существует, накатка с нуля).
Основной синтаксис будет такой:
mysql -u [uname] -p[pass] [db_to_restore] < [backupfile.sql]
Следуя нашему примеру, получаем что-то в духе:
mysql -u root -p Tutorials < tut_backup.sql
А если мы таки запаковались в архив, будет так:
gunzip < [backupfile.sql.gz] | mysql -u [uname] -p[pass] [dbname]
Если накатываем базу не с нуля, а она уже создана, есть другая команда:
mysqlimport -u [uname] -p[pass] [dbname] [backupfile.sql]
С архивом по аналогии.
Эту прекрасную шпаргалку по дампам взял отсюда: webcheatsheet.com/sql/mysql_backup_restore.php [21].
Следующий важный момент в MySQL — права Grants. «Моська» у нас многопользовательская, если есть много пользователей, значит, права свои у них будут — life is cruel :). Советую о них почитать. Самая распространенная задача — открыть юзеру вход не с локалхоста Она решается следующим образом:
Удаляем строку bind-address 127.0.0.1 из главного конфига.
Потом выполняем следующие команды:
~# mysql -u root mysql -p
mysql> GRANT ALL PRIVILEGES ON database.* TO username@»%» IDENTIFIED BY ‘password’ WITH GRANT OPTION;
mysql> exit;
~# mysqladmin -u root -p flush-privileges
Здесь database — база данных, к которой назначаем права пользователю username с паролем password, а % указывает на то, что пользователь может прийти не только с локалхоста, а откуда угодно.
Эти команды на респекте собрал отсюда: saradmin.ru/?p=792 [22].
Node JS мы также можем установить в две команды “sudo apt-get install nodejs” “sudo apt-get install npm”.
Node-проекты заводить обычно легко, что-то в духе node server.js
Хочу поделиться интересной тулзой nodemon — она дает нам намного больше возможностей в области девелопмента на nodeJS, т. к. следит за изменениями в файлах проекта и перезапускает сервер автоматически:
nodemon.io/ [23]
Далее рекомендую ознакомиться с работой в консоли самых популярных в мире web development VCS — git и svn. Мануалов по ним очень много разных и хороших, думаю, подберете на свой вкус ;).
По теме VCS может понадобится мануал по генерации SSH-ключей для Git: help.github.com/articles/generating-ssh-keys [24].
Поделюсь интересным триком: если вам нужен live-вывод изменяющихся файлов в консоль (зачастую логи) — используйте команду tail –f, например, (tail -f /var/log/apache2/error.log).
Вот мы и подобрались к 3-му юниорскому! Довольно неплохой уровень, после которого уже идет хардкор, но тут еще ничего страшного тоже нет, всё достаточно интересно и весело.
Начинается опыт реального подъема серверов с фулстеком (lamp + ftp(s) + ssh) по ситуации, с прикруткой CI-систем, также интересен опыт подъёма хостинг-систем типа Virtualmin / WebMin.
В реальной эксплуатации не рекомендуется оставлять чистый ftp-сервер, лучше использовать SFTP (ftp over ssh) для секьюрности.
help.ubuntu.ru/wiki/webmin [25]
Интересен опыт с nginx вместо apache — отличный мануал можно найти тут: help.ubuntu.ru/wiki/nginx-phpfpm [26].
Также дополню хорошей онлайн-тулзой которая трансформирует rewrite-правила из apache в формат nginx: winginx.com/ru/htaccess [27].
Еще на этом уровне не нужно бояться BASH-скриптинга и знать, что такое sed и grep. Основы рекомендую почитать тут:
help.ubuntu.com/community/Beginners/BashScripting [28]
Хороший левел — знание vim или emacs. Очень холиварная тема, но не упомянуть нельзя.
Если временами вы очень скучаете по некоторым программам из windows, или у вас есть специфичный софт, который все-таки нужен и аналог никак не можете найти (что же такое страшное вам нужно?!), есть wine — wine is not an emulator.
IE В Ubuntu («работает» еще веселее, чем в нативной среде обитания).
Это действительно не эмулятор windows, а набор библиотек, чтобы заводить виндовые програмы под никсами. Есть база данных, какие программы и даже игры поддерживает wine — appdb.winehq.org/ [29].
Давайте затронем сетевую тему, первым в гостем нашей студии станет netstat (network statistics), встречайте! Тулза поможет нам посмотреть статистику сетевой активности, открытые порты, наши сетевые интерфейсы и т. д.
Базовая информация:
en.wikipedia.org/wiki/Netstat [30]
Примеры использования: putty.org.ru/articles/netstat-linux-examples.html [31].
Спасибо, netstat.
Следующий наш гость — Iptables, встречайте!
IPtables — стандартный интерфейс управления работой брандмауэра.
Базовая информация: en.wikipedia.org/wiki/Iptables [32]
Спасибо, Iptables!
И в заключение сетевой темы давайте позовем нашего хедлайнера — nmap. Поприветсвуем гостя nmap!
Очень известная утилита в области сетевой безопасности, видеть ее мы могли в десятках фильмов ;).
nmap.org/movies/ [33]
Базовая информация: en.wikipedia.org/wiki/Nmap#Bibliography [34].
Примеры использования: habrahabr.ru/post/88064/ [35].
Спасибо nmap за столь увлекательную историю и счастливое детство.
Предлагаю перейти на немного advanced level MySQL-тюнинга — PIMP MY DB.
В живых проектах очень важно держать MySQL в боевом состоянии, настроенным на максимальную стабильность и производительность, в противном случае получаем очень неприятный bottleneck.
DB Tuning можно условно разделить на две части:
Оптимизация структуры базы данных (нормализация/денормализация, foreign keys, indexes и т. д.).
Оптимизация настроек сервера DB.
Про оптимизацию структуры базы данных написано немало гайдов и мануалов, и серебряной пули тут не существует. Всегда смотрим на конкретный проект и индивидуальные проблемы. Explain в помощь :).
Советую почитать:
ruhighload.com/post/ [36] ruhighload.com/index.php/2009/07/28/ [37] habrahabr.ru/post/108418/ [38]
В вопросе тюнинга и оптимизации настроек DB очень преуспела компания Percona — MySQL-форк. Рекомендую познакомиться с ними поближе.
Из базового набора для тюнинга у них есть тулкит и визард настройки вашего сервера.
www.percona.com/software/percona-toolkit [39]
tools.percona.com/wizard [40]
Также известная тулза — mysqltuner (http://mysqltuner.com/).
Для тестирования нагрузки на MySQL есть интересная тулза sysbench. Почитать про нее можно тут: ruhighload.com/index.php/2010/03/05/sysbench-testiruem-proizvoditelnost-mysql/ [41].
Добавим в наше приключение немного стильных, модных и молодежных технологий — CI.
Wiki: Непрерывная интеграция (англ. Continuous Integration) — практика разработки ПО, которая заключается в выполнении частых автоматизированных сборок проекта для скорейшего выявления и решения интеграционных проблем.
На практике это очень удобный софт, позволяющий собирать билды, прогонять все виды тестов, делать минификацию js/css, следить за качеством кода, деплоить, итп.
Самые популярные — Jenkins, Travis, TeamCity.
en.wikipedia.org/wiki/Jenkins_ [42](software)
en.wikipedia.org/wiki/Travis_CI [43]
ru.wikipedia.org/wiki/TeamCity [44]
P. S. Клевая тулза Guake —выезжающая консолько в стиле quake.
Автор: DataArt
Источник [45]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/tutorial/74857
Ссылки в тексте:
[1] welcome: http://en.wikipedia.org/wiki/Usage_share_of_operating_systems
[2] putty: http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
[3] вот мануал: https://help.ubuntu.com/community/UsingTheTerminal
[4] www.linfo.org/cd.html: http://www.linfo.org/cd.html
[5] www.linfo.org/touch.html: http://www.linfo.org/touch.html
[6] en.wikipedia.org/wiki/Newline: http://en.wikipedia.org/wiki/Newline
[7] en.wikipedia.org/wiki/Symbolic_link: http://en.wikipedia.org/wiki/Symbolic_link
[8] wiki.debian.org/SymLink: https://wiki.debian.org/SymLink
[9] en.wikipedia.org/wiki/POSIX: http://en.wikipedia.org/wiki/POSIX
[10] ru.wikipedia.org/wiki/Umask: https://ru.wikipedia.org/wiki/Umask
[11] help.ubuntu.ru/wiki/: http://help.ubuntu.ru/wiki/
[12] help.ubuntu.ru/wiki/tar: http://help.ubuntu.ru/wiki/tar
[13] help.ubuntu.ru/wiki/screen: http://help.ubuntu.ru/wiki/screen
[14] en.wikipedia.org/wiki/Hidden_file_and_hidden_directory: http://en.wikipedia.org/wiki/Hidden_file_and_hidden_directory
[15] help.ubuntu.ru/wiki/apt: http://help.ubuntu.ru/wiki/apt
[16] help.ubuntu.com/community/ApacheMySQLPHP: https://help.ubuntu.com/community/ApacheMySQLPHP
[17] help.ubuntu.ru/wiki/apache_%D0%B8_https: http://help.ubuntu.ru/wiki/apache_%D0%B8_https
[18] www.owasp.org/index.php/PHP_Security_Cheat_Sheet: https://www.owasp.org/index.php/PHP_Security_Cheat_Sheet
[19] www.php.net/manual/ru/function.exec.php: http://www.php.net/manual/ru/function.exec.php
[20] doc.norang.ca/apache-basic-auth.html: http://doc.norang.ca/apache-basic-auth.html
[21] webcheatsheet.com/sql/mysql_backup_restore.php: http://webcheatsheet.com/sql/mysql_backup_restore.php
[22] saradmin.ru/?p=792: http://saradmin.ru/?p=792
[23] nodemon.io/: http://nodemon.io/
[24] help.github.com/articles/generating-ssh-keys: https://help.github.com/articles/generating-ssh-keys
[25] help.ubuntu.ru/wiki/webmin: http://help.ubuntu.ru/wiki/webmin
[26] help.ubuntu.ru/wiki/nginx-phpfpm: http://help.ubuntu.ru/wiki/nginx-phpfpm
[27] winginx.com/ru/htaccess: http://winginx.com/ru/htaccess
[28] help.ubuntu.com/community/Beginners/BashScripting: https://help.ubuntu.com/community/Beginners/BashScripting
[29] appdb.winehq.org/: http://appdb.winehq.org/
[30] en.wikipedia.org/wiki/Netstat: http://en.wikipedia.org/wiki/Netstat
[31] putty.org.ru/articles/netstat-linux-examples.html: http://putty.org.ru/articles/netstat-linux-examples.html
[32] en.wikipedia.org/wiki/Iptables: http://en.wikipedia.org/wiki/Iptables
[33] nmap.org/movies/: http://nmap.org/movies/
[34] en.wikipedia.org/wiki/Nmap#Bibliography: http://en.wikipedia.org/wiki/Nmap#Bibliography
[35] habrahabr.ru/post/88064/: http://habrahabr.ru/post/88064/
[36] ruhighload.com/post/: http://ruhighload.com/post/
[37] ruhighload.com/index.php/2009/07/28/: http://ruhighload.com/index.php/2009/07/28/
[38] habrahabr.ru/post/108418/: http://habrahabr.ru/post/108418/
[39] www.percona.com/software/percona-toolkit: http://www.percona.com/software/percona-toolkit
[40] tools.percona.com/wizard: https://tools.percona.com/wizard
[41] ruhighload.com/index.php/2010/03/05/sysbench-testiruem-proizvoditelnost-mysql/: http://ruhighload.com/index.php/2010/03/05/sysbench-testiruem-proizvoditelnost-mysql/
[42] en.wikipedia.org/wiki/Jenkins_: http://en.wikipedia.org/wiki/Jenkins_
[43] en.wikipedia.org/wiki/Travis_CI: http://en.wikipedia.org/wiki/Travis_CI
[44] ru.wikipedia.org/wiki/TeamCity: https://ru.wikipedia.org/wiki/TeamCity
[45] Источник: http://habrahabr.ru/post/243563/
Нажмите здесь для печати.