I have a script called update.sh that updates the server.
Problem is; when I stop the PM2 process it ends the bash process(?) there.
I can't figure out how to spawn a process from the parent that isn't linked to the parent. :-S
update.sh
#!/bin/bash
# Check we are not already updating.
if [ -f update.lock ]; then
echo "Already updating. Locked."
exit
fi
# Make the log file.
rm update.log
touch update.log
# Create update lock.
touch update.lock
echo "Cleaning up" | tee update.log
rm -rf the-last-word
rm -rf Server
echo "Retrieving files from BitBucket" | tee update.log
git clone git@bitbucket.org:dotdot/dot-project.git
# Remove all directories except Server (So we don't have game source code on the Server)
echo "Removing game source code" | tee update.log
cd the-last-word
# Move the Server directory one up.
mv Server ../
cd ../
rm -rf the-last-word
# Stop the previous server.
# == PM2 stop some server name.
echo "Stopping server & removing" | tee update.log
pm2 delete "Some App" | tee update.log
# Update the current & run.
echo "Installing node modules" | tee update.log
cd Server
npm install | tee update.log
# Start the server again
# == PM2 start some server name.
echo "Starting node server" | tee update.log
NODE_ENV=production pm2 start bin/www.js --name "Some App" | tee update.log
# Remove lock file.
cd ..
rm update.lock
Now I run this script using node (express route).
admin.js
// Update server
app.use("/admin/update", authMiddleware, function(req, res, next) {
console.log('Updating server from script.');
const { spawn } = require('child_process');
const deploySh = spawn('sh', [ 'update.sh' ], {
cwd: '/www/thelastword/',
env: Object.assign({}, process.env, { PATH: process.env.PATH + ':/usr/local/bin' })
});
res.status(200).json('Updating Server');
});
If admin.js
is part of the server process, try nohup
const deploySh = spawn('sh', [ 'nohup ./update.sh' ], {
cwd: '/www/thelastword/',
env: Object.assign({}, process.env, { PATH: process.env.PATH + ':/usr/local/bin' })
});
nohup
allow child process to run even parent is killed.
Quote from https://unix.stackexchange.com/questions/137759/why-use-nohup-rather-than-exec :
nohup runs the specificed program with the SIGHUP signal ignored. When a terminal is closed, the kernel sends SIGHUP to the controlling process in that terminal (i.e. the shell). The shell in turn sends SIGHUP to all the jobs running in the background. Running a job with nohup prevents it from being killed in this way if the terminal dies (which happens e.g. if you were logged in remotely and the connection drops, or if you close your terminal emulator).
Reference:
I did a simple test and bash did not exit after pm2 delete
.
dummy-server.js
var pid = require('process').pid;
var server = require('net').createServer().listen();
test.sh
echo "start dummy."
pm2 start ./dummy-server.js --name 'Dummy'
echo "stop dummy."
pm2 delete 'Dummy'
echo "Sleep 5sec"
sleep 5
echo "Done."
Output:
start dummy.
[PM2] Starting ./dummy-server.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ memory │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────────────┼──────────┤
│ Dummy │ 0 │ fork │ 9328 │ online │ 0 │ 0s │ 15.219 MB │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
stop dummy.
[PM2] Applying action deleteProcessId on app [Dummy](ids: 0)
[PM2] [Dummy](0) ✓
┌──────────┬────┬──────┬─────┬────────┬─────────┬────────┬────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ memory │ watching │
└──────────┴────┴──────┴─────┴────────┴─────────┴────────┴────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
Sleep 5sec
Done.
update.sh
is deleting/changing the server directory before stopping it. Sometimes that can create unexpected/strange behavior.
I modified update.sh
as follow:
#!/bin/bash
# Check we are not already updating.
if [ -f update.lock ]; then
echo "Already updating. Locked."
exit
fi
# Make the log file.
rm update.log
touch update.log
# Create update lock.
touch update.lock
# --- Stop server before deleting its directory!
# Stop the previous server.
# == PM2 stop some server name.
echo "Stopping server & removing" | tee update.log
pm2 delete "Some App" | tee update.log
echo "Cleaning up" | tee update.log
rm -rf the-last-word
rm -rf Server
echo "Retrieving files from BitBucket" | tee update.log
git clone git@bitbucket.org:dotdot/dot-project.git
# Remove all directories except Server (So we don't have game source code on the Server)
echo "Removing game source code" | tee update.log
cd the-last-word
# Move the Server directory one up.
mv Server ../
cd ../
rm -rf the-last-word
# Update the current & run.
echo "Installing node modules" | tee update.log
cd Server
npm install | tee update.log
# Start the server again
# == PM2 start some server name.
echo "Starting node server" | tee update.log
NODE_ENV=production pm2 start bin/www.js --name "Some App" | tee update.log
# Remove lock file.
cd ..
rm update.lock