Read each line to match a pattern - if-statement

I have the following details in a input.txt file. My requirement is to match the patterns "Stopped|Aborted|isn't running" in any of the lines, need to print that line. And if the all are in "Running" state need to print a single message that "ALL ARE RUNNING".
SVRSVC1 SVRSVC1 NAME SVRSVC1 PID Running
SVRSVC2 SVRSVC2 NAME SVRSVC2 PID Running
SVRSVC3 SVRSVC3 NAME SVRSVC3 PID Running
SVRSVC4 SVRSVC4 NAME SVRSVC4 PID Running
SVRSVC5 SVRSVC5 NAME SVRSVC5 PID isn't running
SVRSVC6 SVRSVC6 NAME SVRSVC6 PID Running
SVRSVC7 SVRSVC7 NAME SVRSVC7 PID Running
SVRSVC8 SVRSVC8 NAME SVRSVC8 PID Aborted
SVRSVC9 SVRSVC9 NAME SVRSVC9 PID Running
SVRSVC10 SVRSVC10 NAME SVRSVC10 PID Running
SVRSVC11 SVRSVC11 NAME SVRSVC11 PID Running
SVRSVC12 SVRSVC12 NAME SVRSVC12 PID Stopped
SVRSVC13 SVRSVC13 NAME SVRSVC13 PID Running
SVRSVC14 SVRSVC14 NAME SVRSVC14 PID running
Here is code i have written but i would like to know if this is the right approach or any easiest way for this. ?
#set -x
RUNTIME=`date +%Y%m%d_%H%M%S`
TOTAL_RUNSTAT=$(more input.txt | wc -l)
while read -r line; do
if [[ $line =~ Stopped|Aborted|"isn't running" ]]; then
echo $line;
elif [[ $line =~ Running ]]; then
echo $line >> runstatuslog_$RUNTIME;
if [[ `more runstatuslog_$RUNTIME | wc -l` =~ $TOTAL_RUNSTAT ]]; then
echo "ALL SERVICES RUNNING";
fi
fi
done < input.txt
Here is the expected output:
If found "Stopped|Aborted|isn't running" print the line.
SVRSVC5 SVRSVC5 NAME SVRSVC5 PID isn't running
SVRSVC8 SVRSVC8 NAME SVRSVC8 PID Aborted
SVRSVC12 SVRSVC12 NAME SVRSVC12 PID Stopped
if not found, check to see if all are running then, print message "ALL ARE RUNNING"
ALL ARE RUNNING.

It's not clear why you'd want to test for all of the nun-Running states. This will produce the output you asked for from that input:
$ awk '{lc=tolower($0)} lc~/isn\047t running$/ || lc!~/running$/{c++;print} END{if (!c) print "ALL ARE RUNNING"}' file
SVRSVC5 SVRSVC5 NAME SVRSVC5 PID isn't running
SVRSVC8 SVRSVC8 NAME SVRSVC8 PID Aborted
SVRSVC12 SVRSVC12 NAME SVRSVC12 PID Stopped
If that's not what you want then edit your question to clarify your requirements and provide more truly representative sample input/output.

Using grep
grep -E "Stopped$|Aborted$|isn't running$"
-E for extended regex
$ is to mark the end of the line
| is for logical or
Using sed
sed -nE "/Stopped$|Aborted$|isn't running$/p" file
-n to supress the output
/pattern/ is to process only lines that match the pattern
p command is to print the line
Using awk
awk '{if($NF != "Running"){i++;print}}
END{if(i == 0){printf "All are running\n"}}' file
Here we check if the last field $NF is anything but "Running", if so execute the default action, ie print the record. This will not match the running in isn't running as the match is case sensitive.

Related

How can I get the return value of `wget` from a sh script into an `int` variable

