I want to write an if condition in Shell script something like this:
if[ tail -10f logFile | grep -q "RUNNING" ]
So the idea is I have restarted my server and want to perform some action only after the server is started up(RUNNING). So I want to continuously tail the log and check if the server is in RUNNING mode again.
The issue with the above approach is it does not exits even after the server is RUNNING and goes into infinite loop. No code in if or else is printed.
What about?
while [ $(tail -10 logFile | grep -c RUNNING) -eq 0 ]; do sleep 1; done
Related
This is part of bigger code that checking the OS version and choosing the correct condition by it.
( after checking OS version, it will go to this if condition: )
if [ "$AK" = "$OS6" ]
then
if [ "$(ls -la /etc/init.d/discagent 2>/dev/null | wc -l)" == 1 ]
then
/etc/init.d/discagent restart 2>&1 > /dev/null
/etc/init.d/discagent status |& grep -qe 'running'
if [ $? -eq 0 ] ; then
echo " Done "
else
echo " Error "
fi
fi
fi
If im hashing service discagent restart the pipeline is passing.
But if im not hashing it then it hang and not given any errors, And on the output file it is showing only the second server (out of few) that its hang on, And not moving to the next server.
what could be the issue?
p. S
while running it direct on the server it is working.
Run this script manually on the servers, that this script will be running on.
You can use xtrace -x which would show each statement before being executed, when you use with -v with -x so this would be -xv and the statement would be outputted, and then the line after the output of the statement with the variables substituted before the code is substituted.
using -u would show you the exact error when this occurs.
Another command is the trap command to debug your bash script.
More information on the following webpage,
https://linuxconfig.org/how-to-debug-bash-scripts
I currently have 2 bash scripts:
1) tomcat.sh
#!/bin/bash
case "$1" in
'start')
/home/testuser/start.sh
;;
'status')
/home/testuser/status.sh
;;
esac
2) status.sh
#!/bin/bash
COUNT="$( ps -ef | grep tomcat| wc -l )"
echo ${COUNT}
if [ "${COUNT}" -eq 2 ]
then
echo "Tomcat is running."
else
echo "Tomcatis not running"
fi
When I check status via these two methods:
./tomcat.sh status: ${COUNT} echos a value of 4.
status.sh: ${COUNT} echos value of 2.
I'm not sure why there is a discrepancy. I'm expecting both values from echo to match since they are essentially executing status.sh. Am I missing something?
EDIT: Added in the actual search values I'm using.
Your tomcat.sh is still running when the ps -ef in status.sh is running. So, in case of using tomcat.sh ps finds at least these:
tomcat.sh
the tomcat you are looking for
grep tomcat (if you pipe, processes are started right to left, so when ps is running, your grep is also already running)
Right now I am not sure where the 4th is coming from.
In case of just running the status script, it is not finding tomcat.sh and thus you have less results. A solution could be to make your grep more specific for your use case, or use something that is more specific for your task, like pgrep (although pgrep java will possibly also give you other unwanted processes).
Possible solution:
COUNT="$( ps -ef | grep "tomcat" | grep "org.apache.catalina.startup.Bootstrap" | wc -l )"
Edit: Using a pidfile is of course also a way of doing it. In the question you show something that looks like a startup script. So writing a pidfile when starting and then reading and using that pidfile when querying, you can know if the service is started. It won't work though if someone uses another way to start the service.
I wrote a script to run constantly on startup. If for whatever reason the script were to fail, I wrote a second script to check if it has failed, and if so, run the first script again. I then set this second script as a cronjob to run every minute so that it is constantly checking if the first script is alive.
So to test this, I reboot my system. I can see in htop that the first script is running from start up as expected. Good. I kill the process to test the second script. Sure enough, the second script starts the first script again. Still good. I then kill this process, but the second script won't run again now. It still updates a txt file when I manually start the first script, but the second script just doesn't start the first script like it's supposed to. Is it because I killed the cronjob? Restarting the cron service doesn't fix anything though, so I don't know why my second script isn't running again at all.
First script:
#!/bin/bash
stamp=$(date +%Y%m%d-%H%M)
timeout 10d tcpdump -i eth0 -s 96 -z gzip -C 10 -w /home/user/Documents/${stamp}
Second script:
#!/bin/bash
echo "not running" > /home/working.txt
if (( $(ps -ef | grep -v grep | grep tcpdump.sh | wc -l) > 0 ))
then
echo "tcpdump is running!!!" > /home/working.txt
else
/usr/local/bin/tcpdump.sh start
fi
Any help?
You would probably be better off running a simple for loop as the main script, and that kicks off the tcpdump script in the background, so something like:
#!/bin/bash
while true; do
if ps -ef | grep -v grep | grep -q tcpdump; then
: tcpdump running OK
else
# tcpdump not running - start it off
nohup /usr/local/bin/firstscript.sh start &
fi
sleep 30
done
This checks that "tcpdump.sh" is in the output of the "ps -ef" command - if it is, then do nothing (note that you must have an actual command between the "then" and "else" - the ":" command, which just takes it s arguments and ignores them, is sufficient). If it isn't running, start the first script in the background. Then sleep 30 seconds and check again. (Yes, I could have inverted the test so that I didn't need an empty "then" arm, but it would have made the code less obvious)
You put this script as the one which starts at boot time.
Edit: Do you really want to check for "tcpdump.sh"? Is that what the first script is actually called? Assuming that you actually want to check for the tcpdump program, you could use:
if pgrep tcpdump; then
I want to stall the execution of my script until a process is closed (I have the PID stored in a variable).
#!/bin/bash
outputl=$( ps -ef | grep $var4 | awk '{print $2}' ) >> $logfile
while [ "ps -p $outputl" ] > /dev/null;
do
sleep 1;
done
echo "Stopped $instance" >> $logfile
//command...
It stays in the "while" and not continue whit script.
This line:
while [ "ps -p $output1" ]
does not execute the ps command. It simply tests whether the string "ps -p $output1" is not empty, and it obviously isn't. To test the output of a command, use $():
while [ "$(ps -p "$output1")" ]
But since ps produces a header, this will always be true. The best way to test if a PID exists is to use the kill command with signal 0; this doesn't actually send a signal, it just tests whether it's possible to send a signal. I'm assuming this code is being run either by root or the userid running the application being checked. So you can write:
while kill -0 "$output1" 2>/dev/null
Also, your code for getting the PID into $output1 is wrong. ps -ef will also include the grep command, which matches the name you're looking for, so you need to filter that out. Use:
output1=$(ps -ef | grep "$var4" | awk '!/grep/ { print $2 }')
Redirecting the output to $logfile is not necessary, since variable assignments don't print anything.
Many systems have a pgrep command, which can be used by itself to test if a process with a given name exists; if you have this, you can use it instead of reinventing the wheel (and if not, you should be able to install it).
If you have the PID then just wait for it to complete. Try:
outputl=$( ps -ef | awk -v v="$var4" '$0~v{print $2}' )
wait "$outputl"
echo "Stopped $instance" >> $logfile
then look for a better way to find the pid in the first line.
Suppose that ps -ef | grep apache | wc -l gives output 2 which means 2 process are running.
In my server connection fluctuates, so I want to send an alert when the output of ps -ef| grep apache |wc -l is zero more than 5 Minutes.
I want to send an alert when the output of ps -ef| grep apache |wc -l is zero more than 5 Minutes.
First,ps -ef| grep apache can be unreliable because it may count grep apache as an apache process. To avoid that, use ps -ef | grep '[a]pache'. Better, try: pgrep apache. Also, if we are looking for zero or not zero processes, we don't need wc -l.
If your needs are simple, then here is a simple bash script that checks every minute to see if an apache process is running. If five successive tests show no such process, it sends an email to user#admin:
#!/bin/bash
count=0
while sleep 1m
do
if pgrep apache >/dev/null
then
count=0
else
((count++))
fi
if [ "$count" -ge 5 ]
then
echo "Houston, we have a problem: $count" | mail admin#host
count=0
fi
done
Since this only checks every minute, it could miss some process that starts and stops in less than a minute. You may need to adjust the timing. As Jonathan Leffler commented, doing this well is hard work. This script is only intended as a quick-and-simple solution.