This part of my script is trying to spawn a child that is going to clone a hard drive. It basically works but the issue that I am having is that when I encounter an error and want to store the output, it only stores the first line of the output, excluding the things that I actually need. I have run the command outside of the script and it gives me two lines of output, with the second line being the error if it fails. So, how could I store the entire output. Help is much appreciated, thank you!
NtfsPartition.prototype.WriteFs = function(filename, progress, success, error) {
console.log('Writing NTFS FS');
var s = spawn("ntfsclone", ['--restore-image', '--overwrite', this.dev, filename]);
var err_msg = '';
s.on('error', function(err) {
err_msg = err;
});
s.stderr.on('data', function(data) {
err_msg += data.toString();
});
s.stdout.on('data', function(data) {
var match = data.toString().match(kNtfsWriteFsProgressRegex);
if(!match) {
return;
}
progress(match[1]);
});
s.on('exit', function(code) {
if(code != 0) {
console.log(err_msg);
return error('Error: ' + code + ' - ' + err_msg);
}
success();
});
}
To answer your question, I can't actually test this, but I suspect that removing the s.stderr.on('data', ...)
handler will allow you to ensure that err_msg
is an Error
object.
Also taking note of this warning:
Note: The
'exit'
event may or may not fire after an error has occurred. When listening to both the'exit'
and'error'
events, it is important to guard against accidentally invoking handler functions multiple times.
I could see a possible solution looking like this:
NtfsPartition.prototype.WriteFs = function(filename, progress, success, error) {
console.log('Writing NTFS FS');
var s = spawn("ntfsclone", ['--restore-image', '--overwrite', this.dev, filename]);
var errors = [];
// if possible, might get multiple of these
// if not, this still works for a single error
s.on('error', function(err) {
errors.push(err)
});
s.stdout.on('data', function(data) {
var match = data.toString().match(kNtfsWriteFsProgressRegex);
if(!match) {
return;
}
progress(match[1]);
});
// guaranteed to be called, whereas 'exit' is not(?)
s.on('close', function(code) {
if(code != 0) {
var stacks = errors.map(function (err) {
return err.stack;
});
// all the errors
return error('Error: ' + code + '\n\n' + stacks.join('\n\n'))
}
success();
});
}
One of the keys is to use the error.stack
property, since errors typically tend to log the message
property instead by default, when coerced to a string. This property is probably the single-line feedback you were getting in your code, since you never checked the err_msg.stack
.