OS: Linux raspberrypi 4.19.58-v7l+ #1245 SMP Fri Jul 12 17:31:45 BST 2019 armv7l GNU/Linux
Board: Raspberry Pi 4
I have a script:
#!/bin/bash
line=$(head -n 1 /var/www/html/configuration.txt)
file=/var/www/html/4panel/url_response.txt
if [ -f "$file" ]; then
wget_output=$(wget -q -i "$line" -O $file --timeout=2)
echo "$?"
else
echo > $file
chown pi:pi $file
fi
which I call from a C++ program using:
int val_system = 0;
val_system = system("/var/www/html/4panel/get_page.sh");
std::cout<<"System return value: "<<val_system<<std::endl;
If there is something wrong with the script, echo "$?" will output the return value of wget, but val_system will always be 0.
Does system() returns the value of echo "$?" ? In which case 0 is correct. And if that is the case how can I put the return value of wget in val_system ?
I have taken a situation in which echo "$?" always returns 8, basically I've entered an incorrect URL and:
I have tried deleting echo "$?" but val_system still returned 0;
With echo "$?" deleted I have changed the wget line to wget -q -i "$line" -O $file --timeout=2 and val_system now returns 2048.
None of my attempts bared any fruit and I have come here to seek guidance. How can I make val_system / system() return what echo "$?" returns ?
How can I get the return value of wget from the script into an int variable that's inside the C++ program that calls the script ?
The integer value system() returned contains extra information about executed command's status along with its exit code, see system() and Status Information. You need to extract exit code using WEXITSTATUS macro, like:
std::cout << "System return value: " << WEXITSTATUS(val_system) << std::endl;
If you want to echo the status and return it, you will need to save the value of $? to a variable, and exit with it explicitly.
wget_output=$(wget -q -i "$line" -O $file --timeout=2)
status=$?
...
echo $status
...
exit $status
If you don't need to execute echo or any other command between the call to wget and the end of the script, you can rely on the script exiting with the last status (i.e the one corresponding to the call to `wget) implicitly.

how to save the stack trace of a linux demon/service into an external file

I have a problem with printing the stack trace (back-trace) of a demon which is created for C++ application. service is based on /etc/init.d/ init script based architecture and I have seen several services followed the same to deliver applications as services in Linux. in this case when stopping my service by service name stop stack trace of the program is printing on the console. This backtrace contains the uncleaned memory map of the program.
I just need to avoid printing this on the terminal and save it into a separate file till I fix the memory issues of the program.
EDITED:
Can this do by adding more commands to the init script ?
Is there any compilation option to avoid printing the program
stack-trace after stopping the program ?
Can a block of c/c++ source code use to handle this ?
Below is my /etc/init.d/init script.
# Source function library.
. /etc/rc.d/init.d/functions
cscored=${CSCORED-/opt/application-name/bin/cscore &}
prog=cscored
pidfile=${PIDFILE-/var/run/cscored/cscored.pid}
lockfile=${LOCKFILE-/var/lock/subsys/cscored}
RETVAL=0
STOP_TIMEOUT=${STOP_TIMEOUT-10}
start() {
echo -n $"Starting $prog: "
daemon $cscored
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch ${lockfile}
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc $cscored
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
}
reload() {
echo -n $"Reloading $prog: "
if ! $cscored -t >&/dev/null; then
RETVAL=6
echo $"not reloading due to configuration syntax error"
failure $"not reloading $cscored due to configuration syntax error"
else
# Force LSB behaviour from killproc
LSB=1 killproc -p ${pidfile} $cscored -HUP
RETVAL=$?
if [ $RETVAL -eq 7 ]; then
failure $"cscored shutdown"
fi
fi
echo
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status $cscored
RETVAL=$?
;;
restart)
stop
start
;;
condrestart|try-restart)
if status $cscored >&/dev/null; then
stop
start
fi
;;
force-reload|reload)
reload
;;
*)
echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|reload|status|fullstatus|graceful|help|configtest}"
RETVAL=2
esac
exit $RETVAL
You can redirect the output of the console to another file either using a pipe or dup().

How to exit calling script in csh?

I have a csh script (a.csh) which calls another (./b.csh). How do I exit from a.csh if some condition is not satisfied while running b.csh?
Here is how I call b.csh
b.csh >&! b.csh.log
There is a related question for bash How to exit all the calling scripts in bash?.
Inside b.csh, use this to terminate a.csh without terminating b.csh:
set PPID = `ps -ef | awk -v pid="$$" '{if ($2 == pid) {print $3}}'`
kill $PPID
In bash-like shells, $PPID is defined, but for csh we have to extract it manually.
$$ returns the current process ID (pid) (that is, the pid of b.csh).

How can I reliably launch multiple DJango FCGI servers at startup?

