每10秒运行一次node.js脚本

我刚开始使用Node.js,现在我正在试图让我的脚本每隔10秒在后台运行,就像守护进程等待某些事情要做,当有数据从数据库运行时一样。它从程序中读取输出,根据输出执行某些任务。

这是我迄今为止能够做到的,它的工作方式与我的意图一致,但只能在后台运行一次。 我如何使它像守护进程一样每10秒运行一次?

码:

var spawn = require('child_process').spawn; var mysql = require('mysql'); var JSFtp = require('jsftp'); var check = require('node-validator').check; var sanitize = require('node-validator').sanitize; //Setup the db connection var db = mysql.createConnection({ host : 'db', port : 3306, database: 'db', user : 'db', password : 'db' }); //Make the connection db.connect(function(err){ if(err != null) { res.end('Error connecting to mysql:' + err+'\n'); } }); var die = function(msg){ console.error(msg); process.exit(1); } function ip2long ( ip_address ) { var output = false; var parts = []; if (ip_address.match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)) { parts = ip_address.split('.'); output = ( parts[0] * 16777216 + ( parts[1] * 65536 ) + ( parts[2] * 256 ) + ( parts[3] * 1 ) ); } return output; } db.query("SELECT * FROM queue WHERE cooldown > UNIX_TIMESTAMP(NOW()) AND simulated=0 ORDER BY cooldown DESC LIMIT 1", function(err, rows){ if(err != null){ die("Query error: " + err); } if(rows < 1){ die("No rows"); } //Set the vars from the query var name = rows[0]['name']; var ip = rows[0]['ip']; var iterations = rows[0]['runs']; var bin = "/home/hoar/sum/run" var args = ['arg='+name, 'arg2='+iterations, 'path=/var/www/upload/'+name+'.html', 'output=log.log']; var proc = spawn(bin, args); var time = "/.*/"; var pct = "/^\d/"; var name = rows[0]['name']; var ip = rows[0]['ip']; var iterations = rows[0]['runs']; proc.stdout.setEncoding('utf8'); proc.stdout.on('data', function(data) { var str = data.toString(); var s = str.split("|"); var p = s[0].split("/"); var t = (s[1] == null) ? "" : s[1]; if(p != null && s[0] != "@"){ //Needed to check for @ because the program prints this as first line, which is good then we can do the query further done only once. //Check the return numbers from simc to see how many sims it has done if(parseInt(p[0]) < parseInt(p[1])){ //Check if the 6th match is a number and the 7th only contains letters if(t != null){ var time = t.replace(/(\r\n|\n|\r)/gm,""); //Remove any line disturbers for db //Update the database with the amount of time left on the simulation db.query("UPDATE `queue` SET `status`=" + db.escape(time) + " WHERE (`name`=" + name + ")"); //console.log(p[0]+"/"+p[1] + " - " + t + " left"); } //console.log(p[0]+"/"+p[1] + " iterations done"); } }else{ //If the stdout is null run this query since we don't want to run this more than once. db.query("UPDATE `queue` SET `simulated`='2' WHERE (`name`=" + name + " AND simulated!='2')"); //console.log("Updated db to 2"); } }); proc.stderr.on('data', function (data) { var str = data.toString(); //If the program returns stderr we want to make sure it stops and we update the database to let the user know. if(str.indexOf("ERROR! Setup failure...")){ //Update the database with the amount of time left on the simulation db.query("UPDATE `queue` SET `simulated`='3' WHERE (`name`=" + name + ")"); //Kill the DB connection db.destroy(); die("There was an error: " + data); } }); proc.on('exit', function (code) { //Setup the ftp connection var ftp = new JSFtp({ host: "ftp", port: 21, user: "ftp", pass: "ftp" }); //Simulation ended with success update the database and kill. db.query("UPDATE `queue` SET `simulated`='1' WHERE (`name`=" + name + " AND simulated='2')"); ftp.put('/var/www/upload/'+rows[0]['name']+'.html', 'public_html/mysite/'+ip2long(rows[0]['ip'])+'/'+rows[0]['name']+'.html', function(hadError) { if (!hadError) console.log("FTP error"); ftp.raw.quit(); }); db.destroy(); //die("Simulation is done"); }); });//end sql 

