How to start fastapi ,react, node server using shell script file - linux

I need to run many commands one by one to start my project instead of that i tried to put commands on shell script file
server.sh
#!/bin/bash
sudo systemctl start elasticsearch.service
sudo systemctl start kibana.service
cd fastapi
uvicorn main:app --reload --port 8000
cd ..
cd reactjs
npm i
npm start
cd ..
cd node
npm i
npm run dev
These are commands I put it in a .sh file, now problem is after uvicorn main:app --reload --port 8000 this command sh files failed to execute rest of the commands.
how to resolve this using .sh file or yaml file

You must run in background the three main scripts in your code:
uvicorn main:app --reload --port 8000 &
npm start &
npm run dev &
That & is used after a command to run this one in background, so the script will not stop in the first command (avicorn) and it will follow with the code.
And because of those commands will generate an output in the terminal (in the case you are running them from it) that output can be confused, so I would recommend redirect the output to a file for every command you run in background.
Your code could be like this:
#!/bin/bash
sudo systemctl start elasticsearch.service
sudo systemctl start kibana.service
cd fastapi
uvicorn main:app --reload --port 8000 > uvicorn.log &
cd ../reactjs
npm i
npm start > npmstart.log &
cd ../node
npm i
npm run dev > npmdev.log &
For killing those process you should use the kill command.
There are several options for killing, you can visit kill signals on Linux to understand how it works.
Or if you want to use a GUI, the system monitor might work, but you must know what PID is what you want to kill.
When a process starts this saves in $! its current PID (process ID), so you can use the next statement to show the PID:
echo $!
And when you want to kill the process, use:
kill -9 the_pid_shown_with_echo
So your code could be like this (but it's not enough in this case):
#!/bin/bash
sudo systemctl start elasticsearch.service
sudo systemctl start kibana.service
cd fastapi
uvicorn main:app --reload --port 8000 > uvicorn.log &
echo "Uvicorn ID: $!" | tee uvicornpid.txt
cd ../reactjs
npm i
npm start > npmstart.log &
echo "npm start ID: $!" | tee npmstart.txt
cd ../node
npm i
npm run dev > npmdev.log &
echo "npm run dev ID: $!" | tee npmrundev.txt
The statements with tee command like echo "Uvicorn ID: $!" | tee uvicornpid.txt are used for showing the text in the terminal and also redirect the output to a file. So you can check those files later for checking the PID's
But as I said, in this case this is not enough because unless with node this runs various process and if you kill the process by using the PID you got with $! this will kill that process (and maybe other one). But the process which is listening in that port, will stay running and when you run the app again, this will crash because the port is in use (unless you run the app in another port, but I would not recommend it).
You can use several commands for getting the PID you should kill.
The first way is using commands like:
pgrep node
This will return all PID which match with node word
ps -efl | grep -E "(node|PID)"
This will return an output with several columns and you will can see the PID of all process which match with node word and another information that might be useful.
Other useful commands the might be better for you are these:
lsof -i :4000
This will return the process running in the 4000 port (you will get the PID, the name of the process and more information)
fuser 4000/tcp
This only will return 4000/tcp and the PID of the process running in that port.
So, once you get the PID with one of those methods, you should kill the process with the kill command as I explained before.

Related

Can not start a script in monit

I have a script which have to run another script in background:
#!/bin/bash
( cd /var/lib/docker/volumes/hostcontrol-pipe/_data/ && ./run-pipe.sh ) &
Firstly it changes directory and runs a script. run-pipe.sh creates named pipes in its directory.
And I have a monit config file to monitor this script and to restart it if it's not running:
check program check-pipe with path /bin/bash -c "echo 'ping' > /var/lib/docker/volumes/hostcontrol-pipe/_data/host-pipe" with timeout 1 seconds
if status != 0 then
restart
start program = "/var/lib/docker/volumes/hostcontrol-pipe/_data/monit.sh"
First line checks the script is running writing to its pipe, it works.
The line "start program" doesn't work - the script doesn't run and it's abscent in the "ps ax". But I see in "sudo monit -vI":
'check-pipe' start: '/var/lib/docker/volumes/hostcontrol-pipe/_data/monit.sh'
'check-pipe' started
'check-pipe' program started
So, why monit cant run the script? I tried different variants, but cant run it. I can run it without changing directory (cd), but this is nessecary.
Actually monit could not run a script in background because where wasn't output. After adding output file it started to work.
start program = "/bin/bash -c 'cd /var/lib/docker/volumes/hostcontrol-pipe/_data && ./run-pipe.sh > 1.log &'"
Or otherwise /dev/null as output stream.

Make Nodejs script run in background in gitlab CI

Our dev project start by command npm run serve Is it possible to run it on background mode? I tried to use nohup, & in end of string. It works properly in shell, but when it start by CI on Gitlab, pipeline state always is "running" cause npm output permanently shows on screen
The clean way would be to run a container whose run command is "npm run serve"
I'm not certain running a non-blocking command through your pipeline is the right way but you should try using "&"
"npm run serve" will run the command in "detached mode.
I've faced the same problem using nohup and &. It was working well in shell, but not on Gitlab CI, It looks like npm start was not detached.
What worked for me is to call npm start inside a bash script and run it on before_script hook.
test:
stage: test
before_script:
- ./serverstart.sh
script:
- npm test
after_script:
- kill -9 $(ps aux | grep '\snode\s' | awk '{print $2}')
on the bash script serverstart.sh
# !/bin/bash
# start the server and send the console and error logs on nodeserver.log
npm start > nodeserver.log 2>&1 &
# keep waiting until the server is started
# (in my case wait for mongodb://localhost:27017/app-test to be logged)
while ! grep -q "mongodb://localhost:27017/app-test" nodeserver.log
do
sleep .1
done
echo -e "server has started\n"
exit 0
this allowed me to detach npm start and pass to next command while keeping npm startprocess alive

EC2 ubuntu launch node server on reboot not working

I'm trying to launch an express app when my ec2 machine starts. I've a startup script that is:
#!/bin/bash
echo "will reroute traffic" >> /home/ubuntu/log.logs
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -A INPUT -p tcp -m tcp --sport 80 -j ACCEPT
sudo iptables -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT
echo "will kill node" >> /home/ubuntu/log.logs
if pgrep node &> /dev/null ; then killall -KILL node ; fi
if pgrep nodejs &> /dev/null ; then killall -KILL nodejs ; fi
echo "will run node server" >> /home/ubuntu/log.logs
cd server && npm install && npm run build && npm run start </dev/null &>/dev/null &
echo "has run node server" >> /home/ubuntu/log.logs
If I launch it from the console, it starts the server, exits and the server runs fine.
To launch it, I've added those lines to /etc/rc.local:
rm -f /home/ubuntu/log.logs
echo "will run" >> /home/ubuntu/log.logs
/bin/bash /home/ubuntu/startup.sh
echo "has run" >> /home/ubuntu/log.logs
After rebooting, the server is not responding and it looks like it has not started (the server logs ticks when running that are not there)
the output in log.logs looks fine:
will run
will will reroute traffic
will kill node
will run node server
has run node server
has run
so everything seems to have been executed, but the node app is not running, which I confirmed by running top | grep node that returns nothing.
I found that the cheap (or free) AWS VMs got CPU/network throttled causing npm installs etc. to fail. Maybe use a VPS that is a better value or try yarn. Also make it log the npm stuff to a file instead of dev/null.
It turned out that I installed npm and node through nvm, and that nvm adds a script to .bashrc that will load those libraries. To start my script on reboot, I was using cron that is not sourcing .bashrc. Additionally, the default .bashrc on AWS EC2 ubuntu instances starts with a check on wether it's been run from a terminal or not, and escape it it's not been run from a terminal. So sourcing it from cron has no effect.
I didn't see that since the failing line
cd server && npm install && npm run build && npm run start
was not logging anything
I ended up manually sourcing the path to npm and node

Automatically start forever (node) on system restart

I am using node's forever module to keep my node server running. Forever however terminates when there is a system restart. Is there any way I can automatically start the node server (with forever) when the system restarts?
I would suggest using crontab. It's easy to use.
How to
To start editing run the following replacing the "testuser" with your desired runtime user for the node process. If you choose a different user other than yourself, you will have to run this with sudo.
$ crontab -u testuser -e
If you have never done this before, it will ask you which editor you wish to edit with. I like vim, but will recommend nano for ease of use.
Once in the editor add the following line:
#reboot /usr/local/bin/forever start /your/path/to/your/app.js
Save the file. You should get some feedback that the cron has been installed.
For further confirmation of the installation of the cron, execute the following (again replacing "testuser" with your target username) to list the currently installed crons:
$ crontab -u testuser -l
Note that in my opinion, you should always use full paths when executing binaries in cron.
Also, if the path to your forever script is not correct, run which forever to get the full path.
Given that forever calls node, you may also want to provide the full path to node:
#reboot /usr/local/bin/forever start -c /usr/local/bin/node /your/path/to/your/app.js
Further Reading
crontab Man Page
Ubuntu Cron HowTo
You can use forever-service for doing this.
npm install -g forever-service
forever-service install test
This will provision app.js in the current directory as a service via forever. The service will automatically restart every time system is restarted. Also when stopped it will attempt a graceful stop. This script provisions the logrotate script as well.
Github url: https://github.com/zapty/forever-service
NOTE: I am the author of forever-service.
Install PM2 globally using NPM
npm install pm2 -g
Start your script with pm2
pm2 start app.js
generate an active startup script
pm2 startup
NOTE: pm2 startup is for startting the PM2 when the system reboots. PM2 once started, restarts all the processes it had been managing before the system went down.
In case you want to disable the automatic startup, simply use pm2 unstartup
If you want the startup script to be executed under another user, just use the -u <username> option and the --hp <user_home>:
This case is valid for Debian.
Add the following to /etc/rc.local
/usr/bin/sudo -u {{user}} /usr/local/bin/forever start {{app path}}
{{user}} replaces your username.
{{app path}} replaces your app path. For example, /var/www/test/app.js
An alternative crontab method inspired by this answer and this blog post.
1. Create a bash script file (change bob to desired user).
vi /home/bob/node_server_init.sh
2. Copy and paste this inside the file you've just created.
#!/bin/sh
export NODE_ENV=production
export PATH=/usr/local/bin:$PATH
forever start /node/server/path/server.js > /dev/null
Make sure to edit the paths above according to your config!
3. Make sure the bash script can be executed.
chmod 700 /home/bob/node_server_init.sh
4. Test the bash script.
sh /home/bob/node_server_init.sh
5. Replace "bob" with the runtime user for node.
crontab -u bob -e
6. Copy and paste (change bob to desired user).
#reboot /bin/sh /home/bob/node_server_init.sh
Save the crontab.
You've made it to the end, your prize is a reboot (to test) :)
Copied answer from the attached question.
You can use PM2, it's a production process manager for Node.js applications with a built-in load balancer.
Install PM2
$ npm install pm2 -g
Start an application
$ pm2 start app.js
If you using express then you can start your app like
pm2 start ./bin/www --name="app"
Listing all running processes:
$ pm2 list
It will list all process. You can then stop / restart your service by using ID or Name of the app with following command.
$ pm2 stop all
$ pm2 stop 0
$ pm2 restart all
To display logs
$ pm2 logs ['all'|app_name|app_id]
You need to create a shell script in the /etc/init.d folder for that. It's sort of complicated if you never have done it but there is plenty of information on the web on init.d scripts.
Here is a sample a script that I created to run a CoffeeScript site with forever:
#!/bin/bash
#
# initd-example Node init.d
#
# chkconfig: 345
# description: Script to start a coffee script application through forever
# processname: forever/coffeescript/node
# pidfile: /var/run/forever-initd-hectorcorrea.pid
# logfile: /var/run/forever-initd-hectorcorrea.log
#
# Based on a script posted by https://gist.github.com/jinze at https://gist.github.com/3748766
#
# Source function library.
. /lib/lsb/init-functions
pidFile=/var/run/forever-initd-hectorcorrea.pid
logFile=/var/run/forever-initd-hectorcorrea.log
sourceDir=/home/hectorlinux/website
coffeeFile=app.coffee
scriptId=$sourceDir/$coffeeFile
start() {
echo "Starting $scriptId"
# This is found in the library referenced at the top of the script
start_daemon
# Start our CoffeeScript app through forever
# Notice that we change the PATH because on reboot
# the PATH does not include the path to node.
# Launching forever or coffee with a full path
# does not work unless we set the PATH.
cd $sourceDir
PATH=/usr/local/bin:$PATH
NODE_ENV=production PORT=80 forever start --pidFile $pidFile -l $logFile -a -d --sourceDir $sourceDir/ -c coffee $coffeeFile
RETVAL=$?
}
restart() {
echo -n "Restarting $scriptId"
/usr/local/bin/forever restart $scriptId
RETVAL=$?
}
stop() {
echo -n "Shutting down $scriptId"
/usr/local/bin/forever stop $scriptId
RETVAL=$?
}
status() {
echo -n "Status $scriptId"
/usr/local/bin/forever list
RETVAL=$?
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
restart
;;
*)
echo "Usage: {start|stop|status|restart}"
exit 1
;;
esac
exit $RETVAL
I had to make sure the folder and PATHs were explicitly set or available to the root user since init.d scripts are ran as root.
Use the PM2
Which is the best option to run the server production server
What are the advantages of running your application this way?
PM2 will automatically restart your application if it crashes.
PM2 will keep a log of your unhandled exceptions - in this case, in a file at /home/safeuser/.pm2/logs/app-err.log.
With one command, PM2 can ensure that any applications it manages restart when the server reboots. Basically, your node application will start as a service.
ref: https://www.digitalocean.com/community/tutorials/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps
Forever was not made to get node applications running as services. The right approach is to either create an /etc/inittab entry (old linux systems) or an upstart (newer linux systems).
Here's some documentation on how to set this up as an upstart:
https://github.com/cvee/node-upstart
crontab does not work for me on CentOS x86 6.5. #reboot seems to be not working.
Finally I got this solution:
Edit: /etc/rc.local
sudo vi /etc/rc.local
Add this line to the end of the file. Change USER_NAME and PATH_TO_PROJECT to your own. NODE_ENV=production means the app runs in production mode. You can add more lines if you need to run more than one node.js app.
su - USER_NAME -c "NODE_ENV=production /usr/local/bin/forever start /PATH_TO_PROJECT/app.js"
Don't set NODE_ENV in a separate line, your app will still run in development mode, because forever does not get NODE_ENV.
# WRONG!
su - USER_NAME -c "export NODE_ENV=production"
Save and quit vi (press ESC : w q return). You can try rebooting your server. After your server reboots, your node.js app should run automatically, even if you don't log into any account remotely via ssh.
You'd better set NODE_ENV environment in your shell. NODE_ENV will be set automatically when your account USER_NAME logs in.
echo export NODE_ENV=production >> ~/.bash_profile
So you can run commands like forever stop/start /PATH_TO_PROJECT/app.js via ssh without setting NODE_ENV again.
I wrote a script that does exactly this:
https://github.com/chovy/node-startup
I have not tried with forever, but you can customize the command it runs, so it should be straight forward:
/etc/init.d/node-app start
/etc/init.d/node-app restart
/etc/init.d/node-app stop
The problem with rc.local is that the commands are accessed as root which is different than logging to as a user and using sudo.
I solved this problem by adding a .sh script with the startup commands i want to etc/profile.d. Any .sh file in profile.d will load automatically and any command will be treated as if you used the regular sudo.
The only downside to this is the specified user needs to loggin for things to start which in my situation was always the case.
I tried lots of the above answers. None of them worked for me. My app is installed in /home and as user, not as root. This probably means that when the above mentioned start scripts run, /home is not mounted yet, so the app is not started.
Then I found these instructions by Digital Ocean:
https://www.digitalocean.com/community/tutorials/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps
Using PM2 as explained was very simple and works perfectly: My virtual servers had two physical crashes since - downtime was only about a minute.
complete example crontab (located at /etc/crontab) ..
#!/bin/bash
# edit this file with .. crontab -u root -e
# view this file with .. crontab -u root -l
# put your path here if it differs
PATH=/root/bin:/root/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
# * * * * * echo "executes once every minute" > /root/deleteme
#reboot cd /root/bible-api-dbt-server; npm run forever;
#reboot cd /root/database-api-server; npm run forever;
#reboot cd /root/mailer-api-server; npm run forever;
I have found my own solution by using serve & npm as follows:
Install serve package: npm install -g serve
Then have the command serve -s /var/www/sitename to execute on reboot.
This is what works for me on my VPS.
You can use the following command in your shell to start your node forever:
forever app.js //my node script
You need to keep in mind that the server on which your app is running should always be kept on.

How to run Node.js as a background process and never die?

I connect to the linux server via putty SSH. I tried to run it as a background process like this:
$ node server.js &
However, after 2.5 hrs the terminal becomes inactive and the process dies. Is there anyway I can keep the process alive even with the terminal disconnected?
Edit 1
Actually, I tried nohup, but as soon as I close the Putty SSH terminal or unplug my internet, the server process stops right away.
Is there anything I have to do in Putty?
Edit 2 (on Feb, 2012)
There is a node.js module, forever. It will run node.js server as daemon service.
nohup node server.js > /dev/null 2>&1 &
nohup means: Do not terminate this process even when the stty is cut
off.
> /dev/null means: stdout goes to /dev/null (which is a dummy
device that does not record any output).
2>&1 means: stderr also goes to the stdout (which is already redirected to /dev/null). You may replace &1 with a file path to keep a log of errors, e.g.: 2>/tmp/myLog
& at the end means: run this command as a background task.
Simple solution (if you are not interested in coming back to the process, just want it to keep running):
nohup node server.js &
There's also the jobs command to see an indexed list of those backgrounded processes. And you can kill a backgrounded process by running kill %1 or kill %2 with the number being the index of the process.
Powerful solution (allows you to reconnect to the process if it is interactive):
screen
You can then detach by pressing Ctrl+a+d and then attach back by running screen -r
Also consider the newer alternative to screen, tmux.
You really should try to use screen. It is a bit more complicated than just doing nohup long_running &, but understanding screen once you never come back again.
Start your screen session at first:
user#host:~$ screen
Run anything you want:
wget http://mirror.yandex.ru/centos/4.6/isos/i386/CentOS-4.6-i386-binDVD.iso
Press ctrl+A and then d. Done. Your session keeps going on in background.
You can list all sessions by screen -ls, and attach to some by screen -r 20673.pts-0.srv command, where 0673.pts-0.srv is an entry list.
This is an old question, but is high ranked on Google. I almost can't believe on the highest voted answers, because running a node.js process inside a screen session, with the & or even with the nohup flag -- all of them -- are just workarounds.
Specially the screen/tmux solution, which should really be considered an amateur solution. Screen and Tmux are not meant to keep processes running, but for multiplexing terminal sessions. It's fine, when you are running a script on your server and want to disconnect. But for a node.js server your don't want your process to be attached to a terminal session. This is too fragile. To keep things running you need to daemonize the process!
There are plenty of good tools to do that.
PM2: http://pm2.keymetrics.io/
# basic usage
$ npm install pm2 -g
$ pm2 start server.js
# you can even define how many processes you want in cluster mode:
$ pm2 start server.js -i 4
# you can start various processes, with complex startup settings
# using an ecosystem.json file (with env variables, custom args, etc):
$ pm2 start ecosystem.json
One big advantage I see in favor of PM2 is that it can generate the system startup script to make the process persist between restarts:
$ pm2 startup [platform]
Where platform can be ubuntu|centos|redhat|gentoo|systemd|darwin|amazon.
forever.js: https://github.com/foreverjs/forever
# basic usage
$ npm install forever -g
$ forever start app.js
# you can run from a json configuration as well, for
# more complex environments or multi-apps
$ forever start development.json
Init scripts:
I'm not go into detail about how to write a init script, because I'm not an expert in this subject and it'd be too long for this answer, but basically they are simple shell scripts, triggered by OS events. You can read more about this here
Docker:
Just run your server in a Docker container with -d option and, voilá, you have a daemonized node.js server!
Here is a sample Dockerfile (from node.js official guide):
FROM node:argon
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install
# Bundle app source
COPY . /usr/src/app
EXPOSE 8080
CMD [ "npm", "start" ]
Then build your image and run your container:
$ docker build -t <your username>/node-web-app .
$ docker run -p 49160:8080 -d <your username>/node-web-app
Always use the proper tool for the job. It'll save you a lot of headaches and over hours!
another solution disown the job
$ nohup node server.js &
[1] 1711
$ disown -h %1
nohup will allow the program to continue even after the terminal dies. I have actually had situations where nohup prevents the SSH session from terminating correctly, so you should redirect input as well:
$ nohup node server.js </dev/null &
Depending on how nohup is configured, you may also need to redirect standard output and standard error to files.
Nohup and screen offer great light solutions to running Node.js in the background. Node.js process manager (PM2) is a handy tool for deployment. Install it with npm globally on your system:
npm install pm2 -g
to run a Node.js app as a daemon:
pm2 start app.js
You can optionally link it to Keymetrics.io a monitoring SAAS made by Unitech.
$ disown node server.js &
It will remove command from active task list and send the command to background
I have this function in my shell rc file, based on #Yoichi's answer:
nohup-template () {
[[ "$1" = "" ]] && echo "Example usage:\nnohup-template urxvtd" && return 0
nohup "$1" > /dev/null 2>&1 &
}
You can use it this way:
nohup-template "command you would execute here"
Have you read about the nohup command?
To run command as a system service on debian with sysv init:
Copy skeleton script and adapt it for your needs, probably all you have to do is to set some variables. Your script will inherit fine defaults from /lib/init/init-d-script, if something does not fits your needs - override it in your script. If something goes wrong you can see details in source /lib/init/init-d-script. Mandatory vars are DAEMON and NAME. Script will use start-stop-daemon to run your command, in START_ARGS you can define additional parameters of start-stop-daemon to use.
cp /etc/init.d/skeleton /etc/init.d/myservice
chmod +x /etc/init.d/myservice
nano /etc/init.d/myservice
/etc/init.d/myservice start
/etc/init.d/myservice stop
That is how I run some python stuff for my wikimedia wiki:
...
DESC="mediawiki articles converter"
DAEMON='/home/mss/pp/bin/nslave'
DAEMON_ARGS='--cachedir /home/mss/cache/'
NAME='nslave'
PIDFILE='/var/run/nslave.pid'
START_ARGS='--background --make-pidfile --remove-pidfile --chuid mss --chdir /home/mss/pp/bin'
export PATH="/home/mss/pp/bin:$PATH"
do_stop_cmd() {
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 \
$STOP_ARGS \
${PIDFILE:+--pidfile ${PIDFILE}} --name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
rm -f $PIDFILE
return $RETVAL
}
Besides setting vars I had to override do_stop_cmd because of python substitutes the executable, so service did not stop properly.
Apart from cool solutions above I'd mention also about supervisord and monit tools which allow to start process, monitor its presence and start it if it died. With 'monit' you can also run some active checks like check if process responds for http request
For Ubuntu i use this:
(exec PROG_SH &> /dev/null &)
regards
Try this for a simple solution
cmd & exit

Resources