Displayining multiple bash output horizontally - linux

I have 4 important services running on my machine which I want to see them all the time. I have this simple bash script running as bash profile.
echo
PROC="nginx mysql php-fpm pptpd"
for p in $PROC
do
ps cax | grep $p > /dev/null
if [ $? -eq 0 ]; then
echo -e "\e[92m$p running\e[0m"
else
echo -e "\e[101m$p IS NOT RUNNING \e[0m"
fi
done
echo
The out put of this script is:
nginx running
mysql running
php-fpm running
pptpd running
How can I make it like this?
nginx running - mysql running - php-fpm running - pptpd running

Build the status lines first into an array, and then print the array:
status=()
for p in $PROC
do
if ps cax | grep -q $p; then
status+=( " \e[92m$p running\e[0m " )
else
status+=( " \e[101m$p IS NOT RUNNING \e[0m " )
fi
done
(IFS=-; echo -e "${status[*]}")
${status[*]} expands to every element in the array joined by the first character of IFS, which I set to - earlier. Note that I used a subshell (IFS=-; echo ...), so that changing IFS doesn't affect the rest of the script.
Other notes:
ps cax | grep $p > /dev/null
if [ $? -eq 0 ]; then
Can be combined to:
if ps cax | grep -q $p; then
Which is much more concise and readable. You could also consider using pgrep instead.

Use printf or add the -n flag to echo.
POSIX Compliant Refactor without ProcTools
#!/bin/sh
showstatus() {
echo
while [ "$1" ]; do
if ps cax | grep -qF "$1"; then
msg='\e[92m%s running\e[0m'
else
msg='\e[101m%s IS NOT RUNNING \e[0m'
fi
printf "$msg" "$1"
shift
[ "$1" ] && printf ' - '
done
echo
}
showstatus nginx mysql php-fpm pptpd
POSIX Compliant Refactor with ProcTools
#!/bin/sh
showstatus() {
echo
while [ "$1" ]; do
if pkill -0 "$1"; then
msg='\e[92m%s running\e[0m'
else
msg='\e[101m%s IS NOT RUNNING \e[0m'
fi
printf "$msg" "$1"
shift
[ "$1" ] && printf ' - '
done
echo
}
showstatus nginx mysql php-fpm pptpd

Related

Bash script: read 30000 records from file and run multiple process in parallel

