Gulp部署项目到远程服务器报21端口ECONNREFUSED连接错误
问题现象
部署正式主项目前,先行尝试将测试项目部署至组织分配的远程服务器时,触发如下连接错误:
Error: connect ECONNREFUSED 10.208.26.206:21 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1161:16) at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17)
报错指向目标服务器10.208.26.206的21端口FTP连接被拒绝,以下是使用的Gulp项目构建部署完整配置代码:
var gulp = require('gulp'); var uglify = require('gulp-uglify'); var csso = require('gulp-csso'); var htmlmin = require('gulp-htmlmin'); var browserSync = require('browser-sync').create(); var reload = browserSync.reload; var gutil = require('gulp-util'); var ftp = require('vinyl-ftp'); //var GulpSSHDeploy = require('gulp-ssh-deploy').GulpSSHDeploy; var styleSrc = './src/css/*.css'; var styleDest = './dist/css'; var jsSrc = './src/js/*.js'; var jsDest = './dist/js'; var pageSrc = './src/html/*.html'; var pageDest = './dist/html'; var styleWatch = './src/css/**/*.css'; var jsWatch = './src/js/**/*.js'; var pageWatch = './src/html/**/*.html'; var user = 'user'; var password = 'password'; var host = 'test-vm-xyz.xyz.xyz.in'; var port = 21; var localFilesGlob = ['./src/**/*']; var remoteFolder = './home/project/myApp/'; gulp.task('style', function () { return gulp.src(styleSrc) .pipe(csso()) .pipe(gulp.dest(styleDest)) }); gulp.task('js', function () { return gulp.src(jsSrc) .pipe(uglify()) .pipe(gulp.dest(jsDest)); }); gulp.task('page', function () { return gulp.src(pageSrc) .pipe(htmlmin({collapseWhitespace: true})) .pipe(gulp.dest(pageDest)); }); gulp.task('browser-sync', function () { browserSync.init({ open:'external', host: host, proxy: 'http://' + host + ':' + port, port: port, notify: false, ghostMode: false }); }); // 上传文件逻辑 gulp.task('deploy', function () { var conn = ftp.create({ host: host, user: user, password: password, parallel: 10, log: gutil.log }); console.log('Connecting to ' + host + ':' + port); console.log('Uploading files to ' + remoteFolder); console.log('Using user ' + user + ' with password ' + password); return gulp.src(localFilesGlob, {base: './src', buffer: false}) .pipe(conn.newer(remoteFolder)) .pipe(conn.dest(remoteFolder)); }); gulp.task('ftp-deploy-watch', function () { var conn = getFtpConnection(); return gulp.src(localFilesGlob, { base: './src', buffer: false }) .pipe(conn.newer(remoteFolder)) // 仅上传更新过的文件 .pipe(conn.dest(remoteFolder)); }); gulp.task('watch', function () { gulp.watch(styleWatch, gulp.parallel('style')); gulp.watch(jsWatch, gulp.parallel('js')); gulp.watch(pageWatch, gulp.parallel('page')); // gulp.watch(GulpSSHDeploy.watch_files).on('change', reload); }); gulp.task('default', gulp.series('style','js','page', 'watch'),function(){ return console.log('Gulp is running...'); });
问题原因与修复方案
ECONNREFUSED代表TCP握手阶段直接被目标端拒绝,和Gulp、vinyl-ftp本身的代码逻辑无关,本质是发起到21端口的连接时,目标服务器没有对应服务监听该端口,或者中间防火墙直接拦截了请求,按以下顺序排查即可:
- 优先和运维确认服务器开放的文件传输协议:绝大多数企业内部服务器默认不会开启明文FTP(21端口),普遍只开放SFTP(默认走22端口,基于SSH),你代码里已经注释了
gulp-ssh-deploy依赖,大概率运维分配的是SSH/SFTP账号权限而非FTP权限,不要硬连21端口。 - 如果确认必须走FTP协议,先在本地命令行执行
telnet 10.208.26.206 21验证端口连通性:如果telnet直接连接失败,找运维开放服务器防火墙21端口入站规则,同时确认服务器上的FTP服务已经启动并绑定到对应网卡IP;如果telnet能连通但vinyl-ftp连接失败,再核对账号密码、FTP服务的用户访问权限配置。 - 修正现有配置的两处代码问题:
ftp.create()初始化时没有显式传入port参数,默认会走21端口,如果后续运维提供的FTP端口不是默认值,必须在配置对象中添加port: 实际端口号字段ftp-deploy-watch任务中调用了未定义的getFtpConnection()方法,执行该任务会直接报函数不存在错误,需要和deploy任务一样先初始化ftp连接实例再使用。
- 如果最终确认使用SFTP协议,直接弃用
vinyl-ftp,换成你已经注释的gulp-ssh-deploy或者gulp-sftp插件,端口改为22,按SFTP配置要求填写账号、密码/私钥即可。
内容的提问来源于stack exchange,提问作者Mr. Dwivedi
相关产品推荐
相关产品推荐

