Cronjobs and Nodejs - node.js

Im Trying to create log file for every day using cronjobs. Whenever I restart Node server it create a new log file for the same otherwise it writes log in same file. Please help

Take a minute to read this: https://www.npmjs.com/package/cron
And this: https://www.npmjs.com/package/moment
function startLogger() {
var name = (require('moment')()).format('YYYY-MM-DD')
var path = ('~/' + name);
// ONLY if (path) doesn't exist, create it. (Do yourself the code)
// Write to the end of the existent or created file:
(require('fs')).appendFile(path, 'Your log line or multiple lines', function (err) {
if (err) throw err;
console.log('Log saved successfully!');
});
}
PS: I do not recommend to use require inside (), I just did it because I'm without time but I hope you understand it and make your own code.

Related

Read File then delete the file with node.js

I am attempting to use nodeJS to do the following:
Start an executable file (executable file then creates a timestamp_Question.txt file), read the created .txt file and return the text to my front end. Accept user input and create a new timestamp_Answer.txt file with a new name containing the user input, and then delete the original txt file.
Everything seems to be working except the deletion of the original file which is getting the following error
Error: EBUSY: resource busy or locked, unlink 'c:\projects\pizzabox\95912_Questi
on.txt'
at Error (native)
Here are the various segments of my server code:
Starting the .exe file:
startProgram: function(req, res){
var date = new Date().toLocaleTimeString();
date = date.replace(/\D/g,'');
exec('C:/projects/pizzabox/server/webserver/Pizza_page_server.exe', [date], function(err, data) {
console.log(err)
});
res.send(date) /// front end needs date value to track file as date is attached to created txtfile
}
Front end requesting the contents of the txt created by the exe:
getDocument: function(req,res){
console.log('file requested', req.params.dateStamp);
var directory = 'C:/projects/pizzabox/'
var fileCode = req.params.dateStamp.toString()
var fileSuffix = "_Question.txt"
var file = directory+fileCode+fileSuffix
console.log('file is', file);
while(!fs.existsSync(file)){};
fs.readFile(file, 'utf8', function(err,data){
if (err) throw err;
console.log('read ', data);
res.send(data)
});
Front end submitting data to create new timestamp_Answer.txt file and deletion of old timestamp_Question.txt file:
sendValue: function(req,res){
console.log('got value', req.body.value, " questionNumber ", req.body.questionNumber, "timestamp ", req.body.timestamp);
fs.appendFile(req.body.timestamp+'_Answer.txt', "Question_Num:"+req.body.questionNumber+"\nAnswer_Val:"+req.body.value, function(err){
if(err) throw err;
console.log('file created!');
fs.unlink(req.body.timestamp+'_Question.txt', function(err){
if (err) throw err;
console.log('question file deleted');
})
})
}
Any reason why unlink wouldn't have access to the file? does fs.readFile() not close/exit the file after it completes?
It appears you have at least one race condition here. Just because fs.fileExistsSync() sees that a file exists, does not mean that the .exe is done writing to that file or has closed that file. So, it's very likely that your fs.readFile() gets called while the file is still open by the other process.
You probably want to rethink how all your operations are sequenced.
First off, the design you have now is a single user design. Your server can only ever be used by one single user at a time since you have no way of differentiating requests that are coming from different users.
Second off, you should move to a design that is more purposefully sequential rather than trying to use the existence of a file in the file system as evidence that some previous operation might now be done.
Third, off while(!fs.existsSync(file)){}; is never used in anything except a one-off script because it halts all processing of any type of request or timer or any event in the server until that file exists. Further, it probably hogs all the CPU. It's never used in a multi-user server.
You haven't really described the overall client/server flow you're trying to design or described whether this is a single-user system or intended to eventually be for multiple users so it's hard for us to make suggestions about exactly where to go for an architectural redesign.
You could probably make one simple improvement by not returning the date to the client until your .exe is done which hopefully will stop it from requesting its next step until the .exe is done:
startProgram: function(req, res){
var date = new Date().toLocaleTimeString();
date = date.replace(/\D/g,'');
exec('C:/projects/pizzabox/server/webserver/Pizza_page_server.exe', [date], function(err, data) {
if (err) {
console.log(err);
res.sendStatus(500);
} else {
// don't send this until the .exe is done
res.send(date) // front end needs date value to track file as date is attached to created txtfile
}
});
}

I need to create a 'touch' function in node.js

I'm trying to mimic a terminal in node so I need to create a 'touch' function in node.js and I can't find anything that specifically uses touch. How can I set that up?
I've used a couple different things in the past but they keep getting kicked back because I'm not actually using 'fs.touch' or whatever it is.
this was my first attempt.
module.exports.touch = (filename, err) => {
if (err) {
throw err;
} else {
fs.openSync(filename, 'w');
`open filename`
}
};
this was my most recent attempt
module.exports.touch = (filename, callback) => {
open(filename, 'w', (err, fd) => {
err ? callback(err) : close(fd, callback);
});
};
The second one was essentially what they wanted because it did create a touch function but again they want me to actually use fs.touch but I cant find anything about it.
Make time either the current time or the time you want to be set:
fs.utimesSync(filename, time, time);
Just open the path file in write mode, and close it. You will have an empty file, equivalent at touch in command line

Monitoring for files using chokidar

I am trying to setup a monitoring piece in my app, I am using chokidar to do so.
I want the app to be awake all the time monitoring the directory for new file, once it see any new file it should move it a directory. Now i have used batch file to move the files (because with the fs.rename) I keep getting errbusy.
Here is my code, the problem is that I dont see the app being awake, It starts and close. I dont see its waiting to check on files. What am i doing wrong here
const exec = require('child_process').exec;
function movefile() { exec('movetostage.bat', function (err, stdout, stderr) {
if (err)
{
console.log(err);
return ;
}
console.log(stdout);
});
}
function monitordir(){
var watcher = chokidar.watch(DATA_PATH, {ignored: /^\./, persistent: true});
watcher
.on('add', function(event,path) {
if(event){
console.log(event,path);
movefile();
main();
}
})
}
I have added watcher.on('add'), I am guessing that is to check if there is any new files, but the important part here is that the app doesnt keep monitoring it exists

Can a node.js server know if a server file is created?

which is the most elegant way or technology to let a node.js server know if a file is created on a server?
The idea is: a new image has been created (from a webcam or so) -> dispatch an event!
UPDATE: The name of the new file in the directory is not known a priori and the file is generated by an external software.
You should take a look at fs.watch(). It allows you to "watch" a file or directory and receive events when things change.
Note: The documentation states that fs.watch is not consistent across platforms, so you should take that in to account before using it.
fs.watch(fileOrDirectoryPath, function(event, filename) {
// Something changed with filename, trigger event appropriately
});
Also something to be aware of from the docs:
Providing filename argument in the callback is not supported on every
platform (currently it's only supported on Linux and Windows). Even on
supported platforms filename is not always guaranteed to be provided.
Therefore, don't assume that filename argument is always provided in
the callback, and have some fallback logic if it is null.
If filename is not available on your platform and you're watching a directory you may need to do something where you initially read the directory and cache the list of files in it. Then, when you get an event from fs.watch, read the directory again and compare it to the cached list of files to see what was added (if anything).
Update 1: There's a good module called watch, on github, which makes it easy to watch a directory for new files.
Update 2: I threw together an example of how to use fs.watch to get notified when new files are added to a directory. I think the module I linked to above is probably the better way to go, but I thought it would be nice to have a basic example of how it might work if you were to do it yourself.
Note: This is a fairly simplistic example just to show how it could work in general. It could almost certainly be done more efficiently and it's far from throughly tested.
function watchForNewFiles(directory, callback) {
// Get a list of all the files in the directory
fs.readdir(directory, function(err, files) {
if (err) {
callback(err);
} else {
var originalFiles = files;
// Start watching the directory for new events
var watcher = fs.watch(directory, function(event, filename) {
// Get the updated list of all the files in the directory
fs.readdir(directory, function(err, files) {
if (err) {
callback(err);
} else {
// Filter out any files we already knew about
var newFiles = files.filter(function(f) {
return (originalFiles.indexOf(f) < 0);
});
// Reset our list of "original" files
originalFiles = files;
// If there are new files detected, call the callback
if (newFiles.length) {
callback(null, newFiles);
}
}
})
});
}
});
}
Then, to watch a directory you'd call it with:
watchForNewFiles(someDirectoryPath, function(err, files) {
if (err) {
// handle error
} else {
// handle any newly added files
// "files" is an array of filenames that have been added to the directory
}
});
I came up with my own solution using this code here:
var fs = require('fs');
var intID = setInterval(check,1000);
function check() {
fs.exists('file.txt', function check(exists) {
if (exists) {
console.log("Created!");
clearInterval(intID);
}
});
}
You could add a parameter to the check function with the name of the file and call it in the path.
I did some tests on fs.watch() and it does not work if the file is not created. fs.watch() has multiple issues anyways and I would never suggest using it... It does work to check if the file was deleted though...

node.js file system problems

I keep banging my head against the wall because of tons of different errors. This is what the code i try to use :
fs.readFile("balance.txt", function (err, data) //At the beginning of the script (checked, it works)
{
if (err) throw err;
balance=JSON.parse(data);;
});
fs.readFile("pick.txt", function (err, data)
{
if (err) throw err;
pick=JSON.parse(data);;
});
/*....
.... balance and pick are modified
....*/
if (shutdown)
{
fs.writeFile("balance2.txt", JSON.stringify(balance));
fs.writeFile("pick2.txt", JSON.stringify(pick));
process.exit(0);
}
At the end of the script, the files have not been modified the slightest. I then found out on this site that the files were being opened 2 times simultaneously, or something like that, so i tried this :
var balance, pick;
var stream = fs.createReadStream("balance.txt");
stream.on("readable", function()
{
balance = JSON.parse(stream.read());
});
var stream2 = fs.createReadStream("pick.txt");
stream2.on("readable", function()
{
pick = JSON.parse(stream2.read());
});
/****
****/
fs.unlink("pick.txt");
fs.unlink("balance.txt");
var stream = fs.createWriteStream("balance.txt", {flags: 'w'});
var stream2 = fs.createWriteStream("pick.txt", {flags: 'w'});
stream.write(JSON.stringify(balance));
stream2.write(JSON.stringify(pick));
process.exit(0);
But, this time, both files are empty... I know i should catch errors, but i just don't see where the problem is. I don't mind storing the 2 objects in the same file, if that can helps. Besides that, I never did any javascript in my life before yesterday, so, please give me a simple explanation if you know what failed here.
What I think you want to do is use readFileSync and not use readFile to read your files since you need them to be read before doing anything else in your program (http://nodejs.org/api/fs.html#fs_fs_readfilesync_filename_options).
This will make sure you have read both the files before you execute any of the rest of your code.
Make your like code do this:
try
{
balance = JSON.parse(fs.readFileSync("balance.txt"));
pick = JSON.parse(fs.readFileSync("pick.txt"));
}
catch(err)
{ throw err; }
I think you will get the functionality you are looking for by doing this.
Note, you will not be able to check for an error in the same way you can with readFile. Instead you will need to wrap each call in a try catch or use existsSync before each operation to make sure you aren't trying to read a file that doesn't exist.
How to capture no file for fs.readFileSync()?
Furthermore, you have the same problem on the writes. You are kicking off async writes and then immediately calling process.exit(0). A better way to do this would be to either write them sequentially asynchronously and then exit or to write them sequentially synchronously then exit.
Async option:
if (shutdown)
{
fs.writeFile("balance2.txt", JSON.stringify(balance), function(err){
fs.writeFile("pick2.txt", JSON.stringify(pick), function(err){
process.exit(0);
});
});
}
Sync option:
if (shutdown)
{
fs.writeFileSync("balance2.txt", JSON.stringify(balance));
fs.writeFileSync("pick2.txt", JSON.stringify(pick));
process.exit(0);
}

Resources