把你的数据库查询放在一个带有回调的函数中,然后在10秒后再次调用这个函数:

 function mydbquery(callback) { db.query("SELECT * FROM queue WHERE cooldown > UNIX_TIMESTAMP(NOW()) AND simulated=0 ORDER BY cooldown DESC LIMIT 1", function(err, rows){ if(err != null){ die("Query error: " + err); } if(rows < 1){ die("No rows"); } //Set the vars from the query var name = rows[0]['name']; var ip = rows[0]['ip']; var iterations = rows[0]['runs']; var bin = "/home/hoar/sum/run" var args = ['arg='+name, 'arg2='+iterations, 'path=/var/www/upload/'+name+'.html', 'output=log.log']; var proc = spawn(bin, args); var time = "/.*/"; var pct = "/^\d/"; var name = rows[0]['name']; var ip = rows[0]['ip']; var iterations = rows[0]['runs']; proc.stdout.setEncoding('utf8'); proc.stdout.on('data', function(data) { var str = data.toString(); var s = str.split("|"); var p = s[0].split("/"); var t = (s[1] == null) ? "" : s[1]; if(p != null && s[0] != "@"){ //Needed to check for @ because the program prints this as first line, which is good then we can do the query further done only once. //Check the return numbers from simc to see how many sims it has done if(parseInt(p[0]) < parseInt(p[1])){ //Check if the 6th match is a number and the 7th only contains letters if(t != null){ var time = t.replace(/(\r\n|\n|\r)/gm,""); //Remove any line disturbers for db //Update the database with the amount of time left on the simulation db.query("UPDATE `queue` SET `status`=" + db.escape(time) + " WHERE (`name`=" + name + ")"); //console.log(p[0]+"/"+p[1] + " - " + t + " left"); } //console.log(p[0]+"/"+p[1] + " iterations done"); } }else{ //If the stdout is null run this query since we don't want to run this more than once. db.query("UPDATE `queue` SET `simulated`='2' WHERE (`name`=" + name + " AND simulated!='2')"); //console.log("Updated db to 2"); } }); proc.stderr.on('data', function (data) { var str = data.toString(); //If the program returns stderr we want to make sure it stops and we update the database to let the user know. if(str.indexOf("ERROR! Setup failure...")){ //Update the database with the amount of time left on the simulation db.query("UPDATE `queue` SET `simulated`='3' WHERE (`name`=" + name + ")"); //Kill the DB connection db.destroy(); die("There was an error: " + data); } }); proc.on('exit', function (code) { //Setup the ftp connection var ftp = new JSFtp({ host: "ftp", port: 21, user: "ftp", pass: "ftp" }); //Simulation ended with success update the database and kill. db.query("UPDATE `queue` SET `simulated`='1' WHERE (`name`=" + name + " AND simulated='2')"); ftp.put('/var/www/upload/'+rows[0]['name']+'.html', 'public_html/mysite/'+ip2long(rows[0]['ip'])+'/'+rows[0]['name']+'.html', function(hadError) { if (!hadError) console.log("FTP error"); ftp.raw.quit(); }); db.destroy(); //die("Simulation is done"); //NEW CODE!!! callback(); //END OF NEW CODE }); });//end sql } //NEW CODE!!! function wait10sec(){ setTimeout(function(){ mydbquery(wait10sec); }, 10000); } mydbquery(wait10sec); //END OF NEW CODE 

所以它会做你的查询,然后等待10秒,然后再发射。

只要让程序连续运行,并使用setTimeout重新执行定时器的主逻辑。 还有setInterval这是诱人的,但你有风险开始之前运行完成运行。 这是基本模式。

 function doMainStuff() { //do all your stuff lastAsyncThing(function (error) { //When your final async thing is done, start the timer if (error) { //log error. Maybe exit if it's irrecoverable. } setTimeout(doMainStuff, 10 * 1000); }); } //when your program starts, do stuff right away. doMainStuff(); 

永远运行这个脚本包 – https://npmjs.org/package/forever

 $ forever script.js 

这个填充在后台运行这个脚本,从控制台分离。

10秒钟,你可以使用

 setInterval(function(){...}, 10*1000); 

更多信息 – http://www.w3schools.com/jsref/met_win_setinterval.asp