Bash script variable output not working - linux

I have a bash script that is parsing files containing information about processes running on a server. Everything works except the output.
Target output
tomcat7 Running Monitored 3025 18d 2h 16m 3.6% 0.0%
What it actually is outputing
0.0%2h 16m ing
Script portion doing the parsing and output
for SERVER in $SERVERS ; do
SYSTEM=$(sed -n '/System/{p; n;p; n;p; n;p; n;p; n;p}' $H_DIR/$SERVER.txt)
sed -n '/Process/{p; n;p; n;p; n;p; n; n;p; n;n;n; n;p; n; n;p}' $H_DIR/$SERVER.txt > $H_DIR/procs.txt
split --lines=7 $H_DIR/procs.txt $H_DIR/procs.txt.
for PROC in $H_DIR/procs.txt.?? ; do
PROCESS=$(cat $PROC | head -1 | tail -1 | cut -d "'" -f2)
STATUS=$(cat $PROC | head -2 | tail -1 | awk '{ print $NF }')
MONITOR=$(cat $PROC | head -3 | tail -1 | awk '{ print $NF }')
PID=$(cat $PROC | head -4 | tail -1 | awk '{ print $NF }')
UPTIME=$(cat $PROC | head -5 | tail -1 | awk '{ print substr($0, index($0, $2)) }')
PCPU=$(cat $PROC | head -6 | tail -1 | awk '{ print $NF }')
PMEM=$(cat $PROC | head -7 | tail -1 | awk '{ print $NF }')
echo $PROCESS $STATUS $MONITOR $PID $UPTIME $PCPU $PMEM
done
rm -f $H_DIR/procs.*
rm -f $H_DIR/$SERVER.txt
done
raw file being parse
Process 'tomcat7'
status Running
monitoring status Monitored
pid 3025
uptime 18d 2h 30m
memory percent 3.6%
cpu percent 0.0%

On a hunch - your input files have the DOS carriage return line feed combination.
I added that to your file and got the same results you did.
See this question for how to remove the carriage return:
Remove carriage return in Unix
Using the suggested tr -d '\r' method for removing carriage return (and might as well remove single quotes at the same time) you could do something like this:
echo $(tr -d "\r\'" < $PROC | awk 'NR==5{print substr($0,index($0,$2))}{print $NF}')
or if you need each variable assigned then something like this
VARS=$(tr -d "\r\'" < $PROC | awk 'NR==5{print substr($0,index($0,$2))}{print $NF}')
read PROCESS STATUS MONITOR PID UPTIME PCPU PMEM <<<$VARS
echo $PROCESS $STATUS $MONITOR $PID $UPTIME $PCPU $PMEM
Either way, output is
tomcat7 Running Monitored 3025 18d 2h 30m 30m 3.6% 0.0%

Related

Identify processes running more than 3 hrs in linux

I want to find out processes running more than 3 hrs, I have written a command for this but it's not returning expected output
ps -u <user> -o pid,stime,pcpu,pmem,etime,cmd --sort=start_time | \
grep <searchString> | grep -v grep| awk '{print $5}' | \
sed 's/:|-/ /g;'| awk '{print $4" "$3" "$2" "$1"}' | \
awk '$1+$2*60+$3*3600+$4*86400 > 10800'
but it's printing the values of etime in output. But expected output is, command should print the values of "pid,stime,pcpu,pmem,etime,cmd"
I am not able to find exact issue with this.
You are executing "awk '{print $5}'" which is taking in the input and printing out only column 5 which in your case is "etime" , everything from this point on is lost.
If your system supports etimes (notice the s on the end), you can easily do this with
ps -eo pid,etimes,etime,comm,user,tty | awk '{if ( $2>10800) print $0}'
on a system not supporting etimes which has a standard output of etime which hh:mm:ss or just mm:ss if no hours have passed
ps -eo pid,etime,comm,user,tty | awk '{seconds_old=10800 ; split($2,a,":",sep) ; if(length(a) < 3) b = (a[1] *60) + (a[2]) ; else b=((a[1]*3600) + (a[2] *60) + (a[3])) ; if(b > seconds_old ) print $0}'
Adjust "seconds_old" to change the age you want to test for:
There are various other methods of doing this using Find for example:
explained here:
https://serverfault.com/questions/181477/how-do-i-kill-processes-older-than-t
However, the solution should match your expected output
Try this:
ps -u <user> -o pid,stime,pcpu,pmem,etime=,cmd --sort=start_time|grep <searchString>|while read z;do tago=$(echo $z|awk '{print $5}'|sed -E 's/(:|-)/ /g'| awk '{print $4+$3*60+$2*3600+$1*86400}');if [ $tago -ge 10800 ];then echo $z;fi;done
It prints only processes >= 10800 secs old.
You can readjust the output further to fit your needs.
Able to find running process for more than 3 hrs with below command.
ps -u <user> -o pid,stime,pcpu,pmem,etime,cmd --sort=start_time |grep -v grep|awk 'substr($0,23,2) > 3'

Searching a specific file system in bash

