UNPKG

13.3 kBJavaScriptView Raw
1var chalk = require('chalk');
2var util = require('util');
3var fs = require('fs');
4var exec = require('child_process').exec;
5var path = require('path');
6
7var Log = require('./Log');
8var cst = require('../../constants.js');
9var Common = require('../Common.js');
10
11module.exports = function(CLI) {
12
13 /**
14 * Description
15 * @method flush
16 * @return
17 */
18 CLI.prototype.flush = function(api, cb) {
19 var that = this;
20
21 if (!api) {
22 Common.printOut(cst.PREFIX_MSG + 'Flushing ' + cst.PM2_LOG_FILE_PATH);
23 fs.closeSync(fs.openSync(cst.PM2_LOG_FILE_PATH, 'w'));
24 }
25
26 that.Client.executeRemote('getMonitorData', {}, function(err, list) {
27 if (err) {
28 Common.printError(err);
29 return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
30 }
31 list.forEach(function(l) {
32 if (typeof api == 'undefined') {
33 Common.printOut(cst.PREFIX_MSG + 'Flushing:');
34 Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_out_log_path);
35 Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_err_log_path);
36
37 if (l.pm2_env.pm_log_path) {
38 Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_log_path);
39 fs.closeSync(fs.openSync(l.pm2_env.pm_log_path, 'w'));
40 }
41 fs.closeSync(fs.openSync(l.pm2_env.pm_out_log_path, 'w'));
42 fs.closeSync(fs.openSync(l.pm2_env.pm_err_log_path, 'w'));
43 }
44 else if (l.pm2_env.pm_id == api || l.pm2_env.name === api) {
45 Common.printOut(cst.PREFIX_MSG + 'Flushing:');
46
47 if (l.pm2_env.pm_log_path && fs.existsSync(l.pm2_env.pm_log_path)) {
48 Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_log_path);
49 fs.closeSync(fs.openSync(l.pm2_env.pm_log_path, 'w'));
50 }
51
52 if (l.pm2_env.pm_out_log_path && fs.existsSync(l.pm2_env.pm_out_log_path)) {
53 Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_out_log_path);
54 fs.closeSync(fs.openSync(l.pm2_env.pm_out_log_path, 'w'));
55 }
56
57 if (l.pm2_env.pm_err_log_path && fs.existsSync(l.pm2_env.pm_err_log_path)) {
58 Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_err_log_path);
59 fs.closeSync(fs.openSync(l.pm2_env.pm_err_log_path, 'w'));
60 }
61 }
62 });
63
64 Common.printOut(cst.PREFIX_MSG + 'Logs flushed');
65 return cb ? cb(null, list) : that.exitCli(cst.SUCCESS_EXIT);
66 });
67 };
68
69 CLI.prototype.logrotate = function(opts, cb) {
70 var that = this;
71
72 if (process.getuid() != 0) {
73 return exec('whoami', function(err, stdout, stderr) {
74 Common.printError(cst.PREFIX_MSG + 'You have to run this command as root. Execute the following command:');
75 Common.printError(cst.PREFIX_MSG + chalk.grey(' sudo env PATH=$PATH:' + path.dirname(process.execPath) + ' pm2 logrotate -u ' + stdout.trim()));
76
77 cb ? cb(Common.retErr('You have to run this with elevated rights')) : that.exitCli(cst.ERROR_EXIT);
78 });
79 }
80
81 if (!fs.existsSync('/etc/logrotate.d')) {
82 Common.printError(cst.PREFIX_MSG + '/etc/logrotate.d does not exist we can not copy the default configuration.');
83 return cb ? cb(Common.retErr('/etc/logrotate.d does not exist')) : that.exitCli(cst.ERROR_EXIT);
84 }
85
86 var templatePath = path.join(cst.TEMPLATE_FOLDER, cst.LOGROTATE_SCRIPT);
87 Common.printOut(cst.PREFIX_MSG + 'Getting logrorate template ' + templatePath);
88 var script = fs.readFileSync(templatePath, {encoding: 'utf8'});
89
90 var user = opts.user || 'root';
91
92 script = script.replace(/%HOME_PATH%/g, cst.PM2_ROOT_PATH)
93 .replace(/%USER%/g, user);
94
95 try {
96 fs.writeFileSync('/etc/logrotate.d/pm2-'+user, script);
97 } catch (e) {
98 console.error(e.stack || e);
99 }
100
101 Common.printOut(cst.PREFIX_MSG + 'Logrotate configuration added to /etc/logrotate.d/pm2');
102 return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
103 };
104
105 /**
106 * Description
107 * @method reloadLogs
108 * @return
109 */
110 CLI.prototype.reloadLogs = function(cb) {
111 var that = this;
112
113 Common.printOut('Reloading all logs...');
114 that.Client.executeRemote('reloadLogs', {}, function(err, logs) {
115 if (err) {
116 Common.printError(err);
117 return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
118 }
119 Common.printOut('All logs reloaded');
120 return cb ? cb(null, logs) : that.exitCli(cst.SUCCESS_EXIT);
121 });
122 };
123
124 /**
125 * Description
126 * @method streamLogs
127 * @param {String} id
128 * @param {Number} lines
129 * @param {Boolean} raw
130 * @return
131 */
132 CLI.prototype.streamLogs = function(id, lines, raw, timestamp, exclusive, highlight) {
133 var that = this;
134 var files_list = [];
135
136 // If no argument is given, we stream logs for all running apps
137 id = id || 'all';
138 lines = lines !== undefined ? lines : 20;
139 lines = lines < 0 ? -(lines) : lines;
140
141 // Avoid duplicates and check if path is different from '/dev/null'
142 var pushIfUnique = function(entry) {
143 var exists = false;
144
145 if (entry.path.toLowerCase
146 && entry.path.toLowerCase() !== '/dev/null') {
147
148 files_list.some(function(file) {
149 if (file.path === entry.path)
150 exists = true;
151 return exists;
152 });
153
154 if (exists)
155 return;
156
157 files_list.push(entry);
158 }
159 }
160
161 // Get the list of all running apps
162 that.Client.executeRemote('getMonitorData', {}, function(err, list) {
163 var regexList = [];
164 var namespaceList = [];
165
166 if (err) {
167 Common.printError(err);
168 that.exitCli(cst.ERROR_EXIT);
169 }
170
171 if (lines === 0)
172 return Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
173
174 Common.printOut(chalk.bold.grey(util.format.call(this, '[TAILING] Tailing last %d lines for [%s] process%s (change the value with --lines option)', lines, id, id === 'all' ? 'es' : '')));
175
176 // Populate the array `files_list` with the paths of all files we need to tail
177 list.forEach(function(proc) {
178 if (proc.pm2_env && (id === 'all' ||
179 proc.pm2_env.name == id ||
180 proc.pm2_env.pm_id == id)) {
181 if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
182 pushIfUnique({
183 path : proc.pm2_env.pm_out_log_path,
184 app_name :proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
185 type : 'out'});
186 if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
187 pushIfUnique({
188 path : proc.pm2_env.pm_err_log_path,
189 app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
190 type : 'err'
191 });
192 } else if(proc.pm2_env && proc.pm2_env.namespace == id) {
193 if(namespaceList.indexOf(proc.pm2_env.name) === -1) {
194 namespaceList.push(proc.pm2_env.name)
195 }
196 if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
197 pushIfUnique({
198 path : proc.pm2_env.pm_out_log_path,
199 app_name :proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
200 type : 'out'});
201 if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
202 pushIfUnique({
203 path : proc.pm2_env.pm_err_log_path,
204 app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
205 type : 'err'
206 });
207 }
208 // Populate the array `files_list` with the paths of all files we need to tail, when log in put is a regex
209 else if(proc.pm2_env && (isNaN(id) && id[0] === '/' && id[id.length - 1] === '/')) {
210 var regex = new RegExp(id.replace(/\//g, ''));
211 if(regex.test(proc.pm2_env.name)) {
212 if(regexList.indexOf(proc.pm2_env.name) === -1) {
213 regexList.push(proc.pm2_env.name);
214 }
215 if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
216 pushIfUnique({
217 path : proc.pm2_env.pm_out_log_path,
218 app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
219 type : 'out'});
220 if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
221 pushIfUnique({
222 path : proc.pm2_env.pm_err_log_path,
223 app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
224 type : 'err'
225 });
226 }
227 }
228 });
229
230 //for fixing issue https://github.com/Unitech/pm2/issues/3506
231 /* if (files_list && files_list.length == 0) {
232 Common.printError(cst.PREFIX_MSG_ERR + 'No file to stream for app [%s], exiting.', id);
233 return process.exit(cst.ERROR_EXIT);
234 }*/
235
236 if (!raw && (id === 'all' || id === 'PM2') && exclusive === false) {
237 Log.tail([{
238 path : cst.PM2_LOG_FILE_PATH,
239 app_name : 'PM2',
240 type : 'PM2'
241 }], lines, raw, function() {
242 Log.tail(files_list, lines, raw, function() {
243 Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
244 });
245 });
246 }
247 else {
248 Log.tail(files_list, lines, raw, function() {
249 if(regexList.length > 0) {
250 regexList.forEach(function(id) {
251 Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
252 })
253 }
254 else if(namespaceList.length > 0) {
255 namespaceList.forEach(function(id) {
256 Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
257 })
258 }
259 else {
260 Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
261 }
262 });
263 }
264 });
265 };
266
267 /**
268 * Description
269 * @method printLogs
270 * @param {String} id
271 * @param {Number} lines
272 * @param {Boolean} raw
273 * @return
274 */
275 CLI.prototype.printLogs = function(id, lines, raw, timestamp, exclusive) {
276 var that = this;
277 var files_list = [];
278
279 // If no argument is given, we stream logs for all running apps
280 id = id || 'all';
281 lines = lines !== undefined ? lines : 20;
282 lines = lines < 0 ? -(lines) : lines;
283
284 // Avoid duplicates and check if path is different from '/dev/null'
285 var pushIfUnique = function(entry) {
286 var exists = false;
287
288 if (entry.path.toLowerCase
289 && entry.path.toLowerCase() !== '/dev/null') {
290
291 files_list.some(function(file) {
292 if (file.path === entry.path)
293 exists = true;
294 return exists;
295 });
296
297 if (exists)
298 return;
299
300 files_list.push(entry);
301 }
302 }
303
304 // Get the list of all running apps
305 that.Client.executeRemote('getMonitorData', {}, function(err, list) {
306 if (err) {
307 Common.printError(err);
308 that.exitCli(cst.ERROR_EXIT);
309 }
310
311 if (lines <= 0) {
312 return that.exitCli(cst.SUCCESS_EXIT)
313 }
314
315 Common.printOut(chalk.bold.grey(util.format.call(this, '[TAILING] Tailing last %d lines for [%s] process%s (change the value with --lines option)', lines, id, id === 'all' ? 'es' : '')));
316
317 // Populate the array `files_list` with the paths of all files we need to tail
318 list.forEach(function(proc) {
319 if (proc.pm2_env && (id === 'all' ||
320 proc.pm2_env.name == id ||
321 proc.pm2_env.pm_id == id)) {
322 if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
323 pushIfUnique({
324 path : proc.pm2_env.pm_out_log_path,
325 app_name :proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
326 type : 'out'});
327 if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
328 pushIfUnique({
329 path : proc.pm2_env.pm_err_log_path,
330 app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
331 type : 'err'
332 });
333 }
334 // Populate the array `files_list` with the paths of all files we need to tail, when log in put is a regex
335 else if(proc.pm2_env && (isNaN(id) && id[0] === '/' && id[id.length - 1] === '/')) {
336 var regex = new RegExp(id.replace(/\//g, ''));
337 if(regex.test(proc.pm2_env.name)) {
338 if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
339 pushIfUnique({
340 path : proc.pm2_env.pm_out_log_path,
341 app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
342 type : 'out'});
343 if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
344 pushIfUnique({
345 path : proc.pm2_env.pm_err_log_path,
346 app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
347 type : 'err'
348 });
349 }
350 }
351 });
352
353 if (!raw && (id === 'all' || id === 'PM2') && exclusive === false) {
354 Log.tail([{
355 path : cst.PM2_LOG_FILE_PATH,
356 app_name : 'PM2',
357 type : 'PM2'
358 }], lines, raw, function() {
359 Log.tail(files_list, lines, raw, function() {
360 that.exitCli(cst.SUCCESS_EXIT);
361 });
362 });
363 }
364 else {
365 Log.tail(files_list, lines, raw, function() {
366 that.exitCli(cst.SUCCESS_EXIT);
367 });
368 }
369 });
370 };
371};