Keep Track of laravel websocket with monit centos - laravel

Im trying to monitor laravel-websocket with monit instead of supervisord because of more options it provides
So In my /home/rabter/laravelwebsocket.sh :
#!/bin/bash
case $1 in
start)
echo $$ > /var/run/laravelwebsocket.pid;
exec 2>&1 php /home/rabter/core/artisan websockets:serve 1>/tmp/laravelwebsocket.out
;;
stop)
kill `cat /var/run/laravelwebsocket.pid` ;;
*)
echo "usage: laravelwebsocket.sh {start|stop}" ;;
esac
exit 0
And in etc/monit.d I made a file named cwp.laravelwebsocket with code
check process laravelwebsocket with pidfile /var/run/laravelwebsocket.pid
start program "/bin/bash -c /home/rabter/laravelwebsocket.sh start"
stop program "/bin/bash -c /home/rabter/laravelwebsocket.sh stop"
if failed port 6001 then restart
if 4 restarts within 8 cycles then timeout
unfortunately with I run monit everything starts to get monitord but laravel websocket, and it does not start once and in monit table infront I see
Process - laravelwebsocket Execution failed | Does not exist
How can I make monit monitor and start laravel-websocket on startup and on fails or errors or crashes?
I have looked into Monitor a Laravel Queue Worker with Monit
but no luck!

Your bash script inserts its own pid into your pid file. Additionally, the php process should be send to background if using monit, because monit is a monitoring tool, rather then a supervisor.
#!/usr/bin/env bash
case $1 in
start)
php /home/rabter/core/artisan websockets:serve & 2>&1 >/tmp/laravelwebsocket.out
echo $! > /var/run/laravelwebsocket.pid;
;;
stop)
kill $(cat /var/run/laravelwebsocket.pid) ;;
*)
echo "usage: $(basename $0) {start|stop}" ;;
esac
exit 0
Then make that file executable with chmod +x FILEPATH.
This should now work:
check process laravelwebsocket with pidfile /var/run/laravelwebsocket.pid
start program "/home/rabter/laravelwebsocket.sh start"
stop program "/home/rabter/laravelwebsocket.sh stop"
if failed port 6001 then restart
if 4 restarts within 8 cycles then timeout
Do you use monit as init-system for a container? If so, please let me know. Then a few more details apply.

Related

How to run program in Bash script for as long as other program runs in parallel?

I have two programs server and client. server terminates after an unknown duration. I want to run client in parallel to server (both from the same Bash script) and terminate client automatically a few seconds after the server has terminated (on its own).
How can achieve this?
I can run multiple programs in parallel from a bash script and timeout a command in Bash without unnecessary delay, but I don’t know the execution duration of server beforehand so I can’t simply define a timeout for client. The script should continue running so exiting the script to kill the child processes is not an option.
Edits
This question only addresses waiting for both processes to terminate naturally, not how to kill the client process once the server process has terminated.
#tripleee pointed to this question on Unix SE in the comments, which works especially if the order of termination is irrelevant.
#!/bin/bash
execProgram(){
case $1 in
server)
sleep 5 & # <-- change "sleep 5" to your server command.
# use "&" for background process
SERVER_PID=$!
echo "server started with pid $SERVER_PID"
;;
client)
sleep 18 & # <-- change "sleep 18" to your client command
# use "&" for background process
CLIENT_PID=$!
echo "client started with pid $CLIENT_PID"
;;
esac
}
waitForServer(){
echo "waiting for server"
wait $SERVER_PID
echo "server prog is done"
}
terminateClient(){
echo "killing client pid $CLIENT_PID after 5 seconds"
sleep 5
kill -15 $CLIENT_PID >/dev/null 2>&1
wait $CLIENT_PID >/dev/null 2>&1
echo "client terminated"
}
execProgram server && execProgram client
waitForServer && terminateClient
With GNU Parallel you can do:
server() {
sleep 3
echo exit
}
client() {
forever echo client running
}
export -f server client
# Keep client running for 5000 ms more
# then send TERM and wait 1000 ms
# then send KILL
parallel -u --termseq 0,5000,TERM,1000,KILL,1 --halt now,success=1 ::: server client

