Под катом я расскажу как на коленке набросал скрипт keep-alive подключения с Automatic Upload проекта.
В тексте будет много кода и мало комметариев. Связано это с тем что комментировать там и нечего: для новичков разобраться в NodeJS помогут гайды и статьи (но в это в любом случае JavaScript), а для бывалых код-ревью скажет больше чем я.
Сам скрипт написан на NodeJS — он достаточно прост и всегда находится под рукой, поэтому выбор был очевиден. Подключение я использую SFTP. Итак что нам нужно:
- Мониторинг файлов на изменение
- Upload измененных файлов на удаленный сервер
Я решил не углубляться в идеальные для этого библиотеки — не хотелось тратить на эту задачу достаточно много времени. Беглый просмотр интернетов навел меня на 2 простеньких модуля:
Описывать как их устанавливать и как работает NodeJS не буду — гайдов полно на том же хабре.
Файлик я назвал незамысловато deploy.js. Первые строки выглядят просто:
var fs = require('fs'); var Connection = require('ssh2'); var Сhokidar = require('chokidar'); var c = new Connection();
Итак, библиотеки подключили. Первым делом надо подключиться к серверу:
c.connect({ host: 'habrahabr.ru', port: 1500, username: 'habr', password: 'habrapassword' });
Как у большинства модулей у ssh2 есть события. Выведем их в лог:
c.on('connect', function() { console.log('Connection :: connect'); }); c.on('error', function(err) { console.log('Connection :: error :: ' + err); }); c.on('end', function() { console.log('Connection :: end'); }); c.on('close', function(had_error) { console.log('Connection :: close'); });
Ну и конечно то с чем мы и будем работать:
c.on('ready', function() { .... })
В этом модуле есть достаточно полезная фича — sftp: достаточно удобный и простой менеджер для работы с файлами:
c.sftp(function(err,sftp){ if(!err){ console.log('sftp start'); }else{ console.log('sftp err',err); } });
Когда подключение поднято — пришло время внедрить мониторинг файлов:
var watcher = chokidar.watch(local_path, {ignored: // функция отвечающая за игнорирование файлов. я добавил сюда пути папки SVN и самого PhpStorm function(path){ if(path.indexOf(".idea") >= 0 || path.indexOf(".svn") >= 0 || path == (local_path+'/dpl')){ return true; } }, ignoreInitial:true // параметр отчающий за игнорирование файлов при инициализации скрипта. Если false - будет литься весь проект при каждом запуске });
У вотчера есть события add, change, unlink , которые и отрабатывают при манипуляции с файлами. Дело осталось за малым: заставить модуль ssh2 дублировать изменения проекта по sftp:
watcher .on('add', function(path,meta) { console.log('upload added',path.replace(local_path,deploy_path)); sftp.fastPut(path,path.replace(local_path,deploy_path),{},function(err){ if(err){ console.log('sftp upload err',err); } }); }) .on('change', function(path) { console.log('upload changed',path.replace(local_path,deploy_path)); sftp.fastPut(path,path.replace(local_path,deploy_path),{},function(err){ if(err){ console.log('sftp change err',err); } }); }) .on('unlink', function(path) { console.log('remove file',path.replace(local_path,deploy_path)); sftp.unlink(path.replace(local_path,deploy_path),function(err){ if(err){ console.log('sftp remove err',err); } }); }) .on('error', function(error) {console.error('Error happened', error);})
Готово! Файлы заливаются быстрее чем мы табаемся в браузер! По поводу нагрузки — скрипт кушает ЦП примерно как скайп (MacBook Air mid 2012), так что вполне терпимо.
Чтобы не дублировать на каждый проект по деплоеру я набросал легкий Bash скрипт, который бросаю в корень проекта, он уже и запускает наш скрипт.
#!/bin/bash DEPLOY_PATH="/deploy/path" DEPLOYER_PATH="/path/to/deploy.js" SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do TARGET="$(readlink "$SOURCE")" if [[ $SOURCE == /* ]]; then echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'" SOURCE="$TARGET" else DIR="$( dirname "$SOURCE" )" echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')" SOURCE="$DIR/$TARGET" fi done RDIR="$( dirname "$SOURCE" )" DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" if [ "$DIR" != "$RDIR" ]; then echo "local_path is '$DIR'" fi node $DEPLOYER_PATH local_path=$DIR deploy_path=$DEPLOY_PATH
Ну и в этом случае конечно надо получить параметры в deploy.js
var local_path; var deploy_path; process.argv.forEach(function (val, index, array) { var item_arr = val.split('='); if(item_arr.length > 1){ switch(item_arr[0]){ case 'local_path': local_path = item_arr[1]; break; case 'deploy_path': deploy_path = item_arr[1]; break; } } });
Скрипт прост и подходит для многих других задач. Например можно перезапускать NodeJS приложение на удаленном сервера после заливки файла, или дублировать картинки с окружения разработчика на общий dev сервер.
Прикладываю файл скрипта.
Скрипт был написан примерно за час, поэтому в нем могут быть глупости и банальные ошибки, поэтому прошу не судить строго. Смысл поста — не предоставить идеально работающий код а навести на мысли о возможном решении. Долгие часы я шарился в интернетах в поисках плагинов или хаков, но ничего не нашел. Идея пришла сама собой, с выходом нового PhpStorm, когда увидел поддержку консоли в IDE.
Спасибо за внимание и конструктивную критику!
ссылка на оригинал статьи http://habrahabr.ru/company/rangg/blog/202728/
Добавить комментарий