How do I write pid to file - linux

I know this could be easy, but I am unable to figure out.
We want to run two instances of luigi on one machine so need to modify init.d script to write PID to file rather than just touching empty file.
echo -n $"Starting luigid scheduler as $LUIGID_USER: "
( ( /usr/bin/sudo -u $LUIGID_USER $LUIGID_BIN >>/var/log/luigid/server.log 2>&1 ) &)
RETVAL=$?
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/luigid && echo_success || echo_failure
echo
return $RETVAL
At present its just touching the empty PID file. I want it to write PID into the file.
Also while stopping I want to kill by PID stored in PID file
echo -n $"Stopping luigid scheduler: "
killproc luigid
RETVAL=$?
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/luigid && echo_success || echo_failure
echo
Any help please ?
Thanks

You can get the PID of the previous command with $!
Change the start script to:
echo -n "Starting luigid scheduler as $LUIGID_USER: "
/usr/bin/sudo -u $LUIGID_USER $LUIGID_BIN >>/var/log/luigid/server.log 2>&1 &
RETVAL=$?
PID=$!
[ $RETVAL -eq 0 ] && echo $PID > /var/lock/subsys/luigid && echo_success || echo_failure
echo
return $RETVAL
Note you need to remove the brackets from around the command as they start the program in a subshell. The subshell will not return the PID of the started program back to your shell, so you should call it directly from your shell.

(man) shlock should do the trick for that I do believe :
shlock [-du] [-p PID] -f lockfile
...
shlock uses the link(2) system call to make the final target lock file, which
is an atomic operation (i.e. "dot locking", so named for this mechanisms
original use for locking system mailboxes). It puts the process ID ("PID")
from the command line into the requested lock file.
Or depending on the situation (man) flock, for a great example check this out :
http://codehackit.blogspot.fr/2013/04/locking-processes-with-flock.html

Related

pid file contains many integers and service won't stop though it starts successfully

I have written the below code to create a pid file for my spring boot application.
File pid = new File("service.pid");
pid.deleteOnExit();
SpringApplication springApplication = new SpringApplication(BusRouteServiceApplication.class);
springApplication.addListeners(new ApplicationPidFileWriter(pid));
springApplication.run(args);
Still the pid file gets created in the name "app.pid". And I am using the below script to start and stop the spring app.
#!/bin/bash
RUN="java -jar service-0.0.1-SNAPSHOT-exec.jar --filename=$2"
NAME=app
DATA_FILE=$2
PIDFILE=$NAME.pid
LOGFILE=/tmp/$NAME.log
start() {
if [ -f $PIDFILE ]; then
if kill -0 $(cat $PIDFILE); then
echo 'Service already running' >&2
return 1
else
rm -f $PIDFILE
fi
fi
local CMD="$RUN $DATA_FILE &> \"$LOGFILE\" & echo \$!"
sh -c "$CMD" > $PIDFILE
}
stop() {
if [ ! -f $PIDFILE ] || ! kill -0 $(cat $PIDFILE); then
echo 'Service not running' >&2
return 1
fi
kill $(cat $PIDFILE) && rm -f $PIDFILE
}
case $1 in
start)
start
;;
stop)
stop
;;
block)
start
sleep infinity
;;
*)
echo "Usage: $0 {start|stop|block} DATA_FILE"
esac
But service is not stopping. I have printed out the value of cat $PIDFILE. At times this is printing process ID + the date. At times it contains a list what looks like a lot of process ids. What am I doing wrong here? How can I correctly stop this spring boot app? I am new to spring. Any help would be much appreciated.

Bash wait for several simultaneous subprocesses and kill all on error

I'm running a bash script with multiple simultaneous commands (python scripts).
I'm trying to kill all the processes if one of them has failed.
The thing is that the python scripts are still running in the background, and if one of them has failed, my bash script doesn't know about.
Here's a snippet from my script:
set -a
trap cleanup_children SIGTERM
MY_PID=$$
function thread_listener () {
to_execute="$1"
echo "Executing $to_execute ..."
$to_execute &
PID=$!
trap 'echo killing $PID; kill $PID' SIGTERM
echo "Waiting for $PID ($to_execute) ..."
wait $PID || if `kill -0 $MY_PID &> /dev/null`; then kill $MY_PID; fi
}
function cleanup_children () {
for job in `jobs -p`
do
if `kill -0 $job &> /dev/null`; then
echo "Killing child number $job"
ps -p $job
kill $job
fi
done
}
function create_app1 () {
cd ${GIT_DIR}
python ./create-app.py -myapp
exit_code=$?
echo "Create app1 ISO result: ${exit_code}"
[ "${exit_code}" == "1" ] && exit 1
mv ${ISO_OUTPUT_DIR}/rhel-7.1.iso ${ISO_OUTPUT_DIR}/${ISO_NAME}.iso
}
function create_app2 () {
cd ${GIT_DIR}
python ./create-app.py -do-something
exit_code=$?
echo "Create app1 ISO result: ${exit_code}"
[ "${exit_code}" == "1" ] && exit 1
mv ${ISO_OUTPUT_DIR}/rhel-7.1.iso ${ISO_OUTPUT_DIR}/${ISO_NAME}.iso
}
export -f create_app1
export -f create_app2
echo "MY_PID=$MY_PID"
thread_listener create_app1 &
PID_APP1=$!
thread_listener create_app2 &
PID_APP2=$!
wait
kill $PID_APP1 2> /dev/null
kill $PID_APP2 2> /dev/null
Hm, this looks quite advanced ;). Do I assume correctly that you never see the "Create app1 ISO result" output then because the python script does not terminate? It might be an issue with the signal not being properly dispatched to bash background jobs. It might also be related to your python code not properly reacting to the signal. Have you checked out https://docs.python.org/2/library/signal.html? Sure you'd have to figure out the exact steps how to interrupt you python code while executing. I'd suggest to first make sure that the python code reacts to signals the way you want.

