с нуля
обновить:🎉Он был обновлен до кроссплатформенного инструмента автоматического развертывания, см. подробности.Инструмент автоматического развертывания сборки с открытым исходным кодом ⚡ auto-deploy-app
Показать результаты
1. Проект для развертывания упакован и собран локально
2. Определите каталог удаленного развертывания и папку выпуска.
3. Измените конфигурацию
4. Запустите автоматическое развертывание
5. Просмотр удаленных эффектов
6. Повторное развертывание. Резервная копия исходного каталога создана (откройте удаленную резервную копию, чтобы изменения вступили в силу).
предисловие
Когда интерфейсный проект развернут, после завершения настройки nginx вам нужно только загрузить упакованные файлы в указанную директорию сервера.
Как правило, это делается следующими способами:
-
xshell
Подождите, пока инструмент командной строки загрузится -
ftp
и другие инструменты визуализации для загрузки -
jenkins
и другие службы автоматизированного развертывания
Для простых интерфейсных проектов при частом развертыванииxshell
,ftp
Оба метода более сложные иjenkins
Другим службам автоматизированного развертывания необходимо заранее установить программное обеспечение и ознакомиться с процессом настройки.
Поэтому есть надежда, что местныеnode
Сервис реализует загрузку интерфейсных упакованных файлов, что не требует дополнительных программ установки на сервер, но также помогает нам добиться быстрой загрузки и развертывания, а также может помочь нам глубже понятьnode
.
PS:
Раньше я готовил реализацию соответствующего внешнего автоматизированного развертывания и только недавно увидел ее.да да, обратитесь к статьям, упомянутым в статьеnode-ssh
а такжеarchiver
, завершить реализацию проекта,
Спасибо здесь (тоже спасибоnode-ssh
,archiver
,inquirer
автор).
Прикрепил:npm地址
Начинать
1. Определите потребности
Перед разработкой необходимо сначала уточнить требования.Согласно общему процессу развертывания интерфейса, вкратце описан следующий процесс:
Определите необходимость автоматического развертывания на основе процесса развертывания:
2. Подготовка перед разработкой
2.1 Импорт зависимых модулей
Поскольку необходимо реализовать сжатие файлов, подключиться к удаленному серверу и реализовать удаленный вызов команд, требуются как минимум следующие модули:
-
ssh
Модуль (может выполнять общие операции, такие как подключение к серверу, вызов команд и т. д.) -
文件压缩
модуль (достижимый.zip
например, локальная упаковка общих сжатых файлов) -
命令行选择
Модуль (может реализовать выбор и использование нескольких файлов элементов конфигурации)
Поиск информации, окончательный выборnode-ssh
,archiver
,inquirer
соответственно реализовать вышеуказанные функции.
# 安装依赖
npm i node-ssh --save
npm i archiver --save
npm i inquirer --save
2.2 Как реализовать спецификацию
чтобы реализовать требования解耦合理
а также逻辑清晰/灵活
, нужно обратить внимание на общую логику программы, выбирать здесь封装
соответствующие функции реализованы и主程序
Средний свободный график (гибкий调用/关闭/修改
связанные функции) и выдавать подсказки для текущих выполняемых функций, чтобы убедиться, что функции реализованы.完整性
а также异常提示
.
потому что文件压缩
,文件上传
,执行远端命令
и т.д. процесс асинхронный, поэтому порядок выполнения функций должен быть четким, т.е.应在前置任务完成的回调中开启当前任务
, чтобы контролировать асинхронный процесс и логика кода понятна, здесь мы выбираем использование ES6Promise
Синтаксический сахар в сочетании с ES7async awiat
Реализовать логическое управление потоком.
На этом разборка построения программной функции завершена, и теперь начинается реализация проекта.
3. Реализация функции
Предварительный просмотр каталога проектаВот каталог проекта конечного результата для справки:
- node_modules
- utils
- CompressFile.js [сжимать локальные файлы]
- handleCommand.js [вызов удаленной команды]
- handleTime.js [время обработки]
- helper.js [запрос выбора проекта развертывания]
- ssh.js [подключиться к удаленному серверу]
- uploadFile.js [загрузить локальный файл]
- app.js [основная программа]
- config.js [файл конфигурации]
- dist.zip [сжатый файл] (текущая версия не удаляется автоматически)
- package.json
- README.md【Введение в проект】
3.1 Сжатие локальных файлов
compressFile
перенимать需要压缩的目录
а также打包生成文件
, чтобы обеспечить локальное сжатие файла после его передачи.
compressFile.js
Код ссылки
// compressFile.js
const fs = require('fs')
const archiver = require('archiver')
function compressFile (targetDir, localFile) {
return new Promise((resolve, reject)=>{
console.log('1-正在压缩文件...')
let output = fs.createWriteStream(localFile) // 创建文件写入流
const archive = archiver('zip', {
zlib: { level: 9 } // 设置压缩等级
})
output.on('close', () => {
resolve(
console.log('2-压缩完成!共计 ' + (archive.pointer() / 1024 /1024).toFixed(3) + 'MB')
)
}).on('error', (err) => {
reject(console.error('压缩失败', err))
})
archive.pipe(output) // 管道存档数据到文件
archive.directory(targetDir, 'dist') // 存储目标文件并重命名
archive.finalize() // 完成文件追加 确保写入流完成
})
}
module.exports = compressFile
3.2 Подключиться к удаленному серверу
connectServe
Получить дальний конецip
,用户名
,密码
и другую информацию для завершения подключения к удаленному серверу, пожалуйста, обратитесь к конкретной конфигурацииconfig.js
.
ssh.js
Код ссылки
// ssh.js
const node_ssh = require('node-ssh')
const ssh = new node_ssh()
function connectServe (sshInfo) {
return new Promise((resolve, reject) => {
ssh.connect({ ...sshInfo }).then(() => {
resolve(console.log('3-' + sshInfo.host + ' 连接成功'))
}).catch((err) => {
reject(console.error('3-' + sshInfo.host + ' 连接失败', err))
})
})
}
module.exports = connectServe
3.3 Удаленное выполнение команд
runCommand
перенимать需执行的命令
а также执行命令的远端路径
, здесь она разделена отдельно, что удобно主程序
Отдельный звонок тоже удобен文件上传
и другие функции пакета модулей для достижения解耦
Эффект.
handleCommand.js
Код ссылки
// handleCommand.js
// run linux shell(ssh对象、shell指令、执行路径)
function runCommand (ssh, command, path) {
return new Promise((resolve, reject) => {
ssh.execCommand(command, {
cwd: path
}).then((res) => {
if (res.stderr) {
reject(console.error('命令执行发生错误:' + res.stderr))
process.exit()
} else {
resolve(console.log(command + ' 执行完成!'))
}
})
})
}
module.exports = runCommand
3.4 Загрузка файла
uploadFile
перенимать系统配置参数
,待上传的本地文件
, завершите загрузку локального файла в указанный каталог сервера, что также представлено здесьhandleCommand.js
,handleTime.js
,согласно сopenBackUp
Включить ли удаленное резервное копирование и завершить обработку существующих каталогов с тем же именем после распаковки. Ссылка на конкретную конфигурациюconfig.js
.
uploadFile.js
Код ссылки
// uploadFile.js
const runCommand = require ('./handleCommand')
const getCurrentTime = require ('./handleTime')
// 文件上传(ssh对象、配置信息、本地待上传文件)
async function uploadFile (ssh, config, localFile) {
return new Promise((resolve, reject) => {
console.log('4-开始文件上传')
handleSourceFile(ssh, config)
ssh.putFile(localFile, config.deployDir + config.targetFile).then(async () => {
resolve(console.log('5-文件上传完成'))
}, (err) => {
reject(console.error('5-上传失败!', err))
})
})
}
// 处理源文件(ssh对象、配置信息)
async function handleSourceFile (ssh, config) {
if (config.openBackUp) {
console.log('已开启远端备份!')
await runCommand(
ssh,
`
if [ -d ${config.releaseDir} ];
then mv ${config.releaseDir} ${config.releaseDir}_${getCurrentTime()}
fi
`,
config.deployDir)
} else {
console.log('提醒:未开启远端备份!')
await runCommand(
ssh,
`
if [ -d ${config.releaseDir} ];
then mv ${config.releaseDir} /tmp/${config.releaseDir}_${getCurrentTime()}
fi
`,
config.deployDir)
}
}
module.exports = uploadFile
3.5 Обработка времени
getCurrentTime
Получить и вернуть текущее время, которое используется для удаленного удаленного резервного копирования.
handleTime.js
Код ссылки
// 获取当前时间
function getCurrentTime () {
const date = new Date
const yyyy = date.getFullYear()
const MM = coverEachUnit(date.getMonth() + 1)
const dd = coverEachUnit(date.getDate())
const HH = coverEachUnit(date.getHours())
const mm = coverEachUnit(date.getMinutes())
const ss = coverEachUnit(date.getSeconds())
return `${yyyy}-${MM}-${dd}_${HH}:${mm}:${ss}`
}
// 转换时间中一位至两位
function coverEachUnit (val) {
return val < 10 ? '0' + val : val
}
module.exports = getCurrentTime
3.6 Основная программа
Когда все функциональные модули инкапсулированы,异步流程
оба используютPromise
обработать, а затем объединитьasync awiat
Реализация не только обеспечивает порядок реализации функций, но и делает комбинацию функций более лаконичной и элегантной.
main
Совмещение функций таможенного оформления в функции реализует процесс автоматического развертывания, а остальные функции добавляются позже.主程序
Введите и объедините, чтобы завершить обновление.
app.js
Код ссылки
const config = require ('./config')
const helper = require ('./utils/helper')
const compressFile = require ('./utils/compressFile')
const sshServer = require ('./utils/ssh')
const uploadFile = require ('./utils/uploadFile')
const runCommand = require ('./utils/handleCommand')
// 主程序(可单独执行)
async function main () {
try {
console.log('请确保文件解压后为dist目录!!!')
const SELECT_CONFIG = (await helper(config)).value // 所选部署项目的配置信息
console.log('您选择了部署 ' + SELECT_CONFIG.name)
const localFile = __dirname + '/' + SELECT_CONFIG.targetFile // 待上传本地文件
SELECT_CONFIG.openCompress ? await compressFile(SELECT_CONFIG.targetDir, localFile) : '' //压缩
await sshServer.connectServe(SELECT_CONFIG.ssh) // 连接
await uploadFile(sshServer.ssh, SELECT_CONFIG, localFile) // 上传
await runCommand(sshServer.ssh, 'unzip ' + SELECT_CONFIG.targetFile, SELECT_CONFIG.deployDir) // 解压
await runCommand(sshServer.ssh, 'mv dist ' + SELECT_CONFIG.releaseDir, SELECT_CONFIG.deployDir) // 修改文件名称
await runCommand(sshServer.ssh, 'rm -f ' + SELECT_CONFIG.targetFile, SELECT_CONFIG.deployDir) // 删除
} catch (err) {
console.log('部署过程出现错误!', err)
} finally {
process.exit()
}
}
// run main
main()
3.7 Файлы конфигурации
Для облегчения автоматического внешнего развертывания здесь извлекается ключевая информация и создается файл конфигурации.
Пользователям нужно только изменить файл конфигурации для достижения自动化部署
.
config.js
Код ссылки
/*
config.js
说明:
请确保解压后的文件目录为dist
ssh: 连接服务器用户信息
targetDir: 需要压缩的文件目录(启用本地压缩后生效)
targetFile: 指定上传文件名称(config.js同级目录)
openCompress: 关闭后,将跳过本地文件压缩,直接上传同级目录下指定文件
openBackUp: 开启后,若远端存在相同目录,则会修改原始目录名称,不会直接覆盖
deployDir: 指定远端部署地址
releaseDir: 指定远端部署地址下的发布目录名称
更新:
🎉现已支持添加多个配置信息,自动化部署时支持选择配置信息运行
🎉现已支修改服务器连接端口,支持ssh私钥及解密密码连接(ps:不使用此方法时,请注释privateKey)
🎉现已更新模块引用逻辑,远端备份时间格式改为 `yyyy-MM-dd_HH:mm:ss`
*/
const config = [
{
name: '项目A-dev',
ssh: {
host: '192.168.0.110',
port: 22,
username: 'root',
password: 'root',
// privateKey: 'E:/id_rsa', // ssh私钥(不使用此方法时请勿填写, 注释即可)
passphrase: '123456' // ssh私钥对应解密密码(不存在设为''即可)
},
targetDir: 'E:/private/my-vue-cli/dist', // 目标压缩目录(可使用相对地址)
targetFile: 'dist.zip', // 目标文件
openCompress: true, // 是否开启本地压缩
openBackUp: true, // 是否开启远端备份
deployDir: '/home/node_test' + '/', // 远端目录
releaseDir: 'web' // 发布目录
},
{
name: '项目A-prod',
ssh: {
host: '192.168.0.110',
port: 22,
username: 'root',
password: 'root',
privateKey: 'E:/id_rsa', // ssh私钥(不使用此方法时请勿填写, 注释即可)
passphrase: '123456' // ssh私钥对应解密密码(不存在设为''即可)
},
targetDir: 'E:/private/my-vue-cli/dist', // 目标压缩目录(可使用相对地址)
targetFile: 'dist.zip', // 目标文件
openCompress: true, // 是否开启本地压缩
openBackUp: true, // 是否开启远端备份
deployDir: '/home/node_test' + '/', // 远端目录
releaseDir: 'web2' // 发布目录
}
]
module.exports = config
использовать
Извлеките исходный код, установите зависимости, измените файл конфигурации и запустите его.
npm install
npm run deploy
наконец
🎉Исходный код проекта открыт дляgithub
Добро пожаловать на загрузку и использование, в будущем будет улучшено больше функций 🎉Исходный код и описание проекта
Наконечник:Не забудьте, если вам нравитсяstar
О 😘, если есть вопросы 🧐 добро пожаловатьpr
а такжеissues
и активно общаться.
Другие статьи: