fail(function(ex) { /* The journalctl command fails when no entries are matched * so we just ignore this status code */ if (ex.problem == "cancelled" || ex.exit_status === 1) { fire_streamers(); dfd.resolve(entries); } else { dfd.reject(ex); } }).
journal.journalctl = function journalctl(/* ... */) { var matches = []; var i, arg, options = { follow: true }; for (i = 0; i < arguments.length; i++) { arg = arguments[i]; if (typeof arg == "string") { matches.push(arg); } else if (typeof arg == "object") { if (arg instanceof Array) { matches.push.apply(matches, arg); } else { cockpit.extend(options, arg); break; } } else { console.warn("journal.journalctl called with invalid argument:", arg); } } if (options.count === undefined) { if (options.follow) options.count = 10; else options.count = null; } var cmd = [ "journalctl", "-q", "--output=json" ]; if (!options.count) cmd.push("--no-tail"); else cmd.push("--lines=" + options.count); if (options.directory) cmd.push("--directory=" + options.directory); if (options.boot) cmd.push("--boot=" + options.boot); else if (options.boot !== undefined) cmd.push("--boot"); if (options.since) cmd.push("--since=" + options.since); if (options.until) cmd.push("--until=" + options.until); if (options.cursor) cmd.push("--cursor=" + options.cursor); if (options.after) cmd.push("--after=" + options.after); /* journalctl doesn't allow reverse and follow together */ if (options.reverse) cmd.push("--reverse"); else if (options.follow) cmd.push("--follow"); cmd.push("--"); cmd.push.apply(cmd, matches); var dfd = new cockpit.defer(); var promise; var buffer = ""; var entries = []; var streamers = []; var interval = null; function fire_streamers() { var ents, i; if (streamers.length && entries.length > 0) { ents = entries; entries = []; for (i = 0; i < streamers.length; i++) streamers[i].apply(promise, [ents]); } else { window.clearInterval(interval); interval = null; } } var proc = cockpit.spawn(cmd, { host: options.host, batch: 8192, latency: 300, superuser: "******" }). stream(function(data) { if (buffer) data = buffer + data; buffer = ""; var lines = data.split("\n"); var last = lines.length - 1; lines.forEach(function(line, i) { if (i == last) { buffer = line; } else if (line && line.indexOf("-- ") !== 0) { try { entries.push(JSON.parse(line)); } catch (e) { console.warn(e, line); } } }); if (streamers.length && interval === null) interval = window.setInterval(fire_streamers, 300); }). done(function() { fire_streamers(); dfd.resolve(entries); }). fail(function(ex) { /* The journalctl command fails when no entries are matched * so we just ignore this status code */ if (ex.problem == "cancelled" || ex.exit_status === 1) { fire_streamers(); dfd.resolve(entries); } else { dfd.reject(ex); } }). always(function() { window.clearInterval(interval); }); promise = dfd.promise(); promise.stream = function stream(callback) { streamers.push(callback); return this; }; promise.stop = function stop() { proc.close("cancelled"); }; return promise; };
done(function() { fire_streamers(); dfd.resolve(entries); }).