txt with more than 30000 records.
All records are one for line and is an IP like this:
192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4
192.168.0.5
192.168.0.6
192.168.0.7
192.168.0.8
192.168.0.9
192.168.0.10
I read each row in a bash script, and I need to run a curl like this:
while IFS= read -r line || [[ -n "$line" ]]; do
#check_site "$line"
resp=$(curl -i -m1 http://$line 2>&1)
echo "$resp" | grep -Eo "$ok" > /dev/null
if [ $? -ne 0 ]; then
#echo -e "failed: $line" >> "${logfile}"
echo -e "Command: curl -i -m1 http://$line 2>&1" >> "${outfile}"
echo -e "failed: $line:\n\n \"$resp\"\n\n" >> "${outfile}"
echo "$line" >> "${faillog}"
fi
done < "${FILE}"
Is there a method to run multiple lines simultaneously in my file to reduce the execution time?
I solved for the multiprocess in this way:
#export variable to be used into function
export outlog="/tmp/out.log"
export faillog="/tmp/fail.log"
export ok="(curl: \(7\) Failed to connect to)" # acceptable responses
# create function:
check_site() {
ip=$1
resp=$(curl -i -m1 http://$ip 2>&1)
echo "$resp" | grep -Eo "$ok" > /dev/null
if [ $? -ne 0 ]; then
echo -e "Command: curl -i -m1 http://$ip 2>&1" >> "${outlog}"
echo -e "Block failed: $ip:\n\n \"$resp\"\n\n" >> "${outlog}"
echo "$ip" >> "${faillog}"
fi
}
# call the function:
export -f check_site
parallel -j 252 -a "${FILE}" check_site
Xargs will do the trick. Wikipedia
This article describe approach to resolve parallel execution, it may help you:
Parallel execution in Bash
Example from the article:
#!/bin/bash
RANDOM=10
JOBS_COUNTER=0
MAX_CHILDREN=10
MY_PID=$$
for i in {1..100}
do
echo Cycle counter: $i
JOBS_COUNTER=$((`ps ax -Ao ppid | grep $MY_PID | wc -l`))
while [ $JOBS_COUNTER -ge $MAX_CHILDREN ]
do
JOBS_COUNTER=$((`ps ax -Ao ppid | grep $MY_PID | wc -l`))
echo Jobs counter: $JOBS_COUNTER
sleep 1
done
sleep $(($RANDOM % 30)) &
done
echo Finishing children ...
# wait for children here
while [ $JOBS_COUNTER -gt 1 ]
do
JOBS_COUNTER=$((`ps ax -Ao ppid | grep $MY_PID | wc -l`))
echo Jobs counter: $JOBS_COUNTER
sleep 1
done
echo Done

Port Scanner on with Bash

#!/bin/bash
host=$1
startport=$2
stopport=$3
function pingcheck
{
ping = `ping -c 1 $host | grep bytes | wc -l`
if [ $ping > 1 ]; then
echo "$host is up";
else
echo "$host is down quitting";
exit
fi
}
function portcheck
{
for ((counter=$startport; counter<=$stopport; counter++))
do
(echo > /dev/tcp/$host/$counter) > /dev/null 2>&1 && echo "$counter open"
done
}
pingcheck
portcheck
I tried testing the script by passing 127.0.0.1 1 5 to it from the terminal but all i keep getting is ping: unknown host =
127.0.0.1 is down quitting. Tried with other IP Addresses as well, I got the same output. I was following instruction from a book as I am new to shell scripting. It will be helpful if someone can tell me what I am doing wrong.
I made some comments inline:
#!/bin/bash
host=$1
startport=$2
stopport=$3
function pingcheck
{
ping=`ping -c 1 $host | grep bytes | wc -l` #Don't use spaces before and after the "="
if [ $ping -gt 1 ]; then #Don't use >, use -gt
# if [[ $ping > 1 ]]; then #Or use [[ and ]], but this won't work in all shells
echo "$host is up";
else
echo "$host is down quitting";
exit
fi
}
function portcheck
{
for ((counter=$startport; counter<=$stopport; counter++))
do
(echo > /dev/tcp/$host/$counter) > /dev/null 2>&1 && echo "$counter open"
done
}
pingcheck
portcheck
Variables in bash are always in the format:
VARNAME=VALUE
You should not put spaces in between there. VALUE could be an expression using `` or using $(). $() is usually the preferred way, because you can do $(something $(something)) and you can't do `something `something``.
The syntax of if is:
if EXPRESSION
then
something
fi
An expression is in sh always a call to an application. [ is an application usually used in ifs. You can get a really good manual of [ by doing man [. Bash has native support for [[, which isn't an application, but can do more than [.

Environmental variables are not loading while running service startup script

when i start service script with ./script start able to get the credentials through proxy (Environment variables found), if i start the service script like service script start not able to get the credentials through proxy(Environment variables not found), Proxy was not found. How can i work this script through service script start?
script :
#!/bin/bash -l
# chkconfig: 2345 20 80
if [ "$system" = "redhat" ]; then
## source platform specific external scripts
. /etc/init.d/functions
## set or override platform specific variables
lockfile=${LOCKFILE-/var/lock/subsys/$SERVICE_NAME}
## set or override platform specific functions
start_daemon() {
daemon --user $1 --pidfile $2 "$3 $4"
}
log_daemon_msg() {
echo -n $"$1"
}
echo_ok() {
echo_success; echo
}
echo_fail() {
echo_failure; echo
}
log_success_msg() {
success $"$#"
}
log_failure_msg() {
failure $"$#"
echo $"$#"
}
log_action_msg() {
echo $#
}
fi
if [ -n "$http_proxy" ] ; then
echo "proxy found"
echo $http_proxy | grep "#"
if [ $? -eq 0 ]; then
PROXY_HOST=$(echo $http_proxy | sed 's/http:\/\/.*#\(.*\):.*/\1/')
PROXY_PORT=$(echo $http_proxy | sed 's/http:\/\/.*#.*:\(.*\)/\1/' | tr -d "/")
USERNAME=$(echo $http_proxy | sed 's/http:\/\/\(.*\)#.*/\1/'|awk -F: '{print $1}')
PASSWORD=$(echo $http_proxy | sed 's/http:\/\/\(.*\)#.*/\1/'|awk -F: '{print $2}')
else
PROXY_HOST=$(echo $http_proxy | sed 's/http:\/\/\(.*\):.*/\1/')
PROXY_PORT=$(echo $http_proxy | sed 's/http:\/\/.*:\(.*\)/\1/' | tr -d "/")
fi
fi
start() {
echo "Starting $SERVICE_NAME ..."
if [ ! -f $PID_PATH_NAME ]; then
CMD="java "
if [ -n "$PROXY_HOST" -a -n "$PROXY_PORT" ] ; then
CMD="java -Dhttps.proxyHost=$PROXY_HOST -Dhttps.proxyPort=$PROXY_PORT"
if [ -n "$USERNAME" -a -n "$PASSWORD" ]; then
CMD="$CMD -Dhttps.proxyUser=$USERNAME -Dhttps.proxyPassword=$PASSWORD"
fi
fi
#nohup $CMD -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &
#echo "$PATH_TO_JAR"
echo "$CMD"
nohup $CMD -jar $PATH_TO_JAR 2>> /tmp/glog >> /tmp/glog &
echo $! > $PID_PATH_NAME
echo "$SERVICE_NAME started ..."
else
echo "$SERVICE_NAME is already running ..."
fi
}
case "$1" in
start)
start
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
esac
exit 0
When i am running this script like ./script start, script able to find proxy settings and passing the proxy settings. But while running with service script start not able to find proxy settings. Did i miss anything to load environment variables while running script with service?
From man service:
service runs a System V init script in as predictable environment as possible, removing most environment variables and with current working directory set to /.
So when you try to run a service script, only several env variables like TERM, LANG remains, your http_proxy and https_proxy is discarded. To use environment variables you need, you could define them in file /etc/default/yourservice with:
http_proxy=http://yourproxy.com
https_proxy=http://yourproxy.com
and source it in the beginning of your script:
[ -f /etc/default/yourservice ] && . /etc/default/yourservice

Shell script to find the process state while excluding 'ps grep command'

can someone guide me writing shell script to find if the process is active or not? I have to exclude my own grep process filtering from ps command. I want to pass the process as a parameter,
script: (this is currently catching my own process)
#!/bin/sh
SERVICE=$1
echo $1
if ps ax | grep $SERVICE > /dev/null
then
echo "ok"
else
echo "not ok"
fi
example input tried: (though the process is dead I'm getting status as "ok")
./processchecker.sh '/usr/sbin/mysqld'
./processchecker.sh '[/usr/sbin/]mysqld' (i tried using square brackets using online suggestions but failed)
Please help.
You can use pgrep as well - which is a little more efficient:
#!/bin/sh
service=$1
status=0
if [ ! -z "$service" ]; then
pgrep "$service" >/dev/null; status=$?
if [ "$status" -eq 0 ]; then
echo "ok"
else
echo "not ok"
fi
fi
exit "$status"
It's better to have an appropriate exit value as well.
What you have is close, but you want to save the status of the grep command (via $?) and then if/else off of that value.
#!/bin/sh
SERVICE=$1
echo $1
ps ax | grep $SERVICE | grep -v ${0} > /dev/null
status=${?}
if [ "${status}" = "0" ]; then
echo "ok"
else
echo "not ok"
fi

Check if a program in a specific path is running

I am trying to check if a process is running with the code below:
SERVICE="./yowsup/yowsup-cli"
RESULT=`ps aux | grep $SERVICE`
if [ "${RESULT:-null}" = null ]; then
echo "not running"
else
echo "running"
fi
But it keeps echoing it is running although it is not. I realized that the grep itself comes as a result and that is the issue.
How can I skip the grep and just check for the process?
Use pgrep:
if pgrep "$SERVICE" >/dev/null 2>&1 ; then
echo "$SERVICE is running"
fi
or:
if pgrep -f "/path/to/$SERVICE" >/dev/null 2>&1 ; then
echo "$SERVICE is running"
fi
NOTE:
pgrep interprets its argument as a regular expression. As a result, paths containing regex characters will likely fail to match or produce false positives (e.g. pgrep -f /home/user/projects/c++/application/executable won't work as expected due to +). This issue can be worked around by escaping the characters in question (e.g. pgrep -f /home/user/projects/c\+\+/application/executable)
pgrep -f <pattern> matches the specified pattern against the whole command line of running processes. As a result, it will match paths appearing as arguments of other processes (e.g. run nano /usr/bin/sleep in one terminal and pgrep -f /usr/bin/sleep in another -> pgrep reports the pid of nano since it contains /usr/bin/sleep as an argument in its command line). To prevent these kind of false positives, prefix the pattern with a caret (^) to force pgrep to only match against the beginning of the command line (e.g. pgrep -f ^/usr/bin/sleep)
For systems where pgrep isn't available you can use:
service="[.]/yowsup/yowsup-cli"
if ps aux | grep -q "$service"; then
echo "not running"
else
echo "running"
fi
[.] in will force grep to not list itself as it won't match [.] regex.
grep -q can be utilized to avoid command substitution step.
Prefer using lowercase variables in shell.
The problem is that grep you call sometimes finds himself in a ps list, so it is good only when you check it interactively:
$ ps -ef | grep bash
...
myaut 19193 2332 0 17:28 pts/11 00:00:00 /bin/bash
myaut 19853 15963 0 19:10 pts/6 00:00:00 grep --color=auto bash
Easiest way to get it is to use pidof. It accepts both full path and executable name:
service="./yowsup/yowsup-cli" # or service="yowsup-cli"
if pidof "$service" >/dev/null; then
echo "not running"
else
echo "running"
fi
There is more powerful version of pidof -- pgrep.
However, if you start your program from a script, you may save it's PID to a file:
service="./yowsup/yowsup-cli"
pidfile="./yowsup/yowsup-cli.pid"
service &
pid=$!
echo $pid > $pidfile
And then check it with pgrep:
if pgrep -F "$pidfile" >/dev/null; then
echo "not running"
else
echo "running"
fi
This is common technique in /etc/init.d start scripts.
The following solution avoids issues with ps + grep, pgrep and pidof (see Advantages below):
# Check if process is running [$1: path to executable]
function is_process_running() {
local path="$1" line
while read -r line; do
[[ "${line}" == "${path}" || "${line}" == "${path} "* ]] && return 0
done < <(ps -e -o command=)
return 1
}
is_process_running "./yowsup/yowsup-cli" && echo "running" || echo "not running"
Explanation:
ps -e -o command= list all processes, only output command line of each process, omit header line
while read -r line; do ... done < <(ps ...) process output produced by ps line by line
[[ "${line}" == "${path}" || "${line}" == "${path} "* ]] check if line matches path exactly -or- path + space + argument(s)
Advantages:
Works for paths containing regex special characters that would trip grep without option -F or pgrep, e.g. /home/user/projects/c++/application/executable (see NOTE in this answer for details)
Avoids issues with ps + grep / pgrep reporting false positives if path appears as argument of some other process (e.g. nano /usr/bin/sleep + pgrep -f /usr/bin/sleep -> falsely reports pid of nano process)
Avoids issues with pidof reporting false positives for processes that are run from PATH (e.g. sleep 60s & + pidof /tmp/sleep -> falsely reports pid of sleep process running from /usr/bin/sleep, regardless of whether /tmp/sleep actually exists or not)
I thought pidof was made for this.
function isrunning()
{
pidof -s "$1" > /dev/null 2>&1
status=$?
if [[ "$status" -eq 0 ]]; then
echo 1
else
echo 0
fi
)
if [[ $(isrunning bash) -eq 1 ]]; then echo "bash is running"; fi
if [[ $(isrunning foo) -eq 1 ]]; then echo "foo is running"; fi
## bash
## function to check if a process is alive and running:
_isRunning() {
ps -o comm= -C "$1" 2>/dev/null | grep -x "$1" >/dev/null 2>&1
}
## example 1: checking if "gedit" is running
if _isRunning gedit; then
echo "gedit is running"
else
echo "gedit is not running"
fi
## example 2: start lxpanel if it is not there
if ! _isRunning lxpanel; then
lxpanel &
fi
## or
_isRunning lxpanel || (lxpanel &)
Note: pgrep -x lxpanel or pidof lxpanel still reports that lxpanel is running even when it is defunct (zombie); so to get alive-and-running process, we need to use ps and grep
current_pid="$$" # get current pid
# Looking for current pid. Don't save lines either grep or current_pid
isRunning=$(ps -fea | grep -i $current_pid | grep -v -e grep -e $current_pid)
# Check if this script is running
if [[ -n "$isRunning" ]]; then
echo "This script is already running."
fi
SERVICE="./yowsup/yowsup-cli"
RESULT=`ps aux | grep $SERVICE|grep -v grep`
if [ "${RESULT:-null}" = null ]; then
echo "not running"
else
echo "running"
fi

Resources