Bash script giving undesired output - bash

I am facing with the following bash script:
#! /bin/bash
processname=$1
x=1
while [ $x -eq 1 ] ; do
ps -el | grep $processname | awk ' {if($15!="grep") print "The memory consumed by the process " $15 " is = "$9} ' >> out.log
sleep 30
done
and I am running this with :
$ ./myscript.sh Firefox
but when i see the output in the file, apart from the firefox process i am also getting information for /bin/bash process
The memory consumed by the process /Applications/Firefox.app/Contents/MacOS/firefox is = 911328
The memory consumed by the process /bin/bash is = 768
Can some one help me with this so that I only want to get information related to Firefox process and nothing else(/bin.bash etc)

The common trick is to change grep Firefox to grep [F]irefox. In this case, you can achieve it with
ps | grep '['${processname:0:1}']'${processname:1}

This is normal and because the $processname is Firefox. Since your command also monitors it, there is a process that uses it.
For example, try ps -el | grep Firefox and you will get two process lines matching (if you have one instance of Firefox running), one is Firefox, the other is the grep command looking for Firefox.
Piping your output in grep -v /bin/bash' should solve this. Eg:
ps -el | grep $processname | awk ...
becomes:
ps -el | grep $processname | grep -v 'grep' | awk ...

You calling
ps -el | grep $processname | awk ' {if($15!="grep") print "The memory consumed by the process " $15 " is = "$9} '
This means that you run awk and connect it's input with output of grep. Then grep is started and gets output of ps -el as input.
At the moment when bash will start ps you have grep and awk running.
Solution: run ps -el and remember it's output. Then run grep and awk. It should be like this:
ps -el > ps.tmp
grep $processname ps.tmp | awk ' {if($15!="grep") print "The memory consumed by the process " $15 " is = "$9} ' >> out.log
Probably this could be done without using tmp file. Like TMP=$(ps -el). But I don't know how to run grep filter on variable

Related

pgrep process count show extra count

I've a scirpt name server.sh
#!/bin/bash
process_count=$(ps aux | grep server.sh | grep -v grep | wc -l )
echo "total process running:"
echo $process_count
... other script code
when I run script I get output as
./server.sh
total process running:
2
Why do I get process count as 2 instead of 1? I only have one script running and have also excluded grep process.
Even using pgrep -f server.sh and excluding pgrep gives 2 as process count.
My approach is to redirect the output of ps into a temp file, then grep that file. That will eliminate extra processes.
ps aux > /tmp/ps.txt
process_count=$(grep server.sh /tmp/ps.txt | wc -l)
rm /tmp/ps.txt

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}')

Grep output of command and use it in "if" statement, 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

Machine data not displaying output every 15 Seconds

The following script is meant to output "vmstat" for example every 15 seconds, but for some reason it only does this if there's activity or when I kill the script, in other cases it just sits there.
#!/bin/bash
#!/bin/sh
ps -ef | grep -v grep | grep "vmstat 15" | awk '{ print $2 }' | xargs kill
ps -ef | grep -v grep | grep "iostat 15" | awk '{ print $2 }' | xargs kill
ps -ef | grep -v grep | grep "mpstat 15" | awk '{ print $2 }' | xargs kill
today=`date +%Y-%m-%d.%H:%M:%S`
find /var/log/ -name data_collection -type d -exec mv /var/log/data_collection /home/Beer/"data_collection_${today}" \;
mkdir -p /var/log/data_collection
vmstat 15 | /home/Beer/./addtimestamp.pl > /var/log/data_collection/vm_stat &
iostat 15 | /home/Beer/./addtimestamp.pl > /var/log/data_collection/ios_stat &
mpstat 15 | /home/Beer/./addtimestamp.pl > /var/log/data_collection/mp_stat &
Im guessing the '&' symbol at the end has something to do with this, I only did this so I can execute each command at once.
Since feature requests to mark a comment as an answer remain declined, I copy the above solution here.
What is in addtimestamp.pl? It could be that it's buffering input, and not flushing every time it reads something. – Diego Basch
#DiegoBasch that's exactly correct, I just added a '$|=1;' to the Perl script now and it started to work, basically setting the it to line buffer. Ill add the answer. – I AM L

Count the number of processes and kill them

I am writing a script to kill all instances of the same process. As it is going to be used on Linux, AIX, HP-UX and Solaris, I need to use only built-in bash (sh) functions. That's why killall, pkill, etc. don't work for me.
Once there is only one instance of a process it should be just killed in traditional way:
kill -TERM `ps -ef | grep -v grep | grep $process | awk '{print $2}'`
However sometimes the program has extra instances running and that's why ps -ef | … returns more than one PID. That needs to be reported.
example:
bash-3.2$ ps -ef | grep -v grep | grep perl | awk '{print $2}'
5267
5268
5269
5270
5271
My thought was to store those values in a temporary variable and then send kill signal to each in a for loop.
bash-3.2$ tmp=`ps -ef | grep -v grep | grep perl | awk '{print $2}'`
bash-3.2$ echo $tmp
5267 5268 5269 5270 5271
However I still need the information if such a case occurred (how many instances were present).
It seems I need to check the whole string stored in the tmp variable and maybe count spaces?
Anyway the questions reduces to how to check how many values the $tmp variable stores?
For maximum portability and reliability, use -A (POSIX synonym of -e) and a custom format with -o rather than -f.
Your filtering of the output of ps is brittle: it may match other processes. You've had to exclude the grep process, and you may need to exclude your script as well, and there may be other completely innocent processes caught in the fray (such as your script itself) because their command line happens to contain $process as a substring. Make your filtering as strict as possible. With ps -o pid= -o comm=, you get just two columns (PID and command without arguments) with no header.
You don't need to use a loop to do the killing, kill accepts multiple arguments. For the counting, let the shell do it: you have a whitespace-separated list of numbers, to let the shell do the word splitting (with $(…) outside quotes) and count the number of resulting words ($#).
count_and_kill_processes () {
set -- $(ps -A -o pid= -o comm= |
awk -v "name=$process" '$2 == name {print $1}')
count=$#
if [ $# -ne 0 ]; then kill "$#"; fi
}
count_and_kill_processes foo
# now the number of killed processes is in $count
If your shell is bash or ksh on all machines, you can use an array.
pids=($(ps -A -o pid= -o comm= |
awk -v "name=$process" '$2 == name {print $1}') )
if [[ $# -ne 0 ]]; then kill "$#"; fi
# the number of killed processes is ${#pids}
use xargs:
ps aux | grep -ie perl | awk '{print $2}' | xargs kill -9
You can use a loop which should work in both cases:
for pid in $(ps -ef | grep -v grep | grep $process | awk '{print $2}'); do
echo $pid
done
Or count the number of matches:
if [ $(ps -ef | grep -v grep | grep $process | awk '{print $2}' | wc -l) -gt 1 ]
then
# more than one
fi

Resources