How to track process forked by bash script?

Not pure bash question, but requires a combo knowledge of bash and kubernetes cli to fully answer. I want to do some port forwarding thing with kubernetes alongside with other job (like telepresense), and my bash script doing like that:
# Killing all kubectl port forwards that might remain after previous launch.
kill $(pidof kubectl)
#run kube-proxy to tunnel port 2828 to the my pod on k8s
kubectl port-forward deployment/my 2828:2828 -n myns &
#wait for proxy to establish
sleep 10
this script has downsides
killing all kubectl, not only mine
does not kill kubectl at the end of script (could it just handle ctrl+c and "join" process gracefully instead of killing it)?
may sleep longer than needed (can i track if kubectl server is established and script can continue?)
kubectl error is not handled (should exit if error happened)
how could I solve mentioned drawbacks?
You should track the pid of the created kubectl process and possible store it in a "lock" file.
Something like: pid=$! and echo $! > lockfile
Then in the beginning of the script you could check that lockfile and and kill the process:
pid=$(<lockfile)
kill "$pid"
kubectl port-forward deployment/my 2828:2828 -n myns &
pid=$!
echo "$pid" > lockfile
This way you can also check to see if the process is already running or it have stopped:
pid=$(<lockfile)
if ps "$pid" 2>&1 >/dev/null
then
echo "Already running, no need to restart"
exit 0
fi
kubectl port-forward deployment/my 2828:2828 -n myns &
pid=$!
echo "$pid" > lockfile
This will however not work if kubectl forks and stops the parent process.

Troubles with Aerospike 3.8.x monitored with monit on CentOS 7

Since Aerospike went 3.8.0+, it changed the way the process ASD is launched. There is no more /etc/init.d/aerospike instead systemd is now used.
I have a problem as I use monit as a watchdog for aerospike and it is quite difficult to start / stop the asd process through systemd called by monit. Monit uses a limited path so maybe the problem comes from missing environment vars.
Here is what I use in monit:
check process aerospike with pidfile /var/run/aerospike/asd.pid
start = "/usr/bin/bash -c '/opt/aerospike/aerospike-service.sh start'"
stop = "/usr/bin/bash -c '/opt/aerospike/aerospike-service.sh stop'"
I'm calling explicitely a shell script so that I can add environment vars on startup.
Here is my basic shell script:
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin"
case "$1" in
start)
echo "Starting aerospike Server ..."
systemctl start aerospike.service
;;
stop)
echo "Stopping aerospike Server ..."
systemctl stop aerospike.service
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
I blindly copy-pasted my path at the start of the script. The script works if it is launched through CLI, but not if launched through monit.
I use CentOS 7.
I have not found a raw command to launch the asd process (and stop it) as it could be a way to not use systemd and sidestepping this problem.
Is there a way to configure monit to launch nicely systemd services, or are there raw commands for aerospike that can be used directly through monit?

Monit fails to start process

