Various core improvements and easier updating
-The update_explorer.js script has been improved with better spacing and the ability to restart the explorer automatically to ensure new changes take effect immidiately (works with npm start, pm2 and forever) -The code to compile scss to css has been moved from the prestart script into its own compile_css.js script which is now called from the update-explorer.js script to apply css changes after update -The cluster code now handles a custom restart msg which is used to restart the explorer from the update explorer process -Pm2 and Forever are now referenced by the name 'explorer' instead of ./bin/instance or ./bin/cluster [SEE IMPORTANT NOTE BELOW] -Added reload/restart scripts to the package.json for pm2 and forever -Pm2 and forever now write a pid file to the tmp directory when started. NOTE: Forever is now started from the prestart script due to a bug in forever that prevents the pid from being written to a different directory without the absolute path -Fixed a bug which caused the prestart script to be run twice when starting the explorer with `npm start` -The cluster code now accepts a numeric argument to force a specific number of instances to be loaded -The `npm run start-instance` cmd now loads using the cluster code with a single instance -The is_locked function now accepts an optional 'silent' argument to prevent displaying msgs while checking for pid/lock files -Added some process.exit statements to the stop_explorer.js file -Updated the README with cmd changes from package.json and updated description of the "Update Explorer Script" IMPORTANT NOTE: It is strongly recommended to stop the explorer before performing this update. If the explorer is running while you perform this update, you will need to stop and restart the explorer for this update to fully take effect. Because of the changes in this commit, stopping the explorer using the built-in pm2 and/or forever stop cmds will not work and you will need to type out the full stop cmd this one time only, and going forward from now on you should no longer need to even stop the explorer for any update as it is now built into the update cmd. If running using pm2 and you cannot stop the explorer, you can use stop using the following full cmd syntax: Windows: pm2 stop ./bin/instance Linux and other OS's: node node_modules/pm2/bin/pm2 stop ./bin/instance If running using forever and you cannot stop the explorer, you can use stop using the following full cmd syntax: All OS's: node node_modules/forever/bin/forever stop ./bin/cluster
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
const fs = require('fs');
|
||||
const settings = require('../lib/settings');
|
||||
|
||||
console.log('Compiling CSS.. Please wait..');
|
||||
|
||||
// ensure the selected theme is properly installed
|
||||
fs.writeFile('./public/css/_theme-selector.scss', `$theme-name: "${settings.shared_pages.theme}";`, function (err) {
|
||||
const sass = require('sass');
|
||||
|
||||
// generate minified css from style.scss file
|
||||
const minified = sass.compile('./public/css/style.scss', {style: 'compressed'});
|
||||
|
||||
// save the minified css to file
|
||||
fs.writeFile('./public/css/style.min.css', minified.css, function (err) {
|
||||
// generate minified css from custom.scss file
|
||||
const custom_minified = sass.compile('./public/css/custom.scss', {style: 'compressed'});
|
||||
|
||||
// save the minified css to file
|
||||
fs.writeFile('./public/css/custom.min.css', custom_minified.css, function (err) {
|
||||
// finished compiling css
|
||||
process.exit(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
+24
-26
@@ -33,6 +33,8 @@ if (!(nodeVersionMajor > minNodeVersionMajor || (nodeVersionMajor == minNodeVers
|
||||
}
|
||||
|
||||
function check_argument_passed(cb) {
|
||||
const pidName = (process.argv[2] != null && process.argv[2] != '' && (process.argv[2] == 'pm2' || process.argv[2] == 'forever') ? process.argv[2] : 'node');
|
||||
|
||||
// check 1st argument
|
||||
if (process.argv[2] != null) {
|
||||
const { exec } = require('child_process');
|
||||
@@ -54,11 +56,11 @@ function check_argument_passed(cb) {
|
||||
|
||||
// install pm2
|
||||
exec(`npm install pm2@latest${(isWinOS ? ' -g' : '')}`, (err, stdout, stderr) => {
|
||||
// always return true for now without checking results
|
||||
return cb(true);
|
||||
// always return the pidName for now without checking results
|
||||
return cb(pidName);
|
||||
});
|
||||
} else
|
||||
return cb(true);
|
||||
return cb(pidName);
|
||||
});
|
||||
break;
|
||||
case 'forever':
|
||||
@@ -73,42 +75,38 @@ function check_argument_passed(cb) {
|
||||
|
||||
// install forever
|
||||
exec('npm install forever', (err, stdout, stderr) => {
|
||||
// always return true for now without checking results
|
||||
return cb(true);
|
||||
// always return the pidName for now without checking results
|
||||
return cb(pidName);
|
||||
});
|
||||
} else
|
||||
return cb(true);
|
||||
return cb(pidName);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
// argument not passed or unknown argument
|
||||
return cb(true);
|
||||
return cb(pidName);
|
||||
}
|
||||
} else
|
||||
return cb(true);
|
||||
return cb(pidName);
|
||||
}
|
||||
|
||||
// check if an argument was passed into this script
|
||||
check_argument_passed(function(retVal) {
|
||||
const fs = require('fs');
|
||||
const settings = require('../lib/settings');
|
||||
check_argument_passed(function(pidName) {
|
||||
const execSync = require('child_process').execSync;
|
||||
|
||||
// ensure the selected theme is properly installed
|
||||
fs.writeFile('./public/css/_theme-selector.scss', `$theme-name: "${settings.shared_pages.theme}";`, function (err) {
|
||||
const sass = require('sass');
|
||||
// compile scss to css
|
||||
execSync('node ./scripts/compile_css.js', {stdio : 'inherit'});
|
||||
|
||||
// generate minified css from style.scss file
|
||||
const minified = sass.compile('./public/css/style.scss', {style: 'compressed'});
|
||||
// check if the webserver should be started from here based on the pidName
|
||||
if (pidName == 'forever') {
|
||||
const path = require('path');
|
||||
|
||||
// save the minified css to file
|
||||
fs.writeFile('./public/css/style.min.css', minified.css, function (err) {
|
||||
// generate minified css from custom.scss file
|
||||
const custom_minified = sass.compile('./public/css/custom.scss', {style: 'compressed'});
|
||||
// there is a long-time bug or shortcoming in forever that still exists in the latest version which requires the absolute path to the pid file option
|
||||
// more info: https://github.com/foreversd/forever/issues/421
|
||||
// forever is therefore started from here to be able to more easily resolve the absolute path
|
||||
execSync(`forever start --append --uid "explorer" --pidFile "${path.resolve('./tmp/forever.pid')}" ./bin/cluster`, {stdio : 'inherit'});
|
||||
}
|
||||
|
||||
// save the minified css to file
|
||||
fs.writeFile('./public/css/custom.min.css', custom_minified.css, function (err) {
|
||||
// Finished pre-loading
|
||||
});
|
||||
});
|
||||
});
|
||||
// finished pre-loading
|
||||
process.exit(0);
|
||||
});
|
||||
@@ -48,13 +48,16 @@ if (validate_port(settings.webserver.port) == true) {
|
||||
exec(killcmd, (err, stdout, stderr) => {
|
||||
// show shutdown msg
|
||||
console.log('Explorer shutting down... Please wait...');
|
||||
process.exit(0);
|
||||
});
|
||||
} else {
|
||||
// webserver is not running
|
||||
console.log('Error: Cannot stop explorer because it is not currently running');
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// invalid port number
|
||||
console.log('Error: webserver.port value not found in settings.json.');
|
||||
process.exit(1);
|
||||
}
|
||||
+138
-44
@@ -1,78 +1,172 @@
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
// exit function used to cleanup before finishing script
|
||||
function exit(exitCode) {
|
||||
// disconnect mongo connection
|
||||
mongoose.disconnect();
|
||||
var reloadWebserver = false;
|
||||
|
||||
// exit process
|
||||
process.exit(exitCode);
|
||||
function exit() {
|
||||
console.log('Explorer update complete');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
var response;
|
||||
function compile_css() {
|
||||
// compile scss to css
|
||||
execSync('node ./scripts/compile_css.js', {stdio : 'inherit'});
|
||||
}
|
||||
|
||||
// check if the .git directory and .git/refs/heads/master file exist
|
||||
if (fs.existsSync('./.git') && fs.existsSync('./.git/refs/heads/master')) {
|
||||
// get the current commit hash
|
||||
var commit = fs.readFileSync('./.git/refs/heads/master');
|
||||
|
||||
// check if the .git directory exists
|
||||
if (fs.existsSync('./.git')) {
|
||||
// update to newest explorer source
|
||||
console.log('Downloading newest explorer code.. Please wait..');
|
||||
console.log('Downloading newest explorer code.. Please wait..\n');
|
||||
|
||||
try {
|
||||
response = execSync('git pull');
|
||||
console.log('Git response:');
|
||||
execSync('git pull', {stdio : 'inherit'});
|
||||
|
||||
// split response string by new line
|
||||
var splitResponse = (response == null ? '' : response.toString()).split('\n').filter(element => element);
|
||||
// get the current commit hash to see if it has changed
|
||||
var new_commit = fs.readFileSync('./.git/refs/heads/master');
|
||||
|
||||
// check if the response was a single line which indicates it was already up-to-date
|
||||
if (splitResponse.length == 1) {
|
||||
// check if the commit values are the same
|
||||
if (new_commit.toString() == commit.toString()) {
|
||||
// explorer code was already up-to-date
|
||||
console.log('Explorer code is already up-to-date');
|
||||
console.log('\nExplorer code is already up-to-date');
|
||||
} else {
|
||||
console.log(response.toString().trim());
|
||||
console.log('Explorer code successfully updated');
|
||||
console.log('\nExplorer code successfully updated');
|
||||
reloadWebserver = true;
|
||||
}
|
||||
} catch(err) {
|
||||
console.log('Error updating explorer code. Maybe git is not installed globally?');
|
||||
console.log('\nError updating explorer code. Maybe git is not installed globally or you made some custom changes to the explorer code?');
|
||||
}
|
||||
} else {
|
||||
console.log('WARNING: Explorer code not cloned from github and cannot be automatically updated!');
|
||||
console.log('Skipping explorer code update');
|
||||
}
|
||||
|
||||
// update npm modules to latest versions according to package.json rules
|
||||
console.log('Updating out-of-date explorer packages.. Please wait..');
|
||||
execSync('npm update');
|
||||
var outdatedPkgs = null;
|
||||
|
||||
// check for outdated packages
|
||||
try {
|
||||
console.log('\nChecking for outdated packages.. Please wait..');
|
||||
execSync('npm outdated');
|
||||
|
||||
// all packages are up-to-date
|
||||
console.log('All explorer packages are up-to-date');
|
||||
console.log('\nAll explorer packages are up-to-date');
|
||||
} catch (err) {
|
||||
console.log(`The following packages are still out-of-date:\n${err.stdout.toString().trim()}`);
|
||||
outdatedPkgs = err.stdout.toString().trim();
|
||||
}
|
||||
|
||||
// load database and settings files after being updated
|
||||
const db = require('../lib/database');
|
||||
const settings = require('../lib/settings');
|
||||
// add a new line for better spacing
|
||||
console.log('');
|
||||
|
||||
var dbString = 'mongodb://' + encodeURIComponent(settings.dbsettings.user);
|
||||
dbString = dbString + ':' + encodeURIComponent(settings.dbsettings.password);
|
||||
dbString = dbString + '@' + settings.dbsettings.address;
|
||||
dbString = dbString + ':' + settings.dbsettings.port;
|
||||
dbString = dbString + '/' + settings.dbsettings.database;
|
||||
// check if there were any outdated packages
|
||||
if (outdatedPkgs != null) {
|
||||
// update npm modules to latest versions according to package.json rules
|
||||
console.log('Updating out-of-date explorer packages.. Please wait..\n');
|
||||
execSync('npm update');
|
||||
|
||||
// connect to mongo database
|
||||
mongoose.connect(dbString, function(err) {
|
||||
if (err) {
|
||||
console.log('Error: Unable to connect to database: %s', dbString);
|
||||
exit(999);
|
||||
} else {
|
||||
// initialize the database
|
||||
db.initialize_data_startup(function() {
|
||||
exit(0);
|
||||
});
|
||||
// check for outdated packages (again)
|
||||
try {
|
||||
execSync('npm outdated');
|
||||
|
||||
// all packages are up-to-date
|
||||
console.log('All explorer packages are up-to-date\n');
|
||||
reloadWebserver = true;
|
||||
} catch (err) {
|
||||
console.log(`The following packages are still out-of-date:\n${err.stdout.toString().trim()}\n`);
|
||||
|
||||
// check if any of the packages were updated
|
||||
if (err.stdout.toString().trim() == outdatedPkgs)
|
||||
reloadWebserver = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// check if the web server should be reloaded
|
||||
if (reloadWebserver == true) {
|
||||
console.log('Checking if webserver is running.. Please wait..\n');
|
||||
|
||||
const path = require('path');
|
||||
const lib = require('../lib/explorer');
|
||||
var pidActive = false;
|
||||
|
||||
// get a list of all files in the tmp directory
|
||||
var tmpFiles = fs.readdirSync('./tmp');
|
||||
|
||||
// get a list of all pm2 pid files
|
||||
var pm2Files = tmpFiles
|
||||
.filter(file => file.startsWith('pm2') && file.endsWith('.pid'))
|
||||
.map(file => path.basename(file, '.pid'));
|
||||
|
||||
// loop through the pm2 pid files and check if at least one is valid/active by testing the pid to see if it is running
|
||||
for (var i = 0; i < pm2Files.length; i++) {
|
||||
// check if the current pm2.pid file is valid
|
||||
if (lib.is_locked([pm2Files[i]], true) == true) {
|
||||
// this pid is active so stop checking
|
||||
pidActive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check if any pm2 pids were active
|
||||
if (pidActive == true) {
|
||||
// compile css
|
||||
compile_css();
|
||||
|
||||
console.log('\nReloading the explorer.. Please wait..\n');
|
||||
|
||||
// reload pm2 using the zero-downtime reload function
|
||||
execSync(`pm2 reload explorer`, {stdio : 'inherit'});
|
||||
|
||||
// add a new line for better spacing
|
||||
console.log('');
|
||||
|
||||
// finish the script
|
||||
exit();
|
||||
} else {
|
||||
// check if the forever pid file exists and is valid
|
||||
if (fs.existsSync('./tmp/forever.pid') && lib.is_locked(['forever'], true) == true) {
|
||||
// this pid is active
|
||||
pidActive = true;
|
||||
}
|
||||
|
||||
// check if the forever.pid is active
|
||||
if (pidActive == true) {
|
||||
// compile css
|
||||
compile_css();
|
||||
|
||||
console.log('\nReloading the explorer.. Please wait..\n');
|
||||
|
||||
// reload forever using the restart function
|
||||
execSync(`forever restart explorer`, {stdio : 'inherit'});
|
||||
|
||||
// add a new line for better spacing
|
||||
console.log('');
|
||||
|
||||
// finish the script
|
||||
exit();
|
||||
} else {
|
||||
const request = require('postman-request');
|
||||
const settings = require('../lib/settings');
|
||||
|
||||
// try executing the restart explorer api
|
||||
request({uri: `http://localhost:${settings.webserver.port}/system/restartexplorer`, timeout: 1000}, function (error, response, summary) {
|
||||
// check if there was an error
|
||||
if (error != null)
|
||||
console.log('Webserver is not runnning\n');
|
||||
else {
|
||||
// compile css
|
||||
compile_css();
|
||||
|
||||
console.log('\nReloading the explorer.. Please wait..\n');
|
||||
}
|
||||
|
||||
// finish the script
|
||||
exit();
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// finish the script
|
||||
exit();
|
||||
}
|
||||
Reference in New Issue
Block a user