I currently use the following script to launch my DJango FCGI servers:
#!/bin/bash
MYAPP=$1
PIDFILE=/var/run/${MYAPP}_fcgi.pid
SOCKET=/var/django/${MYAPP}/socket.sock
MANAGESCRIPT=/var/django/${MYAPP}/manage.py
# Maximum requests for a child to service before expiring
#MAXREQ=
# Spawning method - prefork or threaded
#METHOD=
# Maximum number of children to have idle
MAXSPARE=2
# Minimum number of children to have idle
MINSPARE=1
# Maximum number of children to spawn
MAXCHILDREN=3
cd "`dirname $0`"
function failure () {
STATUS=$?;
echo; echo "Failed $1 (exit code ${STATUS}).";
exit ${STATUS};
}
function start_server () {
$MANAGESCRIPT runfcgi socket=$SOCKET pidfile=$PIDFILE \
${MAXREQ:+maxrequests=$MAXREQ} \
${METHOD:+method=$METHOD} \
${MAXSPARE:+maxspare=$MAXSPARE} \
${MINSPARE:+minspare=$MINSPARE} \
${MAXCHILDREN:+maxchildren=$MAXCHILDREN} \
${DAEMONISE:+damonize=True}
touch $SOCKET
chown www-data:www-data $SOCKET
chmod 755 $SOCKET
}
function stop_server () {
if [ -f "$PIDFILE" ]
then
kill `cat $PIDFILE` || failure "Server was not running."
rm $PIDFILE
fi
}
DAEMONISE=$3
case "$2" in
start)
echo -n "Starting fcgi: "
[ -e $PIDFILE ] && { echo "PID file exsts."; exit; }
start_server || failure "starting fcgi"
echo "Done."
;;
stop)
echo -n "Stopping fcgi: "
[ -e $PIDFILE ] || { echo "No PID file found."; exit; }
stop_server
echo "Done."
;;
restart)
echo -n "Restarting fcgi: "
[ -e $PIDFILE ] || { echo -n "No PID file found..."; }
stop_server
start_server || failure "restarting fcgi"
echo "Done."
;;
*)
echo "Usage: $0 {start|stop|restart} [--daemonise]"
;;
esac
exit 0
Which I manually call like this:
/var/django/server.sh mysite start
This works fine but when my hosting company reboots our server it leaves me two issues:
I don't have an automated way to launch multiple sites.
I end up with a mysite_fcgi.pid file existing but no associated process.
So I have two questions:
How can I launch a list of sites (stored in a plain text file) automatically on startup? i.e. call /var/django/server.sh mysite1 start then /var/django/server.sh myothersite start?
How can I get rid of the .pid file if the process doesn't exist and attempt to start the server as normal?
Create an init script and assign it to the appropriate runlevel.
You need to implement this in your startup/init script (that you would write in step 1)
Or, use a process manager like supervisord which takes care of all your concerns.
Here is a configuration example for fcgi from supervisord.
[fcgi-program:fcgiprogramname]
command=/usr/bin/example.fcgi
socket=unix:///var/run/supervisor/%(program_name)s.sock
process_name=%(program_name)s_%(process_num)02d
numprocs=5
priority=999
autostart=true
autorestart=unexpected
startsecs=1
startretries=3
exitcodes=0,2
stopsignal=QUIT
stopwaitsecs=10
user=chrism
redirect_stderr=true
stdout_logfile=/a/path
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
stderr_logfile=/a/path
stderr_logfile_maxbytes=1MB
stderr_logfile_backups
environment=A=1,B=2
How can I launch a list of sites (stored in a plain text file) automatically on startup?
In general, your OS provides a file where you can hook your commands at startup. For example, arch linux uses rc.local, gentoo either /etc/local.start either /etc/local.d/*.start, debian requires you to make an init script - which is basically a script that takes "start" or "stop" as argument and lives in /etc/init.d or /etc/rc.d depending on the distribution ...
You can use some bash code as such.
for site in $(</path/to/text/file); do
/var/django/server.sh $site start
done
How can I get rid of the .pid file if the process doesn't exist and attempt to start the server as normal?
if [[ -f $PIDFILE ]]; then # if pidfile exists
if [[ ! -d /proc/$(<$PIDFILE)/ ]]; then # if it contains a non running proc
unlink $PIDFILE # delete the pidfile
fi
fi

sos Job scheduler

i am using sos job scheduler which support many language.i accept the shell script to write jobs but i am not a shell script writer.i want to implement a following points in job scheduler:
execute a shell script A. script A return "success" if time is between 6:00AM and 3PM.else it return "fail".
on "success" execute a shell script C or on "Fail" it execute shell script B.
Script B and Script C send email with“Success” or “Failure” in subject line.
please help me to sortout the above discuss problem.
Thanks
There are two command line utilities that are helpful in this case:
date: Displays the current time/date in a specified format.
mail: Sends e-mail from the command line.
Since we only need the full hour for our logic I use the date format "+%H" (hour from 0-23). This gives the following script basis:
#!/bin/sh
hour=$(date +%H)
if [ $hour -gt 6 -a $hour -lt 15 ]; then
echo "message body" | mail -s Success <your e-mail address>
else
echo "message body" | mail -s Failure <your e-mail address>
fi
#!/bin/bash
hour=$(date +%H)
recipient="root"
case "$hour" in
[6-9]|1[0-5])
subject="success"
body="message"
;;
*)
subject="failure"
body="message"
;;
esac
echo $body | mailx -s "$subject" "$recipient"