I have a task which asks to write a script which displays all partitions formatted with a specific file system, given as parameter.
I have written the script but when i run it it displays '0'. What am i doing wrong?
This is my code:
#!/bin/bash
n=sudo parted -l | tail -n +8 | awk '{print $5}' | wc | awk '{print $2}'
m=sudo parted -l | tail -n +8 | awk '{print $5}'
q=sudo parted -l | tail -n +8
for i in $n; do
if [ "[ $m | sed -n ip ]" = "$1" ]; then
echo "$q | sed -n ip"
fi
done
Different approach from yours, but does it do what you need?
lsblk -f | awk '$0 ~ fs {print $NF}' fs=ext2

Echo result from Linux file with dynamic filename

I have a tomcat server I am trying to get a list of info on for a project. I need to get the results from /etc/default/tomcat file. However some of my servers are tomcat6 and some are tomcat7 so hardcoding the filename is not going to work.
How would I dynamically insert the filename in this batch script.
#!/bin/bash
echo Server Name: `hostname`
echo CPU: `top -b -n1 | grep "Cpu(s)" | awk '{print $2 + $4}'`
FREE_DATA=`free -m | grep Mem`
CURRENT=`echo $FREE_DATA | cut -f3 -d' '`
TOTAL=`echo $FREE_DATA | cut -f2 -d' '`
echo Internal IP : `ifconfig eth0 2>/dev/null|awk '/inet addr:/ {print $2}'|sed 's/addr://'`
echo OS Memory: `cat /proc/meminfo | grep MemTotal | awk '{ print $2 }'`
echo Operating System: `uname -mrs`
***echo Tomcat Memory: `cat /etc/default/tomcat6 | grep Xmx | awk '{ print $5}'`***
Your last command can be simplified to single awk like this:
awk '/Xmx/{print "Tomcat Memory:", $5}' "$tomcatFile"
Pass "$tomcatFile" whatever tomcat filename from ver6 or ver7.
You can get output from both tomcat files in same command using:
awk '/Xmx/{print "Tomcat Memory:", $5}' /etc/default/tomcat[67]

Read variable from AWK

I'm trying to get memory info by this command:
#!/bin/bash
set -x
cat /proc/meminfo | grep "MemFree" | tail -n 1 | awk '{ print $2 $4 }' | read numA numB
echo $numA
I'm getting this
+ awk '{ print $2 $4 }'
+ read numA numB
+ tail -n 1
+ grep MemFree
+ cat /proc/meminfo
+ echo
My attempts to read these data to variable were unsuccessful. My question is how I can read this to variables? I want to read how many memory is free like: 90841312 KB
Regards
Assign the output directly to your variable:
var=$(cat /proc/meminfo | grep "MemFree" | tail -n 1 | awk '{ print $2 $4 }')
echo $var
Using BASH you can reduce your complex commands to this:
read -r _ numA _ numB < <(grep MemFree /proc/meminfo | tail -n 1)
BTW: If you print multiple vales from awk, you need a separator:
$ echo "11 22" | awk '{print $1 }'
11
$ echo "11 22" | awk '{print $2}'
22
$ echo "11 22" | awk '{print $1 $2}'
1122
^ note no space there...
You either need a comma:
$ echo "11 22" | awk '{print $1,$2}'
11 22
Or physicality:
$ echo "11 22" | awk '{print $1" "$2}'
11 22
Because without separation, the command substitution not read what you intend:
$ read -r f1 f2 <<< $(echo "11 22" | awk '{print $1 $2}')
$ echo $f1
1122
echo $f2
# f1 got two fields and nada for f2
arr=( $(awk '/MemFree/{split($0,a)} END{print a[2], a[4]}' /proc/meminfo) )
echo "${arr[0]}"
echo "${arr[1]}"

Getting error while running script to find disk space

I am running below script:-
#!/bin/bash
threshold="20"
i=2
result=`df -kh |grep -v “Filesystem” | awk ‘{ print $5 }’ | sed ‘s/%//g’`
for percent in $result; do
if ((percent > threshold))
then
partition=`df -kh | head -$i | tail -1| awk ‘{print $1}’`
echo “$partition at $(hostname -f) is ${percent}% full”
fi
let i=$i+1
done
But I get the following error:
awk: ‘{
awk: ^ invalid char '▒' in expression
sed: -e expression #1, char 1: unknown command: `▒'
Please help me to resolve this.
What awk does not work? (your script does work fine on my Ubuntu)
This line:
result=`df -kh |grep -v "Filesystem" | awk '{ print $5 }' | sed 's/%//g'`
could be changed to:
result=$(df -kh | awk '!/Filesystem/ {print $5+0}')
Avoid using old and outdated backtics if parentheses works like this: var=$(code...)
This:
partition=`df -kh | head -$i | tail -1| awk '{print $1}'`
could be changed to:
partition=$(df -kh | awk -v line="$i" 'NR==line {print $1}')
This
let i=$i+1
could be change to:
((i++))
This would then give some like this:
#!/bin/bash
threshold="20"
i=2
result=$(df -kh | awk '!/Filesystem/ {print $5+0}')
for percent in $result; do
if ((percent > threshold))
then
partition=$(df -kh | awk -v line="$i" 'NR==line {print $1}')
echo "$partition at $(hostname -f) is ${percent}% full"
fi
((i++))
done
You're using ‘ for a single quote not '. Try re-encoding your file with an editor.
You got the answer to your syntax error, now re-write the whole script as just:
#!/bin/bash
df -kh |
awk -v t=20 -v h="$(hostname -f)" '(NR>1)&&($5+0>t){printf "%s at %s is %s full\n",$1,h,$5}'

Resources