Linux Script Start,Stop,Restart

Linux script start,stop,restart

Which other part is the same? The way that script works is it checks the value of $1, which is the first parameter to the script supplied on the command-line. If it's 'start', then the part after start) is executed. If it's 'stop', then the part after stop) is executed. If it's 'restart', then the part after restart) is executed.

Line by line for that first part:

#! /bin/sh

Hey, it's a shell script! Specifically, execute this script using the sh shell.

test –f /usr/bin/sshd || exit 0

Is there a file called /usr/bin/sshd? If not, exit with a 0 return status.

case “$1” in

Check the value of $1, the first command-line option.

    start)

If $1 is 'start'...

            echo –n “Starting sshd: sshd”

Print "Starting sshd: sshd".

            /usr/sbin/sshd

Execute /usr/sbin/sshd.

            echo “.”

Print ".".

            ;;

Exit the case statement.

How can I make a bash script start, stop and restart in ubuntu

As mentioned in the comment, the better way to do that follow running-a-java-process-from-systemd

But if you are really interested in a bash script, then you can do something like this, but keep in mind there is might be a better approach for that.

#!/bin/bash

function start_app() {

# tested with this , uncomment your command
nohup node bin/www > logfile.txt 2>&1 &
# nohup java -Xms512m -Xmx8g -jar /data/software/190716/myapp-0.0.1.jar --server.port=8080 --spring.config.location=/data/software/myapp.properties
# write the pid to text to file to use it later
app_pid=$!
echo "Process started having PID $app_pid"
# wait for process to check proper state, you can change this time accordingly
sleep 3
if ps -p $app_pid > /dev/null
then
echo "Process successfully running having PID $app_pid"
# write if success
echo $app_pid > process_id.txt
else
echo "Process stopped before reached to steady state"
fi
}

function stop_app() {
# Get the PID from text file
application_pid=$(cat process_id.txt)
echo "stopping process, Details:"
# print details
ps -p $application_pid
# check if running
if ps -p $application_pid > /dev/null
then
# if running then kill else print message
echo "Going to stop process having PId $application_pid"
kill -9 $application_pid
if [ $? -eq 0 ]; then
echo "Process stopped successfully"
else
echo "Failed to stop process having PID $application_pid"
fi
else
echo "Failed to stop process, Process is not running"
fi
}

case "$1" in
start_app) start_app ;;
stop_app) stop_app ;;
restart) stop_app; start_app ;;
*) echo "usage: $0 start_app|stop_app|restart_app" >&2
exit 1
;;
esac

Sample Image

Functionality of a start-stop-restart shell script

1)
COMMAND="$CMD -p $PORT -l $LISTEN_IP -m $MEM_SIZE -v"-v in Unix tradition very often is a shortcut for --verbose. All those dollar signs are variable expansion (their text values are inserted into the string assigned to new variable COMMAND).

2)
ps -ef | grep -v grep | grep $( cat $PID ) - it's a pipe: ps redirects its output to grep which outputs to another grep and the end result is printed to the standard output.
grep -v grep means "take all lines that do not contain 'grep'" (grep itself is a process, so you need to exclude it from output of ps). $( $command ) is a way to run command and insert its standard output into this place of script (in this case: cat $PID will show contents of file with name $PID).

3) kill_cmd.
This function is an endless loop trying to kill the LIST of 'memcached' processes' PIDs. First, it tries to send TERM signal (politely asking each process in $LIST to quit, saving its work and shutting down correctly), gives them 2 seconds (sleep 2) to do their shutdown job and then tries to make sure that all processes are killed using signal KILL (-9), which slays the process immediately using OS facilities: if a process has not done its shutdown work in 2 seconds, it's considered hung). If slaying with kill -9 was successful, it removes the PID file and quits the loop.

