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
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:
PID recycling (killing the wrong process):
/etc/init.d/foo start
: startfoo
, writefoo
'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 takingfoo
'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, findsbar
, thinks it'sfoo
, kills it, starts a newfoo
.
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.
.What if you don't even have write access or are in a read-only environment?
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.
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!- Parsing
ps
leads to a LOT of false positives. Take theps 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:
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.
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
Linux Command Ambiguous Redirect
Reading Input from Keyboard with X64 Linux Syscalls (Assembly)
How to Remove End Folder Name from a Path in Linux Script
Problems with Accessing Command Line Arguments in Linux from X86 Asm
Syntax Error of ";; Unexpected" on Simple Init Script for Debian
Using $Origin to Specify the Interpreter in Elf Binaries Isn't Working
Asp Net Core Linux Err_Connection_Refused
Netcat Tcp Programming with Bash
Any Reason for Using "*/" in Command "Ls -D */" to List Directories
Knowing If a Remote Port Forward Was Successful
Shell Script to Write and Read Data from Serial Communication
Curl Command Doesn't Work in Bash Script
Why Can't Cuda's Examples Makefile Find the Cuda Libraries
When Running Ls -L, Why Does the Filesize on a Directory Not Match the Output of Du
Delete Files with Backslash in Linux
Stack Smashing Code Not Working on Linux Kernel 2.6.38.7... Please Help
Difference Between Core and Core-File
Why Does Autoconf Erroneously Find a Function Which Isn't Available Later