2025-05-08 23:25:06 +02:00
var chalk = require ( 'ansis' ) ;
2016-06-04 14:04:26 +02:00
var util = require ( 'util' ) ;
var fs = require ( 'fs' ) ;
var exec = require ( 'child_process' ) . exec ;
var path = require ( 'path' ) ;
var Log = require ( './Log' ) ;
var cst = require ( '../../constants.js' ) ;
var Common = require ( '../Common.js' ) ;
module . exports = function ( CLI ) {
/**
* Description
* @method flush
* @return
*/
2018-07-24 15:35:32 +03:00
CLI . prototype . flush = function ( api , cb ) {
2016-06-05 12:39:04 +02:00
var that = this ;
2018-12-18 13:48:04 +01:00
if ( ! api ) {
Common . printOut ( cst . PREFIX _MSG + 'Flushing ' + cst . PM2 _LOG _FILE _PATH ) ;
fs . closeSync ( fs . openSync ( cst . PM2 _LOG _FILE _PATH , 'w' ) ) ;
}
2016-06-04 14:04:26 +02:00
2016-06-05 12:39:04 +02:00
that . Client . executeRemote ( 'getMonitorData' , { } , function ( err , list ) {
2016-06-04 14:04:26 +02:00
if ( err ) {
Common . printError ( err ) ;
2016-06-05 14:10:05 +02:00
return cb ? cb ( Common . retErr ( err ) ) : that . exitCli ( cst . ERROR _EXIT ) ;
2016-06-04 14:04:26 +02:00
}
list . forEach ( function ( l ) {
2018-12-18 13:48:04 +01:00
if ( typeof api == 'undefined' ) {
Common . printOut ( cst . PREFIX _MSG + 'Flushing:' ) ;
Common . printOut ( cst . PREFIX _MSG + l . pm2 _env . pm _out _log _path ) ;
Common . printOut ( cst . PREFIX _MSG + l . pm2 _env . pm _err _log _path ) ;
2016-06-04 14:04:26 +02:00
2018-07-24 15:35:32 +03:00
if ( l . pm2 _env . pm _log _path ) {
Common . printOut ( cst . PREFIX _MSG + l . pm2 _env . pm _log _path ) ;
fs . closeSync ( fs . openSync ( l . pm2 _env . pm _log _path , 'w' ) ) ;
}
fs . closeSync ( fs . openSync ( l . pm2 _env . pm _out _log _path , 'w' ) ) ;
fs . closeSync ( fs . openSync ( l . pm2 _env . pm _err _log _path , 'w' ) ) ;
2016-06-04 14:04:26 +02:00
}
2023-01-20 13:59:32 +08:00
else if ( l . pm2 _env . pm _id == api || l . pm2 _env . name === api ) {
2018-12-18 13:48:04 +01:00
Common . printOut ( cst . PREFIX _MSG + 'Flushing:' ) ;
2023-01-20 13:59:32 +08:00
if ( l . pm2 _env . pm _log _path && fs . existsSync ( l . pm2 _env . pm _log _path ) ) {
2018-07-24 15:35:32 +03:00
Common . printOut ( cst . PREFIX _MSG + l . pm2 _env . pm _log _path ) ;
fs . closeSync ( fs . openSync ( l . pm2 _env . pm _log _path , 'w' ) ) ;
}
2016-06-04 14:04:26 +02:00
2023-01-20 13:59:32 +08:00
if ( l . pm2 _env . pm _out _log _path && fs . existsSync ( l . pm2 _env . pm _out _log _path ) ) {
Common . printOut ( cst . PREFIX _MSG + l . pm2 _env . pm _out _log _path ) ;
2018-07-24 15:35:32 +03:00
fs . closeSync ( fs . openSync ( l . pm2 _env . pm _out _log _path , 'w' ) ) ;
2023-01-20 13:59:32 +08:00
}
if ( l . pm2 _env . pm _err _log _path && fs . existsSync ( l . pm2 _env . pm _err _log _path ) ) {
Common . printOut ( cst . PREFIX _MSG + l . pm2 _env . pm _err _log _path ) ;
2018-07-24 15:35:32 +03:00
fs . closeSync ( fs . openSync ( l . pm2 _env . pm _err _log _path , 'w' ) ) ;
2023-01-20 13:59:32 +08:00
}
2018-07-24 15:35:32 +03:00
}
2016-06-04 14:04:26 +02:00
} ) ;
2018-12-18 13:48:04 +01:00
2016-06-04 14:04:26 +02:00
Common . printOut ( cst . PREFIX _MSG + 'Logs flushed' ) ;
2016-06-05 14:10:05 +02:00
return cb ? cb ( null , list ) : that . exitCli ( cst . SUCCESS _EXIT ) ;
2016-06-04 14:04:26 +02:00
} ) ;
} ;
2016-06-05 12:39:04 +02:00
CLI . prototype . logrotate = function ( opts , cb ) {
2016-09-18 23:32:39 +08:00
var that = this ;
2016-06-04 14:04:26 +02:00
if ( process . getuid ( ) != 0 ) {
return exec ( 'whoami' , function ( err , stdout , stderr ) {
Common . printError ( cst . PREFIX _MSG + 'You have to run this command as root. Execute the following command:' ) ;
2025-05-08 23:25:06 +02:00
Common . printError ( cst . PREFIX _MSG + chalk . gray ( ' sudo env PATH=$PATH:' + path . dirname ( process . execPath ) + ' pm2 logrotate -u ' + stdout . trim ( ) ) ) ;
2016-06-04 14:04:26 +02:00
2016-06-05 14:10:05 +02:00
cb ? cb ( Common . retErr ( 'You have to run this with elevated rights' ) ) : that . exitCli ( cst . ERROR _EXIT ) ;
2016-06-04 14:04:26 +02:00
} ) ;
}
if ( ! fs . existsSync ( '/etc/logrotate.d' ) ) {
Common . printError ( cst . PREFIX _MSG + '/etc/logrotate.d does not exist we can not copy the default configuration.' ) ;
2016-06-05 14:10:05 +02:00
return cb ? cb ( Common . retErr ( '/etc/logrotate.d does not exist' ) ) : that . exitCli ( cst . ERROR _EXIT ) ;
2016-06-04 14:04:26 +02:00
}
var templatePath = path . join ( cst . TEMPLATE _FOLDER , cst . LOGROTATE _SCRIPT ) ;
Common . printOut ( cst . PREFIX _MSG + 'Getting logrorate template ' + templatePath ) ;
var script = fs . readFileSync ( templatePath , { encoding : 'utf8' } ) ;
var user = opts . user || 'root' ;
script = script . replace ( /%HOME_PATH%/g , cst . PM2 _ROOT _PATH )
. replace ( /%USER%/g , user ) ;
try {
fs . writeFileSync ( '/etc/logrotate.d/pm2-' + user , script ) ;
} catch ( e ) {
console . error ( e . stack || e ) ;
}
Common . printOut ( cst . PREFIX _MSG + 'Logrotate configuration added to /etc/logrotate.d/pm2' ) ;
2016-06-05 14:10:05 +02:00
return cb ? cb ( null , { success : true } ) : that . exitCli ( cst . SUCCESS _EXIT ) ;
2016-06-04 14:04:26 +02:00
} ;
/**
* Description
* @method reloadLogs
* @return
*/
2016-06-05 12:39:04 +02:00
CLI . prototype . reloadLogs = function ( cb ) {
var that = this ;
2016-06-04 14:04:26 +02:00
Common . printOut ( 'Reloading all logs...' ) ;
2016-06-05 12:39:04 +02:00
that . Client . executeRemote ( 'reloadLogs' , { } , function ( err , logs ) {
2016-06-04 14:04:26 +02:00
if ( err ) {
Common . printError ( err ) ;
2016-06-05 14:10:05 +02:00
return cb ? cb ( Common . retErr ( err ) ) : that . exitCli ( cst . ERROR _EXIT ) ;
2016-06-04 14:04:26 +02:00
}
Common . printOut ( 'All logs reloaded' ) ;
2016-06-05 14:10:05 +02:00
return cb ? cb ( null , logs ) : that . exitCli ( cst . SUCCESS _EXIT ) ;
2016-06-04 14:04:26 +02:00
} ) ;
} ;
/**
* Description
* @method streamLogs
* @param {String} id
* @param {Number} lines
* @param {Boolean} raw
* @return
*/
2019-10-29 16:00:15 +05:30
CLI . prototype . streamLogs = function ( id , lines , raw , timestamp , exclusive , highlight ) {
2016-06-05 12:39:04 +02:00
var that = this ;
2016-06-04 14:04:26 +02:00
var files _list = [ ] ;
// If no argument is given, we stream logs for all running apps
id = id || 'all' ;
lines = lines !== undefined ? lines : 20 ;
lines = lines < 0 ? - ( lines ) : lines ;
// Avoid duplicates and check if path is different from '/dev/null'
var pushIfUnique = function ( entry ) {
var exists = false ;
if ( entry . path . toLowerCase
&& entry . path . toLowerCase ( ) !== '/dev/null' ) {
files _list . some ( function ( file ) {
if ( file . path === entry . path )
exists = true ;
return exists ;
} ) ;
if ( exists )
return ;
files _list . push ( entry ) ;
}
}
// Get the list of all running apps
2016-06-05 12:39:04 +02:00
that . Client . executeRemote ( 'getMonitorData' , { } , function ( err , list ) {
2017-06-06 17:45:39 +05:30
var regexList = [ ] ;
2019-11-23 13:46:27 +05:30
var namespaceList = [ ] ;
2017-07-04 20:13:15 +02:00
2016-06-04 14:04:26 +02:00
if ( err ) {
Common . printError ( err ) ;
2016-06-05 14:10:05 +02:00
that . exitCli ( cst . ERROR _EXIT ) ;
2016-06-04 14:04:26 +02:00
}
2017-05-21 07:29:19 +08:00
if ( lines === 0 )
2019-10-29 16:00:15 +05:30
return Log . stream ( that . Client , id , raw , timestamp , exclusive , highlight ) ;
2016-08-06 17:53:43 -07:00
2025-05-08 23:25:06 +02:00
Common . printOut ( chalk . bold . gray ( util . format . call ( this , '[TAILING] Tailing last %d lines for [%s] process%s (change the value with --lines option)' , lines , id , id === 'all' ? 'es' : '' ) ) ) ;
2016-06-04 14:04:26 +02:00
// Populate the array `files_list` with the paths of all files we need to tail
list . forEach ( function ( proc ) {
if ( proc . pm2 _env && ( id === 'all' ||
proc . pm2 _env . name == id ||
proc . pm2 _env . pm _id == id ) ) {
if ( proc . pm2 _env . pm _out _log _path && exclusive !== 'err' )
pushIfUnique ( {
path : proc . pm2 _env . pm _out _log _path ,
2016-08-06 17:53:43 -07:00
app _name : proc . pm2 _env . pm _id + '|' + proc . pm2 _env . name ,
2016-06-04 14:04:26 +02:00
type : 'out' } ) ;
if ( proc . pm2 _env . pm _err _log _path && exclusive !== 'out' )
pushIfUnique ( {
path : proc . pm2 _env . pm _err _log _path ,
2016-08-06 17:53:43 -07:00
app _name : proc . pm2 _env . pm _id + '|' + proc . pm2 _env . name ,
2016-06-04 14:04:26 +02:00
type : 'err'
} ) ;
2019-11-23 13:46:27 +05:30
} else if ( proc . pm2 _env && proc . pm2 _env . namespace == id ) {
if ( namespaceList . indexOf ( proc . pm2 _env . name ) === - 1 ) {
namespaceList . push ( proc . pm2 _env . name )
}
if ( proc . pm2 _env . pm _out _log _path && exclusive !== 'err' )
pushIfUnique ( {
path : proc . pm2 _env . pm _out _log _path ,
app _name : proc . pm2 _env . pm _id + '|' + proc . pm2 _env . name ,
type : 'out' } ) ;
if ( proc . pm2 _env . pm _err _log _path && exclusive !== 'out' )
pushIfUnique ( {
path : proc . pm2 _env . pm _err _log _path ,
app _name : proc . pm2 _env . pm _id + '|' + proc . pm2 _env . name ,
type : 'err'
} ) ;
2016-06-04 14:04:26 +02:00
}
2017-06-06 17:45:39 +05:30
// Populate the array `files_list` with the paths of all files we need to tail, when log in put is a regex
else if ( proc . pm2 _env && ( isNaN ( id ) && id [ 0 ] === '/' && id [ id . length - 1 ] === '/' ) ) {
var regex = new RegExp ( id . replace ( /\//g , '' ) ) ;
if ( regex . test ( proc . pm2 _env . name ) ) {
2019-05-14 14:45:55 +00:00
if ( regexList . indexOf ( proc . pm2 _env . name ) === - 1 ) {
regexList . push ( proc . pm2 _env . name ) ;
}
2017-06-06 17:45:39 +05:30
if ( proc . pm2 _env . pm _out _log _path && exclusive !== 'err' )
pushIfUnique ( {
path : proc . pm2 _env . pm _out _log _path ,
app _name : proc . pm2 _env . pm _id + '|' + proc . pm2 _env . name ,
type : 'out' } ) ;
if ( proc . pm2 _env . pm _err _log _path && exclusive !== 'out' )
pushIfUnique ( {
path : proc . pm2 _env . pm _err _log _path ,
app _name : proc . pm2 _env . pm _id + '|' + proc . pm2 _env . name ,
type : 'err'
} ) ;
}
}
2016-06-04 14:04:26 +02:00
} ) ;
2018-07-24 14:48:40 +03:00
//for fixing issue https://github.com/Unitech/pm2/issues/3506
/* if (files_list && files_list.length == 0) {
2017-12-29 00:22:30 +01:00
Common.printError(cst.PREFIX_MSG_ERR + 'No file to stream for app [%s], exiting.', id);
return process.exit(cst.ERROR_EXIT);
2018-07-24 14:48:40 +03:00
}*/
2017-12-29 00:22:30 +01:00
2016-06-04 14:04:26 +02:00
if ( ! raw && ( id === 'all' || id === 'PM2' ) && exclusive === false ) {
Log . tail ( [ {
path : cst . PM2 _LOG _FILE _PATH ,
app _name : 'PM2' ,
type : 'PM2'
} ] , lines , raw , function ( ) {
Log . tail ( files _list , lines , raw , function ( ) {
2019-10-29 16:00:15 +05:30
Log . stream ( that . Client , id , raw , timestamp , exclusive , highlight ) ;
2016-06-04 14:04:26 +02:00
} ) ;
} ) ;
}
else {
Log . tail ( files _list , lines , raw , function ( ) {
2017-06-06 17:45:39 +05:30
if ( regexList . length > 0 ) {
regexList . forEach ( function ( id ) {
2019-10-29 16:00:15 +05:30
Log . stream ( that . Client , id , raw , timestamp , exclusive , highlight ) ;
2017-06-06 17:45:39 +05:30
} )
}
2019-11-23 13:46:27 +05:30
else if ( namespaceList . length > 0 ) {
namespaceList . forEach ( function ( id ) {
Log . stream ( that . Client , id , raw , timestamp , exclusive , highlight ) ;
} )
}
2017-06-06 17:45:39 +05:30
else {
2019-10-29 16:00:15 +05:30
Log . stream ( that . Client , id , raw , timestamp , exclusive , highlight ) ;
2017-06-06 17:45:39 +05:30
}
2016-06-04 14:04:26 +02:00
} ) ;
}
} ) ;
} ;
2017-01-12 16:46:33 +01:00
/**
* Description
* @method printLogs
* @param {String} id
* @param {Number} lines
* @param {Boolean} raw
* @return
*/
CLI . prototype . printLogs = function ( id , lines , raw , timestamp , exclusive ) {
var that = this ;
var files _list = [ ] ;
// If no argument is given, we stream logs for all running apps
id = id || 'all' ;
lines = lines !== undefined ? lines : 20 ;
lines = lines < 0 ? - ( lines ) : lines ;
// Avoid duplicates and check if path is different from '/dev/null'
var pushIfUnique = function ( entry ) {
var exists = false ;
if ( entry . path . toLowerCase
&& entry . path . toLowerCase ( ) !== '/dev/null' ) {
files _list . some ( function ( file ) {
if ( file . path === entry . path )
exists = true ;
return exists ;
} ) ;
if ( exists )
return ;
files _list . push ( entry ) ;
}
}
// Get the list of all running apps
that . Client . executeRemote ( 'getMonitorData' , { } , function ( err , list ) {
if ( err ) {
Common . printError ( err ) ;
that . exitCli ( cst . ERROR _EXIT ) ;
}
if ( lines <= 0 ) {
return that . exitCli ( cst . SUCCESS _EXIT )
}
2025-05-08 23:25:06 +02:00
Common . printOut ( chalk . bold . gray ( util . format . call ( this , '[TAILING] Tailing last %d lines for [%s] process%s (change the value with --lines option)' , lines , id , id === 'all' ? 'es' : '' ) ) ) ;
2017-01-12 16:46:33 +01:00
// Populate the array `files_list` with the paths of all files we need to tail
list . forEach ( function ( proc ) {
if ( proc . pm2 _env && ( id === 'all' ||
proc . pm2 _env . name == id ||
proc . pm2 _env . pm _id == id ) ) {
if ( proc . pm2 _env . pm _out _log _path && exclusive !== 'err' )
pushIfUnique ( {
path : proc . pm2 _env . pm _out _log _path ,
app _name : proc . pm2 _env . pm _id + '|' + proc . pm2 _env . name ,
type : 'out' } ) ;
if ( proc . pm2 _env . pm _err _log _path && exclusive !== 'out' )
pushIfUnique ( {
path : proc . pm2 _env . pm _err _log _path ,
app _name : proc . pm2 _env . pm _id + '|' + proc . pm2 _env . name ,
type : 'err'
} ) ;
}
2017-06-06 17:45:39 +05:30
// Populate the array `files_list` with the paths of all files we need to tail, when log in put is a regex
else if ( proc . pm2 _env && ( isNaN ( id ) && id [ 0 ] === '/' && id [ id . length - 1 ] === '/' ) ) {
var regex = new RegExp ( id . replace ( /\//g , '' ) ) ;
if ( regex . test ( proc . pm2 _env . name ) ) {
if ( proc . pm2 _env . pm _out _log _path && exclusive !== 'err' )
pushIfUnique ( {
path : proc . pm2 _env . pm _out _log _path ,
app _name : proc . pm2 _env . pm _id + '|' + proc . pm2 _env . name ,
type : 'out' } ) ;
if ( proc . pm2 _env . pm _err _log _path && exclusive !== 'out' )
pushIfUnique ( {
path : proc . pm2 _env . pm _err _log _path ,
app _name : proc . pm2 _env . pm _id + '|' + proc . pm2 _env . name ,
type : 'err'
} ) ;
}
}
2017-01-12 16:46:33 +01:00
} ) ;
if ( ! raw && ( id === 'all' || id === 'PM2' ) && exclusive === false ) {
Log . tail ( [ {
path : cst . PM2 _LOG _FILE _PATH ,
app _name : 'PM2' ,
type : 'PM2'
} ] , lines , raw , function ( ) {
Log . tail ( files _list , lines , raw , function ( ) {
that . exitCli ( cst . SUCCESS _EXIT ) ;
} ) ;
} ) ;
}
else {
Log . tail ( files _list , lines , raw , function ( ) {
that . exitCli ( cst . SUCCESS _EXIT ) ;
} ) ;
}
} ) ;
} ;
2016-06-04 14:04:26 +02:00
} ;