ps -ef | grep -v grep | grep $CMD | grep -w $USR | awk '{print $2}' prints all PIDs of processes with name $CMD ('memcached') and user $USR ('user'). -w option of grep means 'the Whole word only' (this excludes situations where the sought name is a part of another process name, like 'fakememcached'). awk is a little interpreter most often used to take a word number N from every line of input (you can consider it a selector for a column of a text table). In this case, it prints every second word in ps output lines, that means every PID.

If you have any other questions, I'll add answers below.

Understand Bash init script start/stop/restart/

It depends on your distribution / version / configuration choices.
For Debian with System V-style startup files, please have a look to http://www.debian.org/doc/debian-policy/ch-opersys.html#s-sysvinit

Roughly, each runlevel has a directory, for example /etc/rc2.d for level 2, containing symbolic links to regular files (scripts) in /etc/init.d

At some point in time, when going to level 2, the following script loop runs

for s in /etc/rc2.d/S* 
do
$s start
done

starting the execution of all links with names starting with an S, in alphabetical order. Actually The S is followed by two digits, specifying the execution order.

Same idea for the K* files, when leaving the runlevel.

Now back to your question : this is the job of some lines in the /etc/inittab file

# The default runlevel.
id:2:initdefault:

....
# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.

l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
...

How do I write a bash script to restart a process if it dies?

Avoid PID-files, crons, or anything else that tries to evaluate processes that aren't their children.

There is a very good reason why in UNIX, you can ONLY wait on your children. Any method (ps parsing, pgrep, storing a PID, ...) that tries to work around that is flawed and has gaping holes in it. Just say no.

Instead you need the process that monitors your process to be the process' parent. What does this mean? It means only the process that starts your process can reliably wait for it to end. In bash, this is absolutely trivial.

until myserver; do
echo "Server 'myserver' crashed with exit code $?. Respawning.." >&2
sleep 1
done

The above piece of bash code runs myserver in an until loop. The first line starts myserver and waits for it to end. When it ends, until checks its exit status. If the exit status is 0, it means it ended gracefully (which means you asked it to shut down somehow, and it did so successfully). In that case we don't want to restart it (we just asked it to shut down!). If the exit status is not 0, until will run the loop body, which emits an error message on STDERR and restarts the loop (back to line 1) after 1 second.

Why do we wait a second? Because if something's wrong with the startup sequence of myserver and it crashes immediately, you'll have a very intensive loop of constant restarting and crashing on your hands. The sleep 1 takes away the strain from that.

Now all you need to do is start this bash script (asynchronously, probably), and it will monitor myserver and restart it as necessary. If you want to start the monitor on boot (making the server "survive" reboots), you can schedule it in your user's cron(1) with an @reboot rule. Open your cron rules with crontab:

crontab -e

Then add a rule to start your monitor script:

@reboot /usr/local/bin/myservermonitor

Alternatively; look at inittab(5) and /etc/inittab. You can add a line in there to have myserver start at a certain init level and be respawned automatically.


Edit.

Let me add some information on why not to use PID files. While they are very popular; they are also very flawed and there's no reason why you wouldn't just do it the correct way.

Consider this:

  1. PID recycling (killing the wrong process):

    • /etc/init.d/foo start: start foo, write foo's PID to /var/run/foo.pid
    • A while later: foo dies somehow.
    • A while later: any random process that starts (call it bar) takes a random PID, imagine it taking foo's old PID.
    • You notice foo's gone: /etc/init.d/foo/restart reads /var/run/foo.pid, checks to see if it's still alive, finds bar, thinks it's foo, kills it, starts a new foo.
  2. PID files go stale. You need over-complicated (or should I say, non-trivial) logic to check whether the PID file is stale, and any such logic is again vulnerable to 1..

  3. What if you don't even have write access or are in a read-only environment?

  4. It's pointless overcomplication; see how simple my example above is. No need to complicate that, at all.

See also: Are PID-files still flawed when doing it 'right'?