I've written a scrip that works fine to start and stop a server.
#!/bin/bash
PID_FILE='/var/run/rserve.pid'
start() {
touch $PID_FILE
eval "/usr/bin/R CMD Rserve"
PID=$(ps aux | grep Rserve | grep -v grep | awk '{print $2}')
echo "Starting Rserve with PID $PID"
echo $PID > $PID_FILE
}
stop () {
pkill Rserve
rm $PID_FILE
echo "Stopping Rserve"
}
case $1 in
start)
start
;;
stop)
stop
;;
*)
echo "usage: rserve {start|stop}" ;;
esac
exit 0
If I start it by running
rserve start
and then start monit it will correctly capture the PID and the server:
The Monit daemon 5.3.2 uptime: 0m
Remote Host 'localhost'
status Online with all services
monitoring status Monitored
port response time 0.000s to localhost:6311 [DEFAULT via TCP]
data collected Mon, 13 May 2013 20:03:50
System 'system_gauss'
status Running
monitoring status Monitored
load average [0.37] [0.29] [0.25]
cpu 0.0%us 0.2%sy 0.0%wa
memory usage 524044 kB [25.6%]
swap usage 4848 kB [0.1%]
data collected Mon, 13 May 2013 20:03:50
If I stop it, it will properly kill the process and unmonitor it. However if I start it again, it won't start the server again:
ps ax | grep Rserve | grep -vc grep
1
monit stop localhost
ps ax | grep Rserve | grep -vc grep
0
monit start localhost
[UTC May 13 20:07:24] info : 'localhost' start on user request
[UTC May 13 20:07:24] info : monit daemon at 4370 awakened
[UTC May 13 20:07:24] info : Awakened by User defined signal 1
[UTC May 13 20:07:24] info : 'localhost' start: /usr/bin/rserve
[UTC May 13 20:07:24] info : 'localhost' start action done
[UTC May 13 20:07:34] error : 'localhost' failed, cannot open a connection to INET[localhost:6311] via TCP
Here is the monitrc:
check host localhost with address 127.0.0.1
start = "/usr/bin/rserve start"
stop = "/usr/bin/rserve stop"
if failed host localhost port 6311 type tcp with timeout 15 seconds for 5 cycles
then restart
I had problem start or stop process via shell too.
One solution might be add "/bin/bash" in the config like this:
start program = "/bin/bash /urs/bin/rserv start"
stop program = "/bin/bash /urs/bin/rserv stop"
It worked for me.
monit is a silent killer. It does not tell you anything. Here are things I would check which monit won't help you identify
Check permissions of all the files you are reading / writing. If you are redirecting output to a file, make sure that file is writable by uid and gid you are using to execute the program
Again check exec permission on the program you are trying to run
Specify full path to any program you are trying to execute ( not strictly necessary, but you don't have to worry about path not being set if you always specify full path )
Make sure you can run the program outside of monit without any error before trying to investigate why monit is not starting.
If the Monit log is displaying
failed to start (exit status -1) -- no output
Then it may be that you're trying to run a script without any of the Bash infrastructure. You can run such a command by wrapping it in /bin/bash -c, like so:
check process my-process
matching "my-process-name"
start program = "/bin/bash -c '/etc/init.d/my-init-script'"
When monit starts it checks for its own pidfile and checks if the process with
matching PID is running already - if it does, then it just wakes up this
process.
in your case, check if this pid is being used by some other process:
ps -ef |grep 4370
if yes, then you need to remove the below file(usually under /run directory) and start monit again:
monit.pid
For me, the issue was that the stop command was not being run, even though I specifically specified "then restart" on the configuration.
The solution was just to change:
start program = "/etc/init.d/.... restart"

run nodejs forever

im runnig an http server using nodejs. i want also the server to run forever, even when my machine restarts,i want node to run again upon restart. so i created a script to put in the
/etc/init.d/
here is the script
#! /bin/sh -e
set -e
PATH=/usr/local/bin/node:/bin:/usr/bin:/sbin:/usr/sbin
DAEMON=/opt/node-v0.4.7/examples/app.js
case "$1" in
start) forever start $DAEMON ;;
stop) forever stop $DAEMON ;;
force-reload|restart)
forever restart $DAEMON ;;
*) echo "Usage: /etc/init.d/node {start|stop|restart|force-reload}"
exit 1 ;;
esac
exit 0
however when i run
/etc/init.d/node
i keep getting the same error saying
/etc/init.d/node: 13: Syntax error: word unexpected (expecting ")")
can you guys see the error ? i'm sure it's probably some easy syntax error but it's kinda late and i'm really tired.
thanks for the help
I changed the shebang from:
#! /bin/sh -e
To:
#! /bin/bash
And now that script works for me.
You can create upstart service in Ubuntu(if you use it).
Create myapp.conf in /etc/init and write something like:
start on startup
respawn
exec node /path/to/your/script.js
Then your app will start after reboot and you can manage it via start and stop commands.
And look at forever node.js module

Resources