how to monitor docker containers resource usage using shell script - docker

how to monitor docker containers resource usage using a shell script.
I was just wondering can we use the docker stats command to get metrics to monitor docker containers resource usage

I have written a small shell script that will help to filter docker containers that are using max system resources. (I guess will work for one docker-swarm node cluster)
#!/bin/bash
#This script is used to complete the output of the docker stats command.
#The docker stats command does not compute the total amount of resources (RAM or CPU)
#Get the total amount of RAM, assumes there are at least 1024*1024 KiB, therefore > 1 GiB
docker stats | while read line
do
HOST_MEM_TOTAL=$(grep MemTotal /proc/meminfo | awk '{print $2/1024/1024}')
#echo "HOST TOTAL Memory: $HOST_MEM_TOTAL"
oldifs=IFS
IFS=;
dStats=$(docker stats --no-stream --format "table {{.MemPerc}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.Name}}\t{{.ID}}" | sed -n '1!p')
#dStats=$( docker stats --no-stream --format "table {{.MemPerc}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.Name}}\t{{.ID}}")
SUM_RAM=`echo $dStats | tail -n +2 | sed "s/%//g" | awk '{s+=$1} END {print s}'`
SUM_CPU=`echo $dStats | tail -n +2 | sed "s/%//g" | awk '{s+=$2} END {print s}'`
SUM_RAM_QUANTITY=`LC_NUMERIC=C printf %.2f $(echo "$SUM_RAM*$HOST_MEM_TOTAL*0.01" | bc)`
# Output the result
echo "########################################### Start of Resources Output ##############################################" >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
echo " " >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
dat=$(date)
echo "Present date & Time is: $dat" >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
#IFS=$olifs
#echo "MEM % CPU % MEM USAGE / LIMIT NAME CONTAINER ID" >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
echo "MEM % CPU % MEM USAGE / LIMIT NAME CONTAINER ID" >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
IFS=$'\r\n' GLOBIGNORE='*'
for i in $dStats
do
cpuPerc=$(echo $i | awk '{print $2}')
memPerc=$(echo $i | awk '{print $1}')
cpuPerc=${cpuPerc%"%"}
cpuPerc=${cpuPerc/.*}
memPerc=${memPerc%"%"}
memPerc=${memPerc/.*}
#if [ $cpuPerc -ge 100 ] && [ $memPerc -ge 35 ]
if [ $cpuPerc -ge 100 ] || [ $memPerc -ge 50 ]
then
#IFS=$oldifs
echo $i >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
else
a="hello"
fi
done
#IFS=$oldifs
SUM_RAM=${SUM_RAM/.*}
SUM_CPU=${SUM_CPU/.*}
if [ $SUM_RAM -ge 70 ] && [ $SUM_CPU -ge 100 ]
#if [ $SUM_RAM -ge 70 ] || [ $SUM_CPU -ge 100 ]
then
echo " " >>/tmp/emailFiles/Docker-Resources-Usage-Stats.txt
echo "Total-MEMORY-Usage Total-CPU-Usage Used-MEM / Total-MEM" >> /tmp/emailFiles/SIMSAPP-Docker-Resources-Usage-Stats.txt
#echo -e "${SUM_RAM}%\t\t\t${SUM_CPU}%\t\t${SUM_RAM_QUANTITY}GiB / ${HOST_MEM_TOTAL}GiB\tTOTAL" >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
echo -e "${SUM_RAM}%\t\t\t${SUM_CPU}%\t\t${SUM_RAM_QUANTITY}GiB / ${HOST_MEM_TOTAL}GiB" >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
echo " ">>/tmp/emailFiles/Docker-Resources-Usage-Stats.txt
fi
disk_usage=$(df -hT | grep ext4 | awk '{print $6}')
#disk_usage=$(df -kv| grep sda1 | awk '{preint $5}')
disk_usage=${disk_usage%"%"}
#disk_usage=${disk_usage/.*}
if [ $disk_usage -ge 90 ]
then
#echo "Filesystem Size Used Avail Use% Mounted on" >>/tmp/emailFiles/Docker-Resources-Usage-Stats.txt
echo "Filesystem Type Size Used Avail Use% Mounted on" >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
#df -kh | grep sda1 >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
df -hT | grep ext4 >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
echo " "
#cat /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
fi
echo "########################################### End of Resources Output ################################################" >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
echo " " >> /tmp/emailFiles/Docker-Resources-Usage-Stats.txt
done
Please modify it according to your requirement, if you find it useful.

Related

Jenkins pass a shell script variable to a down stream job