difference between init and control script?

I am writing a script, for the first time. I followed few examples and I have my init script and then a control script that uses the loop option, to create a copy if itself and start the final application.
My questions are:
1. What is the difference between an init script and a control script? Why is better to implement them separately?
2. Why do I need to create a copy of the control script to start the application (loop), why not do it directly with the control script? What are the benefits of doing it like this?
3. How could I improve my scripts? For example I don't know if using directly kill -9 is the best option, I have read few comments against it..
My init script is very basic:
#!/bin/bash
APPCTL="/home/app/appctl"
APPBIN="/home/app/app.cpp"
if [ ! -x "$APPCTL" -o ! -f "$APPBIN" ]; then
echo "ERROR: app is missing or is not executable" >&2
exit 1
fi
if [ "$1" = "stop" -o "$1" = "restart" ]; then
echo "Stopping app"
"$APPCTL" stop
fi
if [ "$1" = "start" -o "$1" = "restart" ]; then
echo "Starting app"
"$APPCTL" start
fi
My control script is the following:
#!/bin/sh
APP_DIR="/home/app"
APP_CTL="$APP_DIR/appctl"
APP_BIN="$APP_DIR/app.cpp"
APPCLT_PID="/var/run/appctl.pid"
OWN_PID=$$
case "$1" in
start)
if [ -f "$APPCLT_PID" ]; then
PID=$(cat "$APPCLT_PID")
fi
if [ "$PID" != "" ]; then
COMM=$(ps --pid "$PID" ho comm)
if [ "$COMM" == "appctl" ]; then
echo "Already runnning..."
exit 0
fi
fi
"$APP_CTL" loop 2>&1 &
;;
stop)
if [ -f "$APPCLT_PID" ]; then
PID=$(cat $APPCLT_PID)
if [ "$PID" != "" ]; then
kill -9 "$PID"
fi
rm -f "$APPCLT_PID"
fi
for pid in $(pgrep -f $APP_BIN); do
kill $pid
done
;;
loop)
echo $OWN_PID > "$APPCLT_PID"
cd "$APP_DIR"
while true; do
nice -n 10 "$APP_BIN" > /dev/null 2>&1
sleep 5
done
;;
esac
exit 0
Thanks.

How to rerun the process if it dies - Linux

Can any one let me know how to re-run the process automatically again if it gets dies. Below is my code which i have tired but it is giving me an error :
Edited Code :
commandpid=`$busyboxValue pidof command`
echo ${commandpid} > /sdcard/CommandProcess.txt
if [ $commandpid -gt 0 ]
then
echo -16 > /proc/$commandpid/oom_adj
echo -1000 > /proc/$commandpid/oom_score_adj
fi
while [ true ]
do
echo "PID $commandpid"
if [ ps -p $commandpid > /dev/null ]
then
echo "[$(date)] :Process is already running with PID $commandpid"
else
echo "[$(date)] :Process is not running"
/data/local/command 1200 &
commandpid=`$busyboxValue pidof command`
echo ${commandpid} > /sdcard/CommandProcess.txt
fi
sleep 10
done
I have updated the code but still with the above code multiple process id i am getting. Dose it mean my else part code is keep executing? If yes the what changes i need to do to stop it?
Can please any one help me ?
To repeatedly run a command, regardless of exit status:
while :; do command; done
To repeatedly run a command until a successful exit:
until command; do :; done

Bash script unexpected end of file

I have the following code:
#!/bin/bash -x
# Arguments:
# $1 - command to run
# $2 - time limit (in milliseconds)
# $3 - memory limit (in kilobytes)
# NOTE TO SELF: $! is the pid of last process
# NOTE TO SELF: Appending & creates new process
dir=$(mktemp -d)
ulimit -m $3
{ $1 ; "$?" > "$dir/retc" } &
pid=$!
./sleep.pl $2
if [ ps -p $pid > /dev/null ]
then
kill -9 $pid
echo "0Time Limit Exceeded"
else
echo "NAH"
ret=$(cat "$dir/retc")
if [ $ret = 9 ]
then
echo "0Memory Limit Exceeded"
else
if [ $ret = 0 ]
then
echo "1" # If it only returns one then it must be passed through final phase of verifying if result is correct
else
echo "0Received signal $ret"
fi
fi
fi
rm -r $dir
exit 0
However, it returns an error "Unexpected end of file", without executing anything in the if/else blocks.
You missed the semicolon, the redirection is wrong also:
{ $1 ; "$?"; } >"$dir/retc" &
From bash man: list must be terminated with a newline or semicolon
Also:
if [ ps -p $pid > /dev/null ]
Should be:
if [[ $(ps -p $pid >/dev/null) -eq 0 ]]
I'd recommend using () over {} to explicitly show that you're wanting to summon a subshell. Also I think you missed echo to show the value of $?.
( "$1"; echo "$?" > "$dir/etc"; ) &
With () you wouldn't need to add a semicolon in the end unlike with {} however it's still a good practice.

Resources