diff --git a/app/js/LatexRunner.js b/app/js/LatexRunner.js index 972f1fe..fe737c7 100644 --- a/app/js/LatexRunner.js +++ b/app/js/LatexRunner.js @@ -19,6 +19,7 @@ const Settings = require('settings-sharelatex') const logger = require('logger-sharelatex') const Metrics = require('./Metrics') const CommandRunner = require('./CommandRunner') +const fs = require('fs') const ProcessTable = {} // table of currently running jobs (pids or docker container names) @@ -127,9 +128,36 @@ module.exports = LatexRunner = { : undefined, x5 => x5[1] ) || 0 - return callback(error, output, stats, timings) + // record output files + LatexRunner.writeLogOutput(project_id, directory, output, () => { + return callback(error, output, stats, timings) + }) + })) + }, + + writeLogOutput(project_id, directory, output, callback) { + if (!output) { + return callback() + } + // internal method for writing non-empty log files + function _writeFile(file, content, cb) { + if (content && content.length > 0) { + fs.writeFile(file, content, (err) => { + if (err) { + logger.error({ project_id, file }, "error writing log file") // don't fail on error + } + cb() + }) + } else { + cb() } - )) + } + // write stdout and stderr, ignoring errors + _writeFile(Path.join(directory, "output.stdout"), output.stdout, () => { + _writeFile(Path.join(directory, "output.stderr"), output.stderr, () => { + callback() + }) + }) }, killLatex(project_id, callback) { diff --git a/app/js/ResourceWriter.js b/app/js/ResourceWriter.js index ed3a1e8..97e971e 100644 --- a/app/js/ResourceWriter.js +++ b/app/js/ResourceWriter.js @@ -231,7 +231,9 @@ module.exports = ResourceWriter = { path === 'output.pdf' || path === 'output.dvi' || path === 'output.log' || - path === 'output.xdv' + path === 'output.xdv' || + path === 'output.stdout' || + path === 'output.stderr' ) { should_delete = true } diff --git a/test/unit/js/LatexRunnerTests.js b/test/unit/js/LatexRunnerTests.js index b468b83..15902e9 100644 --- a/test/unit/js/LatexRunnerTests.js +++ b/test/unit/js/LatexRunnerTests.js @@ -37,7 +37,10 @@ describe('LatexRunner', function() { done() {} }) }, - './CommandRunner': (this.CommandRunner = {}) + './CommandRunner': (this.CommandRunner = {}), + 'fs': (this.fs = { + writeFile: sinon.stub().callsArg(2) + }) } }) @@ -83,6 +86,21 @@ describe('LatexRunner', function() { ) .should.equal(true) }) + + it('should record the stdout and stderr', function () { + this.fs.writeFile + .calledWith( + this.directory + '/' + 'output.stdout', + "this is stdout" + ) + .should.equal(true) + this.fs.writeFile + .calledWith( + this.directory + '/' + 'output.stderr', + "this is stderr" + ) + .should.equal(true) + }) }) describe('with an .Rtex main file', function() { diff --git a/test/unit/js/ResourceWriterTests.js b/test/unit/js/ResourceWriterTests.js index a632c1b..1080765 100644 --- a/test/unit/js/ResourceWriterTests.js +++ b/test/unit/js/ResourceWriterTests.js @@ -230,6 +230,12 @@ describe('ResourceWriter', function() { { path: '_markdown_main/30893013dec5d869a415610079774c2f.md.tex', type: 'tex' + }, + { + path: 'output.stdout' + }, + { + path: 'output.stderr' } ] this.resources = 'mock-resources' @@ -256,7 +262,19 @@ describe('ResourceWriter', function() { .should.equal(true) }) - it('should delete the extra files', function() { + it('should delete the stdout log file', function () { + return this.ResourceWriter._deleteFileIfNotDirectory + .calledWith(path.join(this.basePath, 'output.stdout')) + .should.equal(true) + }) + + it('should delete the stderr log file', function () { + return this.ResourceWriter._deleteFileIfNotDirectory + .calledWith(path.join(this.basePath, 'output.stderr')) + .should.equal(true) + }) + + it('should delete the extra files', function () { return this.ResourceWriter._deleteFileIfNotDirectory .calledWith(path.join(this.basePath, 'extra/file.tex')) .should.equal(true)