Question: How do you check if a PID exists and use the result within an IF statement in bash?
Things I've tried
if [ "$(ps -p $pid)" -eq 0 ]; then
echo "Running"
else
echo "Not Running"
fi
if [ "$(kill -0 $pid)" -eq 0 ]; then
echo "Running"
else
echo "Not Running"
fi
Neither of these evaluate correctly no matter how I redirect STDOUT/STDER
How do you check if a PID exists and use the result within an if statement?
You can capture the output in a variable and then check the exit status:
output=$(ps -p "$pid")
if [ "$?" -eq 0 ]; then
echo "Found"
echo "$output"
fi
Just remember that $? is getting reset every time you run a command, so something like the following wont work:
output=$(ps -p "$pid")
echo "$output"
# Now $? will be refering to the exit status of echo
if [ "$?" -eq 0 ]; then
echo "Found"
fi
One can also stick everything together in the if statement:
if output=$(ps -p "$pid")
then
echo "Found: $output"
fi
Make it dynamic by passing the pid you want to check:
#!/usr/local/bin/bash
if ps -p $1 > /dev/null;
then
echo "running"
else
echo "not running"
fi
Example runs:
What's your host OS?
If you have /proc then this may work for you:
if [ -d "/proc/$pid" ]; then
echo "Running"
else
echo "Not running"
fi
Related
I wanna write a script which check variables of this script.
I have tried some, but it isn't working. The idea is:
If on of the parameters is a number, print that it is number
If on of the parameters is a character, print that it is character
If 'man parameter' is executable, print that it is might be a function
Script I have tried:
#!/bin/bash
echo Hello $LOGNAME'!'
test $# -eq 0 && echo 'Try again, no parameters were entered' || echo 'Num of parameters is '$#
re='^[0-9]+$'
for i in $*
do
if ![["$i" =~ $re]];then
echo 'Parameter '$i' is alphabetical'
else
if [["$i" =~ $re]];then
echo 'Parameter '$i' is digital'
else
if [ $i];then
echo $i' might be a function. Try to use man of --help'
fi
fi
fi
done
#!/bin/bash
echo "Hello ${LOGNAME}!"
[ "$#" -eq 0 ] && { echo 'Try again, no parameters were entered'; exit 1; }
echo 'Num of parameters is '$#
re='^[0-9]+$'
for i in "$#"
do
if ! [[ "$i" =~ $re ]];then
echo "Parameter '$i' is alphabetical"
man "$i" > /dev/null 2> /dev/null
if [ "$?" -eq 0 ];then
echo "$i might be a function. Try to use man of --help"
fi
else
echo "Parameter '$i' is digital"
fi
done;
When you write a test you need spaces around your brackets.
You can easily find and fix those bugs if you use shellcheck
I am trying to write a Ping result bash code.
this way it work, but i'm not a fan of using the last ouput function:
#!/bin/bash
ping -q -c2 10.10.50.120 > /dev/null
resp=$?
echo "$resp"
if [ "$resp" == 0 ]
then
echo "ok"
else
echo "not ok"
fi
Ouput:
0
ok
but this way it doesn't work:
#!/bin/bash
resp=$(ping -q -c2 10.10.50.120 > /dev/null)
echo "$resp"
if [ "$resp" == 0 ]
then
echo "ok"
else
echo "not ok"
fi
Ouput:
not ok
Can anyone help me to find out how to write it correctly?
I wanted to avoid the "$?" function.
That's great. So just use if.
if output=$(ping -q -c2 10.10.50.120); then
# or like: if ping -q -c2 10.10.50.120 >/dev/null; then
echo "ok"
else
echo "not ok"
fi
echo "Anyway, ping command ouptutted: $output"
It is possible to save the exit status to a variable without the "$?" function?
No.
I'm using link to create a semaphore - the idea is to lock out of writing to a db.
Here I have a script to create a table in a database:
#!/bin/bash
if [ "$#" -lt 3 ]; then
echo "Not enough parameters"
exit 1
elif [ "$#" -gt 3 ]; then
echo "Too many parameters"
exit 1
fi
if [ ! -d "$1" ]; then
echo "That database doesn't exist!"
exit 1
fi
./P.sh $1
if [ -f "$1/$2.txt" ]; then
echo "That table already exists!"
./V.sh $1
exit 1
else
touch "$1/$2.txt"
fi
./V.sh $1
echo "$3" > "$1/$2.txt"
echo "Ok, table created"
exit 0
Here's my P file:
#!/bin/bash
if [ -z "$1" ]; then
echo "Usage $0 mutex-name"
exit 1
elif [ ! -e "$1" ]; then
echo "Target for the lock must exist"
exit 2
else
while ! ln "$1" "$1.lock"; do
sleep 1
done
exit 0
fi
and my V:
#! /bin/bash
if [ -z "$1" ]; then
echo "Usage $1 mutex-name"
exit 1
else
rm "$1.lock"
exit 0
fi
let's say I create a table by running ./create_table people footballers age,height
This should create a file footballers.lock (created by P) and then once the writing has happened the V should remove it. But for some reason the P thinks that the .lock file already exists, and it definitely doesn't.
Can anyone spot what's going wrong?
Found it - you can't use ln on directories...
I have file "sleepdaemon" which launches python program as service
I run this script:
sudo /etc/init.d/sleepdaemon start
but when I check the state $?=0 always
this is how i check
if [ "$?" -eq 0 ]; then
echo "Process is running"
fi
if [ "$?" -eq 1 ]; then
echo "Process is not running"
fi
if [ "$?" -eq 2 ]; then
echo "Process is not running"
fi
What's the problem ?
The value of $? gets reset after every test, so you either need to save it in a variable before testing, or use a case ... esac statement.
sudo returns the result of the command, or 1 if it can't run it. ? is set for EVERY command:
if (( $? == 0 )); then
echo "Process is running"
elif (( $? == 1 )); then
echo "Process is not running" >&2
elif (( $? == 2 )); then
echo "Process is not running" >&2
else
echo "Unknown exit code $?" >&2
fi
Use (( ... )) for arithmetic comparisons - it is easier and safer. You should always have a default long-stop, and you should report errors to stderr, not stdout.
If $? is always zero, then check the documentation for sleepdaemon (I tried, but can't find a return code documented anywhere).
The exit statements in each status check if statement do not break the while loop and truly exit the script. Is there something I can do to break the loop and exit with that $STATUS code?
EDIT: I've updated my code and it still isn't working. The status check if statements successfully break the loop but when I try to evaluate the $EXIT_STATUS it's always null, likely having something to do with scope. What am I missing here?
if [ $RESTART -le $STEP ]; then
. tell_step
while read XML_INPUT; do
XML_GDG=`get_full_name $GDG_NAME P`
cp $XML_INPUT $XML_GDG
STATUS=$?
EXIT_STATUS=$STATUS
if [ $STATUS -ne 0 ]; then
break
fi
add_one_gen $XML_GDG
STATUS=$?
EXIT_STATUS=$STATUS
if [ $STATUS -ne 0 ]; then
break
fi
done < $XML_STAGE_LIST
echo $EXIT_STATUS
if [ $EXIT_STATUS -ne 0 ]; then
exit $EXIT_STATUS
fi
fi
I had the same problem: when piping into a while loop, the script did not exit on exit. Instead it worked like "break" should do.
I have found 2 solutions:
a) After your while loop check the return code of the while loop and exit then:
somecommand | while something; do
...
done
# pass the exit code from the while loop
if [ $? != 0 ]
then
# this really exits
exit $?
fi
b) Set the bash script to exit on any error. Paste this at the beginning of your script:
set -e
Not really understand why your script dosn't exits on exit, because the next is works without problems:
while read name; do
echo "checking: $name"
grep $name /etc/passwd >/dev/null 2>&1
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "grep failed for $name rc-$STATUS"
exit $STATUS
fi
done <<EOF
root
bullshit
daemon
EOF
running it, produces:
$ bash testscript.sh ; echo "exited with: $?"
grep failed for bullshit rc-1
exited with: 1
as you can see, the script exited immediatelly and doesn't check the "daemon".
Anyway, maybe it is more readable, when you will use bash functions like:
dostep1() {
grep "$1:" /etc/passwd >/dev/null 2>&1
return $?
}
dostep2() {
grep "$1:" /some/nonexistent/file >/dev/null 2>&1
return $?
}
err() {
retval=$1; shift;
echo "$#" >&2 ; return $retval
}
while read name
do
echo =checking $name=
dostep1 $name || err $? "Step 1 failed" || exit $?
dostep2 $name || err $? "Step 2 failed" || exit $?
done
when run like:
echo 'root
> bullshit' | bash testexit.sh; echo "status: $?"
=checking root=
Step 2 failed
status: 2
so, step1 was OK and exited on the step2 (nonexisten file) - grep exit status 2, and when
echo 'bullshit
bin' | bash testexit.sh; echo "status: $?"
=checking bullshit=
Step 1 failed
status: 1
exited immediatelly on step1 (bullshit isn't in /etc/passwd) - grep exit status 1
You'll need to break out of your loop and then exit from your script. You can use a variable which is set on error to test if you need to exit with an error condition.
I had a similar problem when pipelining. My guess is a separate shell is started when piplining. Hopefully it helps someone else who stumbles across the problem.
From jm666's post above, this will not print 'Here I am!':
while read name; do
echo "checking: $name"
grep $name /etc/passwd >/dev/null 2>&1
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "grep failed for $name rc-$STATUS"
exit $STATUS
fi
done <<EOF
root
yayablah
daemon
EOF
echo "Here I am!"
However the following, which pipes the names to the while loop, does. It will also exit with a code of 0. Setting the variable and breaking doesn't seem to work either (which makes sense if it is another shell). Another method needs to be used to either communicate the error or avoid the situation in the first place.
cat <<EOF |
root
yayablah
daemon
EOF
while read name; do
echo "checking: $name"
grep $name /etc/passwd >/dev/null 2>&1
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "grep failed for $name rc-$STATUS"
exit $STATUS
fi
done
echo "Here I am!"