nodejs 监控代码变动实现ftp上传
被动模式下
//https://www.npmjs.com/package/watch //文件同步功能 var watch = require('watch'); var path = require("path"); var fs = require('fs'); var http = require('http'); const ftp = require("basic-ftp"); var files=[]; var config={ //remote_root:'/Users/apple/kefu/', // host:'192.168.1.159', // username:'apple', // password:'123', remote_root:'/', host:'127.0.0.1', username:'aaaa', password:'aaaa', }; //需要忽略的文件或目录 var ignore=[ __dirname+'\\file', ]; function readDirSync(path){ var files=[]; var pa = fs.readdirSync(path); pa.forEach(function(ele,index){ var info = fs.statSync(path+"/"+ele); if(info.isDirectory()){ files=files.concat(readDirSync(path+"/"+ele)); }else{ files.push(path+"/"+ele); } }) return files; } console.log('start watching'); watch.createMonitor(__dirname,{ignoreDotFiles:true}, function (monitor) { monitor.on("created", function (f, stat) { for(var i=0;i<ignore.length;i++){ if(f.indexOf(ignore[i])>=0) return; } // Handle new files console.log("created:",f); var stats=fs.statSync(f); if(stats.isDirectory()){ var folder_files=readDirSync(f); for(var i=0;i<folder_files.length;i++){ console.log("created:",folder_files[i]); if(files.indexOf(folder_files[i])===-1) files.push(folder_files[i]); } }else if(stats.isFile()){ if(files.indexOf(f)===-1) files.push(f); } }) monitor.on("changed", function (f, curr, prev) { for(var i=0;i<ignore.length;i++){ if(f.indexOf(ignore[i])>=0) return; } // Handle file changes console.log("changed:",f); if(files.indexOf(f)===-1) files.push(f); }) monitor.on("removed", function (f, stat) { for(var i=0;i<ignore.length;i++){ if(f.indexOf(ignore[i])>=0) return; } // Handle removed files console.log("removed:",f); }) }); async function upload(){ console.log('start to upload'); //https://www.npmjs.com/package/basic-ftp const client = new ftp.Client(); client.ftp.verbose = true; try { await client.connect(config.host, 21); // await client.useTLS(); await client.login(config.username, config.password); await client.useDefaultSettings(); //await client.upload(fs.createReadStream("README.md"), "README.md"); //上传目录 避免中文 //console.log(await client.list()); //read file console.log('begin to upload'); if(!files.length){ console.log('no files to upload'); return; } var contents=files; for(var i=0;i<contents.length;i++){ var roots=contents[i].trim(); if(!roots) continue; if(!fs.existsSync(roots)) continue; roots=roots.replace(/\\/g,'/'); //E:/wwwroot2/kefuv3/application/models/0/usersModel.class.php var local_file=roots; var local_path=path.dirname(local_file); var remote_path=local_path.replace(__dirname.replace(/\\/g,'/'),'').substr(1); //Users/apple/kefu/application/models/0/usersModel.class.php var remote_file=local_file.replace(__dirname.replace(/\\/g,'/'),'').substr(1); //dir await client.ensureDir(config.remote_root+remote_path); //change dir await client.cd(config.remote_root+remote_path); //upload await client.upload(fs.createReadStream(local_file), path.basename(local_file)); } files=[]; console.log('upload finished!'); } catch(err) { console.log(err); } client.close(); } var x=0; //http://nodejs.cn//api/process.html#process_signal_events process.stdin.resume(); process.on('SIGINT', () => { // x++; // if(x==2){ // console.log('byebye'); // process.exit(0); // } upload(); });
主动模式下
//https://www.npmjs.com/package/watch //https://blog.csdn.net/zgljl2012/article/details/50365492 //文件同步功能 var watch = require('watch'); var path = require("path"); var fs = require('fs'); var p = require('child_process'); var iconv = require("iconv-lite"); var files=[]; var config={ //remote_root:'/Users/apple/kefu/', // host:'192.168.1.159', // username:'apple', // password:'123', remote_root:'/', host:'127.0.0.1', username:'', password:'', }; //需要忽略的文件或目录 var ignore=[ __dirname+'\\file', __dirname+'\\cmd.txt', ]; function readDirSync(path){ var files=[]; var pa = fs.readdirSync(path); pa.forEach(function(ele,index){ var info = fs.statSync(path+"/"+ele); if(info.isDirectory()){ files=files.concat(readDirSync(path+"/"+ele)); }else{ files.push(path+"/"+ele); } }) return files; } console.log('start watching'); watch.createMonitor(__dirname,{ignoreDotFiles:true}, function (monitor) { monitor.on("created", function (f, stat) { for(var i=0;i<ignore.length;i++){ if(f.indexOf(ignore[i])>=0) return; } // Handle new files console.log("created:",f); var stats=fs.statSync(f); if(stats.isDirectory()){ var folder_files=readDirSync(f); for(var i=0;i<folder_files.length;i++){ console.log("created:",folder_files[i]); if(files.indexOf(folder_files[i])===-1) files.push(folder_files[i]); } }else if(stats.isFile()){ if(files.indexOf(f)===-1) files.push(f); } }) monitor.on("changed", function (f, curr, prev) { for(var i=0;i<ignore.length;i++){ if(f.indexOf(ignore[i])>=0) return; } // Handle file changes console.log("changed:",f); if(files.indexOf(f)===-1) files.push(f); }) monitor.on("removed", function (f, stat) { for(var i=0;i<ignore.length;i++){ if(f.indexOf(ignore[i])>=0) return; } // Handle removed files console.log("removed:",f); }) }); function create_dir_cmd(remote_root,remote_path){ // a/b/c if(!remote_path) return ''; var folder=remote_path.split('/'); var cmd=''; var base=remote_root; for(let i=0;i<folder.length;i++){ if(!folder[i]) continue; base+=folder[i]+'/'; cmd+="mkdir "+base+"\n"; } return cmd; } function upload(){ console.log('begin to upload'); if(!files.length){ console.log('no files to upload'); return; } var son=''; var contents=files; for(var i=0;i<contents.length;i++){ var roots=contents[i].trim(); if(!roots) continue; if(!fs.existsSync(roots)) continue; roots=roots.replace(/\\/g,'/'); //E:/wwwroot2/kefuv3/application/models/0/usersModel.class.php var local_file=roots; var local_path=path.dirname(local_file); var remote_path=local_path.replace(__dirname.replace(/\\/g,'/'),'').substr(1); //Users/apple/kefu/application/models/0/usersModel.class.php var remote_file=local_file.replace(__dirname.replace(/\\/g,'/'),'').substr(1); //dir //await client.ensureDir(config.remote_root+remote_path); //change dir //await client.cd(config.remote_root+remote_path); //upload //await client.upload(fs.createReadStream(local_file), path.basename(local_file)); son+=create_dir_cmd(config.remote_root,remote_path);//mkdir son+="cd "+config.remote_root+remote_path+"\n";//change dir son+="put \""+local_file+"\" \""+path.basename(local_file)+"\"\n";//upload } var str=`open ${config.host} ${config.username} ${config.password} binary prompt off pwd ${son} close quit `; var flag=fs.writeFile('cmd.txt', str,(err) => { if (err) throw err; console.log('cmd.txt保存成功!'); p.exec('ftp -s:cmd.txt', { encoding: 'binary' },function (error, stdout, stderr) { if (error !== null) { console.log('exec error: ' + error); } console.log(iconv.decode(Buffer.from(stdout, 'binary'), 'cp936')); files=[]; console.log('upload finished!'); }); }); } var x=0; //http://nodejs.cn//api/process.html#process_signal_events process.stdin.resume(); process.on('SIGINT', () => { // x++; // if(x==2){ // console.log('byebye'); // process.exit(0); // } upload(); });
建议使用第二种,使用的是windows的ftp命令,兼容了主动模式
watch.bat
node watch.js pause
使用时双击watch.bat
需要上传时按ctrl+c