I'm new to Jenkins.
I have a job with an "Execute Shell" Build trigger, and in that shell script i initiate some variables with values i take from some source.
I need to pass these values to a downstream job.
The values i want to pass are $IMG_NAME and $IMG_PATH from this shell script:
#!/bin/bash -x
whoami
echo "BASE_PATH: $BASE_PATH"
declare -A BRANCHES
for i in $(echo $BRANCHES_LIST | tr ',' '\n'); do BRANCHES[$i]= ; done
echo 'user' | sudo -S umount -rf /mnt/tlv-s-comp-prod/drops/
echo 'user' | sudo -S mount.nfs -o nolock,nfsvers=3 tlv-s-comp-prod:/export/drops /mnt/tlv-s-comp-prod/drops
ls /mnt/tlv-s-comp-prod/drops/
echo "cleanup workspace"
rm ${WORKSPACE}/*.txt &> /dev/null
i="0"
while [ $i -lt 6 ]
do
if [[ ${BASE_PATH} == *"Baseline"* ]]; then
unset BRANCHES[#]
declare -A BRANCHES
BRANCHES[Baseline]=
fi
for BRANCH in "${!BRANCHES[#]}"; do
echo "BRANCH: $BRANCH"
if [ $BRANCH == "Baseline" ]; then BRANCH=; fi
img_dir=$(ls -td -- ${BASE_PATH}/${BRANCH}/*/ | head -n 1)
echo "img_dir: $img_dir"
IMG_PATH=$(ls $img_dir*.rpm)
echo "IMG_PATH: $IMG_PATH"
cd $img_dir
IMG_NAME=$(ls *.rpm) > env.properties
if [ ! -z "$IMG_NAME" ]; then
if [ $(( $(date +%s) - $(stat -c %Z $IMG_PATH) )) -lt 10000800 ]; then
echo "IMG_NAME: ${IMG_NAME}"
#BRANCHES[$BRANCH]=$IMG_PATH
#echo "REG_OSA_SOFTSYNC_BUILD_IMG_FULL_PATH=${BRANCHES[$BRANCH]}" >> ${WORKSPACE}/$BRANCH.txt
echo "BRANCH_NAME=$BRANCH" >> ${WORKSPACE}/${BRANCH}_branch.txt
echo "REG_OSA_SOFTSYNC_BUILD_NAME=$BRANCH-$IMG_NAME" >> ${WORKSPACE}/${BRANCH}_branch.txt
else
echo "$IMG_NAME is out dated"
fi
else
echo "IMG_NAME is empty"
fi
BRANCH_NAME=""
done
$TEMP=$BRANCH_NAME
echo "TEMP: $TEMP"
if [ $(ls ${WORKSPACE}/*_branch.txt | wc -l) == $(echo ${#BRANCHES[#]}) ]; then break; fi
#for i in $(ls *_branch.txt); do i=$(echo $i | awk -F '_branch.txt' '{print $1}'); if [ $(echo ${!BRANCHES[#]} | grep $i | wc -l) == 0 ]; then state=1 break; fi done
i=$[$i+1]
sleep 1800
done
This is the "Trigger parameterized build on other projects" configuration:

cron not running in alpine docker

I have created and added below entry in my entry-point.sh for docker file.
# start cron
/usr/sbin/crond &
exec "${DIST}/bin/ss" "$#"
my crontab.txt looks like below:
bash-4.4$ crontab -l
*/5 * * * * /cleanDisk.sh >> /apps/log/cleanDisk.log
So when I run the docker container, i don't see any file created called as cleanDisk.log.
I have setup all permissions and crond is running as a process in my container see below.
bash-4.4$ ps -ef | grep cron
12 sdc 0:00 /usr/sbin/crond
208 sdc 0:00 grep cron
SO, can anyone, guide me why the log file is not getting created?
my cleanDisk.sh looks like below. Since it runs for very first time,and it doesn't match all the criteria, so I would expect at least to print "No Error file found on Host $(hostname)" in cleanDisk.log.
#!/bin/bash
THRESHOLD_LIMIT=20
RETENTION_DAY=3
df -Ph /apps/ | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print $5,$1 }' | while read output
do
#echo $output
used=$(echo $output | awk '{print $1}' | sed s/%//g)
partition=$(echo $output | awk '{print $2}')
if [ $used -ge ${THRESHOLD_LIMIT} ]; then
echo "The partition \"$partition\" on $(hostname) has used $used% at $(date)"
FILE_COUNT=$(find ${SDC_LOG} -maxdepth 1 -mtime +${RETENTION_DAY} -type f -name "sdc-*.sdc" -print | wc -l)
if [ ${FILE_COUNT} -gt 0 ]; then
echo "There are ${FILE_COUNT} files older than ${RETENTION_DAY} days on Host $(hostname)."
for FILENAME in $(find ${SDC_LOG} -maxdepth 1 -mtime +${RETENTION_DAY} -type f -name "sdc-*.sdc" -print);
do
ERROR_FILE_SIZE=$(stat -c%s ${FILENAME} | awk '{ split( "B KB MB GB TB PB" , v ); s=1; while( $1>1024 ){ $1/=1024; s++ } printf "%.2f %s\n", $1, v[s] }')
echo "Before Deleting Error file ${FILENAME}, the size was ${ERROR_FILE_SIZE}."
rm -rf ${FILENAME}
rc=$?
if [[ $rc -eq 0 ]];
then
echo "Error log file ${FILENAME} with size ${ERROR_FILE_SIZE} is deleted on Host $(hostname)."
fi
done
fi
if [ ${FILE_COUNT} -eq 0 ]; then
echo "No Error file found on Host $(hostname)."
fi
fi
done
edit
my docker file looks like this
FROM adoptopenjdk/openjdk8:jdk8u192-b12-alpine
ARG SDC_UID=20159
ARG SDC_GID=20159
ARG SDC_USER=sdc
RUN apk add --update --no-cache bash \
busybox-suid \
sudo && \
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf
RUN addgroup --system ${SDC_USER} && \
adduser --system --disabled-password -u ${SDC_UID} -G ${SDC_USER} ${SDC_USER}
ADD --chown=sdc:sdc crontab.txt /etc/crontabs/sdc/
RUN chgrp sdc /etc/cron.d /etc/crontabs /usr/bin/crontab
# Also tried to run like this but not working
# RUN /usr/bin/crontab -u sdc /etc/crontabs/sdc/crontab.txt
USER ${SDC_USER}
EXPOSE 18631
RUN /usr/bin/crontab /etc/crontabs/sdc/crontab.txt
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["dc", "-exec"]

How to get packets statistics by port

Is there a better way to get port statistics, such as stat by source port, or destination port?
for example to get results like below:
--------------------------------
| Src/Dst Port | Packets Count |
| -----------------------------|
| 22 | 100 |
| -----------------------------|
| 80 | 200 |
|------------------------------|
| 8080 | 300 |
| -----------------------------|
I have checked wireshark's Statistics menu, and tshark command, but still don't know how to get the results I want.
I don't believe it's possible to directly get this summary information from either Wireshark or tshark, but you can probably write a script to do it.
Here's one such script that may help you get started:
#!/bin/sh
# Check usage
if (( ${#} < 2 )) ; then
echo "Usage: $0 <file> <type> ... where type is udp or tcp"
exit 1
fi
# Sanity check if the file specified actually exists or not
stat ${1} &> /dev/null
if [ $? -ne 0 ] ; then
echo "File ${1} doesn't exist"
exit 2
fi
# Validate the type
if [ "${2}" != "udp" -a "${2}" != "tcp" ] ; then
echo "Invalid type ${2}. Specify either udp or tcp."
exit 3
fi
echo "Src/Dst Port | Packets Count"
tshark -nq -r ${1} -z endpoints,${2} | grep "^[1-9]" | tr -s ' ' | cut -s -d ' ' -f 2,3 | sort -n | gawk '{arr[$1]+=$2} END {for (i in arr) {print i,arr[i]}}'

RedHat Memory Used High

Looking for some help if you will..
I have a virtual machine on RedHat 6.5 with 32gb memory.
A free is showing 24.6gb used, 8.2gb free. Only 418mb is cached, 1.8gb buffers.
Executed a top and sorted by virtual used, and I can only account for about 6gb of that 24.6gb used.
A "ps aux" doesn't show any processes that could be taking the memory.
I am flummoxed and looking for some advice on where I can look to see whats taking the memory?
Any help would be appreciated.
Below Bash Script will help you figure out which application is consuming how much of memory.
#!/bin/bash
# Make sure only root can run our script
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root" 1>&2
exit 1
fi
### Functions
#This function will count memory statistic for passed PID
get_process_mem ()
{
PID=$1
#we need to check if 2 files exist
if [ -f /proc/$PID/status ];
then
if [ -f /proc/$PID/smaps ];
then
#here we count memory usage, Pss, Private and Shared = Pss-Private
Pss=`cat /proc/$PID/smaps | grep -e "^Pss:" | awk '{print $2}'| paste -sd+ | bc `
Private=`cat /proc/$PID/smaps | grep -e "^Private" | awk '{print $2}'| paste -sd+ | bc `
#we need to be sure that we count Pss and Private memory, to avoid errors
if [ x"$Rss" != "x" -o x"$Private" != "x" ];
then
let Shared=${Pss}-${Private}
Name=`cat /proc/$PID/status | grep -e "^Name:" |cut -d':' -f2`
#we keep all results in bytes
let Shared=${Shared}*1024
let Private=${Private}*1024
let Sum=${Shared}+${Private}
echo -e "$Private + $Shared = $Sum \t $Name"
fi
fi
fi
}
#this function make conversion from bytes to Kb or Mb or Gb
convert()
{
value=$1
power=0
#if value 0, we make it like 0.00
if [ "$value" = "0" ];
then
value="0.00"
fi
#We make conversion till value bigger than 1024, and if yes we divide by 1024
while [ $(echo "${value} > 1024"|bc) -eq 1 ]
do
value=$(echo "scale=2;${value}/1024" |bc)
let power=$power+1
done
#this part get b,kb,mb or gb according to number of divisions
case $power in
0) reg=b;;
1) reg=kb;;
2) reg=mb;;
3) reg=gb;;
esac
echo -n "${value} ${reg} "
}
#to ensure that temp files not exist
[[ -f /tmp/res ]] && rm -f /tmp/res
[[ -f /tmp/res2 ]] && rm -f /tmp/res2
[[ -f /tmp/res3 ]] && rm -f /tmp/res3
#if argument passed script will show statistic only for that pid, of not – we list all processes in /proc/ #and get statistic for all of them, all result we store in file /tmp/res
if [ $# -eq 0 ]
then
pids=`ls /proc | grep -e [0-9] | grep -v [A-Za-z] `
for i in $pids
do
get_process_mem $i >> /tmp/res
done
else
get_process_mem $1>> /tmp/res
fi
#This will sort result by memory usage
cat /tmp/res | sort -gr -k 5 > /tmp/res2
#this part will get uniq names from process list, and we will add all lines with same process list
#we will count nomber of processes with same name, so if more that 1 process where will be
# process(2) in output
for Name in `cat /tmp/res2 | awk '{print $6}' | sort | uniq`
do
count=`cat /tmp/res2 | awk -v src=$Name '{if ($6==src) {print $6}}'|wc -l| awk '{print $1}'`
if [ $count = "1" ];
then
count=""
else
count="(${count})"
fi
VmSizeKB=`cat /tmp/res2 | awk -v src=$Name '{if ($6==src) {print $1}}' | paste -sd+ | bc`
VmRssKB=`cat /tmp/res2 | awk -v src=$Name '{if ($6==src) {print $3}}' | paste -sd+ | bc`
total=`cat /tmp/res2 | awk '{print $5}' | paste -sd+ | bc`
Sum=`echo "${VmRssKB}+${VmSizeKB}"|bc`
#all result stored in /tmp/res3 file
echo -e "$VmSizeKB + $VmRssKB = $Sum \t ${Name}${count}" >>/tmp/res3
done
#this make sort once more.
cat /tmp/res3 | sort -gr -k 5 | uniq > /tmp/res
#now we print result , first header
echo -e "Private \t + \t Shared \t = \t RAM used \t Program"
#after we read line by line of temp file
while read line
do
echo $line | while read a b c d e f
do
#we print all processes if Ram used if not 0
if [ $e != "0" ]; then
#here we use function that make conversion
echo -en "`convert $a` \t $b \t `convert $c` \t $d \t `convert $e` \t $f"
echo ""
fi
done
done < /tmp/res #this part print footer, with counted Ram usage echo "--------------------------------------------------------" echo -e "\t\t\t\t\t\t `convert $total`" echo "========================================================" # we clean temporary file [[ -f /tmp/res ]] && rm -f /tmp/res [[ -f /tmp/res2 ]] && rm -f /tmp/res2 [[ -f /tmp/res3 ]] && rm -f /tmp/res3
I am going to take a wild stab at this. Without having access to the machine or additional information troubleshooting this will be difficult.
The /tmp file system is special in that it exists entirely in memory. There are a couple others that are like this but /tmp is a special flower. Check the disk usage on this directory and you may see where your memory is getting consumed. ( du -sh /tmp )

Look through the last 15 lines of a log file to check for "error" repeated 3 times and execute a command

I would like a script that would read the last 15 lines of a text file and if the word "error" appears more than 3 times it would execute a command.
#!/bin/bash
if [ `tail -15 <file> | grep error | wc -l` -gt 3 ]
then
echo "Too many errors..."
else
echo "Everything is fine."
fi
Or on the command line:
if [ `tail -15 <file> | grep error | wc -l` -gt 3 ]; then echo "Too many errors..."; else echo "Everything is fine."; fi

Resources