Grep output of command and use it in "if" statement, bash - bash

Okay so here's another one about the StarMade server.
Previously I had this script for detecting a crash, it would simply search through the logs:
#!/bin/bash
cd "$(dirname "$0")"
if ( grep "[SERVER] SERVER SHUTDOWN" log.txt.0); then
sleep 7; kill -9 $(ps -aef | grep -v grep | grep 'StarMade.jar' | awk '{print $2}')
fi
It would find "[SERVER] SERVER SHUTDOWN" and kill the process after that, however this is not a waterproof method, because with different errors it could be possible that the message doesn't appear, rendering this script useless.
So I have this tool that can send commands to the server, but returns an EOF exception when the server is in a crashed state. I basically want to grab the output of this command, and use it in the if-statement above, instead of the current grep command, in such a way that it would execute the commands below when the grep finds "java.io.EOFException".
I could make it write the output to a file and then grep it from there, but I wonder, isn't there a better/more efficient method to do this?
EDIT: okay, so after a bit of searching I put together the following:
if ( java -jar /home/starmade/StarMade/StarNet.jar xxxxx xxxxx /chat) 2>&1 > /dev/null |grep java.io.EOFException);
Would this be a valid if-statement? I need it to match "java.io.EOFException" in the output of the first command, and if it matches, to execute something with "then" (got that part working).

Not sure to solve your problem, but this line:
ps -aef | grep -v grep | grep 'StarMade.jar' | awk '{print $2}'
could be change to
ps -aef | awk '/[S]tarMade.jar/ {print $2}'
The [S] prevents awk from finding itself.
Or just like this to get the pid
pidof StarMade.jar

Related

Bash- Running a command on each grep correspondence without stopping tail -n0 -f

I'm currently monitoring a log file and my ultimate goal is to write a script that uses tail -n0 -f and execute a certain command once grep finds a correspondence. My current code:
tail -n 0 -f $logfile | grep -q $pattern && echo $warning > $anotherlogfile
This works but only once, since grep -q stops when it finds a match. The script must keep searching and running the command, so I can update a status log and run another script to automatically fix the problem. Can you give me a hint?
Thanks
use a while loop
tail -n 0 -f "$logfile" | while read LINE; do
echo "$LINE" | grep -q "$pattern" && echo "$warning" > "$anotherlogfile"
done
awk will let us continue to process lines and take actions when a pattern is found. Something like:
tail -n0 -f "$logfile" | awk -v pattern="$pattern" '$0 ~ pattern {print "WARN" >> "anotherLogFile"}'
If you need to pass in the warning message and path to anotherLogFile you can use more -v flags to awk. Also, you could have awk take the action you want instead. It can run commands via the system() function where you pass the shell command to run

how stopped script while procces id exist? Solaris

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.

Strip process pid to log_file_name (weird behaviour when running from cron)

I am curious if anyone have similar issue when running scripts from cron. This line of script should copy opentsdb_daemon.log file to opentsdb_daemon_with_pid.log. Currently openTSDB is running on only one PID.
!/bin/sh
cp -f /opt/opentsdb/opentsdb-2.2.0/var/log/opentsdb/opentsdb_daemon.log "/opt/opentsdb/opentsdb-2.2.0/var/log/opentsdb/opentsdb_daemon_pid_$(ps -ef | grep [o]pentsdb | awk '{print $2}').log
It runs ok. File opentsdb_daemon_pid_76079.log is created but when running fron cron it's creating something like this: opentsdb_daemon_pid_63453?63454?76079.log
I have tried to run it from diffrent cron users - with same effect. I would be extremely grateful for any advice.
The command ps -ef | grep [o]pentsdb | awk '{print $2}' should return multiple PID at the time cron run it, what you get is all the PID separated by "?"
The "?" is because \n is not correctly diplayed in the filename
I assume that it is because when cron executes the command, the command appears in the process list, so :
grep [o]pentsdb is also grep by grep [o]pentsdb ;)
You can determine it by the two consecutive PID 63453 and 63454 which are the process lines "cron execute the command xxx" and the child of this process which is the "command xxx"
Maybe a solution could be to add something like :
$(ps -ef | grep [o]pentsdb |grep -Ev "grep|cron" | awk '{print $2}')

Kill command won't work correctly in bash script

I was running an ubuntu console, when I type the following command, all the processes would be perfectly killed.
kill -9 $(ps -ef | grep 'job1/' | grep -v grep| awk '{print $2}')
But when I was trying to use crontab to call a script routinely, things went wrong.
#!/bin/bash
pid=$(ps -ef | grep 'job1/' | grep -v grep | awk '{print $2}')
echo $pid
kill -9 $pid
# the following commands were never executed
sleep 5
/data/job1/tomcat8/bin/startup.sh
The result was just like this:
15432 15438
Killed
It seems to just killed the job, but won't execute the following commands. Any idea?
If you are going to make a script that kills things by PID then you need to be very careful that you kill the right things.
You already have grep -v grep to avoid killing the grep itself, but it seems that you have not put in anything to protect against the script killing itself. Since you know your own PID you could grep -v that, but what if you are 123 and one of the things you want to kill is 1234? Probably safer to go by script name.

Kill empty process id

In my Makefile, I have the following to kill all my running nginx processes:
killNginx:
sudo kill -9 $(ps -ef | grep [n]ginx | awk '{print $2}')
The problem is that it gives me an error when there are no nginx processes running. Is there a way I can run the kill command only if nginx is running?
EDIT:
Actually I think the issue is the $2 not getting executed. I tried $$2 but still does not work. Anyone have any other ideas to escape $2?
Found a way that made it work for me:
killNginx:
ps -ef | grep [n]ginx | awk '{print $$2}' | xargs sudo kill -9
You need to escape every single $ in your recipe that does not introduce a make variable. So, you need to escape both $$(ps ... and print $$2. You seem to be implying that this isn't your problem: however there's no way this will even come close to working without that.
You can also look into killall. Something like killall -I nginx || true might do it.
Give this a shot:
for PID in $(ps -ef | grep [n]ginx | awk '{ print $2 }'); do
sudo kill -9 $PID
done

Resources