By the way; even worse than PID files is parsing ps! Don't ever do this.

  1. ps is very unportable. While you find it on almost every UNIX system; its arguments vary greatly if you want non-standard output. And standard output is ONLY for human consumption, not for scripted parsing!
  2. Parsing ps leads to a LOT of false positives. Take the ps aux | grep PID example, and now imagine someone starting a process with a number somewhere as argument that happens to be the same as the PID you stared your daemon with! Imagine two people starting an X session and you grepping for X to kill yours. It's just all kinds of bad.

If you don't want to manage the process yourself; there are some perfectly good systems out there that will act as monitor for your processes. Look into runit, for example.

start-stop-daemon run with external script condition

Inside the /etc/init.d directory is the file with the service we want to modify, for example the emqx service. We will have something like this:

do_start()
{
start-stop-daemon --start \
--name emqx \
--user emqx \
--exec /usr/local/bin/checkconditionandrun.sh emqx -- start \
|| return 2
}

case "$1" in
start)
log_daemon_msg "Starting emqx"
do_start
case "$?" in
0|1) log_end_msg 0 ;;
2) log_end_msg 1
exit 1
;;
esac
;;
stop)
log_daemon_msg "Stopping emqx"
do_stop
case "$?" in
0|1) log_end_msg 0 ;;
2) log_end_msg 1
exit 1
;;
esac
;;

The key to all this is in two things:

  1. In the do_start() function, the start-stop-daemon --start command should not directly call the "emqx start" command. A script must be called to verify what we need to verify and then that script will or will not execute the command passed as parameter.

  2. Now if we want our service to restart automatically if it has failed, as would be done through a .service with the inputs Restart=always and RestartSec=10, we must know the following:

    a) systemd supports legacy scripts /etc/init.d this way, when systemd loads service definitions, systemd-sysv-generator autogenerates .service files on the fly from the scripts in /etc/init.d.

    b) We can add configuration to an auto-generated service by adding "drop-in" files called "restart.conf" to a folder with the following name: /etc/systemd/system/servicename.service.d/

As explained above and assuming that our service is called "emqx", we can create a file in the following folder:

/etc/systemd/system/emqx.service.d/restart.conf

with the following content:

[Service]
Restart=always
RestartSec=10

In this way we achieve that a service contained in init.d can control both its startup and its subsequent reboot retry by systemd itself.

For more information about it:

https://singlebrook.com/2017/10/23/auto-restart-crashed-service-systemd/

https://www.freedesktop.org/software/systemd/man/systemd.service.html

https://www.digitalocean.com/community/tutorial_series/how-to-configure-a-linux-service-to-start-automatically-after-a-crash-or-reboot

script to check script is running and start it, if it’s stopped

You should not need to run the complete bash script again. Changing

./tg/tgcli -s ./bot/bot.lua $@

to

while :; do
./tg/tgcli -s ./bot/bot.lua $@
done

will restart bot.lua everytime it exits.

shell script to Start/Stop tomcat server

Please follow below step:

  • Save provided code in .sh file (i.e. StartStopScript.sh) at one location.
  • Update export BASE variable with you tomcat bin location.
  • Update prog variable with tomcat version.
  • IMPORTANT: run the script with argument eg.

StartStopScript.sh start to start the server

StartStopScript.sh stop to stop the server

StartStopScript.sh restart to restart the server

StartStopScript.sh status to check server status

How to run a shell script at startup

The file you put in /etc/init.d/ have to be set to executable with:

chmod +x /etc/init.d/start_my_app

As pointed out by @meetamit, if it still does not run you might have to create a symbolic link to the file in /etc/rc.d/

ln -s /etc/init.d/start_my_app /etc/rc.d/

Please note that on the latest versions of Debian, this will not work as your script will have to be LSB compliant (provide at least the following actions: start, stop, restart, force-reload, and status):
https://wiki.debian.org/LSBInitScripts

As a note, you should always use the absolute path to files in your scripts instead of the relative one, it may solve unexpected issues:

/var/myscripts/start_my_app

Finally, make sure that you included the shebang on top of the file:

#!/bin/sh


Related Topics



Leave a reply



Submit