BASH Free Space Script: Variation - bash

I made a script in order to check the available space on root, /var, /tmp, /usr and /opt since I need 1.5G free on each of them. Of course, there are times when all those are in root, not in another partitions.
But I got some error from my script:
1- Sometimes the output its weird when it runs in a non-English System.
2- --output in df -h its not available since some systems are old.
I want to change this script a little bit since I want it to work in every machine and I would like to ask for ideas.
I have tested the script on 650 machines already. 140 of them created the problems that I mention.
printf "root=" ; df -h --output=avail / | grep -v Avail | xargs | tr -d '[:space:]'
printf ",opt=" ; df -h --output=avail /opt | grep -v Avail | xargs | tr -d '[:space:]'
printf ",usr=" ; df -h --output=avail /usr | grep -v Avail | xargs | tr -d '[:space:]'
printf ",tmp=" ; df -h --output=avail /tmp | grep -v Avail | xargs | tr -d '[:space:]'
printf ",var=" ; df -h --output=avail /var | grep -v Avail | xargs
1- Problem:
Wrong: root=Dispo 1.5G,var=Dispo 1.5G,usr=Dispo 1.5G,tmp=Dispo
1.5G,opt=Dispo 1.5G
Correct: root=1.5G,var=1.5G,usr=1.5G,tmp=1.5G,opt=1.5G
2- Problem:
df: Unbekannte Option »--output=avail«
„df --help“ gibt weitere Informationen.
root= opt= usr= tmp= var=
EDIT:
Looks like #CharlesDufy answer worked. I made the script like this:
#!/bin/bash
sudo df -h / /var /tmp /opt /usr > freespace.txt
rootSpace=$(awk "NR==2 { print $4 }" freespace.txt)
varSpace=$(awk "NR==3 { print $4 }" freespace.txt)
tmpSpace=$(awk "NR==4 { print $4 }" freespace.txt)
optSpace=$(awk "NR==5 { print $4 }" freespace.txt)
usrSpace=$(awk "NR==6 { print $4 }" freespace.txt)
customProp="root=$rootSpace,var=$varSpace,tmp=$tmpSpace,opt=$optSpace,usr=$usrSpace"
#and the rest....
Also I want to ask 2 more questions:
Is it possible to take the freespace.txt output without creating a file?
If the 4 folders are in root, like they are not separte partitions, my output looks like this
root=12G,var=12G,tmp=12G,opt=12G,usr=12G
Is there a way to make an output like this without tons of IF, ELIF or ELSE comands?
root=12G,var=root,tmp=root,opt=root,usr=root

Related

Named pipe swallowing first field of Linux command output

I'm trying to parse the output of the Linux df tool for use in a machine status report. I'm using almost identical code to parse the output of the ps tool and it works fine (all fields are available in read loop) but in the code below the first field output from awk (percentUsed) is missing when I read from the named pipe.
#!/bin/sh
mkfifo dfPipe0
IFS=" "
df -h | awk '{ print $6" "$3" "$7" "$1 }' > dfPipe0 &
while read -r percentUsed size mountedOn fileSystem
do
printf "%s\n" "${percentUsed} | ${size} | ${mountedOn} | ${fileSystem}"
done < dfPipe0
rm dfPipe0
Sample df + awk output
$ df -h | awk '{ print $6" "$3" "$7" "$1 }'
Use% Size Mounted Filesystem
0% 1.9G /dev devtmpfs
- 0 /sys/kernel/security securityfs
4% 1.9G /dev/shm tmpfs
$
I edited my code to use the standard pipe suggestion by #Barmar and it resolves my problem. The code below works fine.
df -h | \
while read -r fileSystem size used avail percentUsed mountedOn
do printf "%s\n" "$fileSystem | $size | $used | $avail | $percentUsed | $mountedOn"
done

How to `rm` files as awk action?

This one-liner:
sudo df /tmp \
| grep '/tmp' \
| expand - \
| cut -d " " -f 12 \
| sed 's/%//' \
| awk '{ if ($1<50)
$("sudo rm -rf /path/to/trash/files/*")
}'
seems to have no effect, while this:
sudo df /tmp \
| grep '/tmp' \
| expand - \
| cut -d " " -f 12 \
| sed 's/%//' \
| awk '{ if ($1<50)
print $1
}'
prints the percentage of disk used for tmp.
(The end goal is to flip the comparison around to ($1>50), but for testing I'm trying <.)
You don't really need so many commands in pipeline with awk.
You can just use:
df /tmp | awk 'NR>1 && $5+0 > 50 {system ("date")}'
Here change date command to something else that you need to run there.

How to add shell script to jenkins pipeline

I have the below shell script:
du -sh /bbhome/shared/data/repositories/* |sort -h |tail -20 |
while IFS= read -r line;do
DIR=`echo $line | awk '{print$2}'`
Rep=`cat $DIR/repository-config |grep 'project\|repo' | tr '\n' ' '`
Size=`echo $line | awk '{print $1}' `
echo $Size $Rep
done
How can I run it thought Execute shell in Jenkins? I need also to add ssh command to the env (no need for a password).
Note I don't want to connect to the env and run this shell, but directly from Excecue shell box
If I'm not wrong your are using a Freestyle job and not a pipeline job.
Anyway, I think you have to try the following :
ssh -t XXXXX#YYYYY << 'EOF'
du -sh /bbhome/shared/data/repositories/* |sort -h |tail -20 |
while IFS= read -r line;do\
DIR=echo $line | awk '{print$2}'\
Rep=cat $DIR/repository-config |grep 'project\|repo' | tr '\n' ' '\
Size=echo $line | awk '{print $1}' \
echo $Size $Rep\
done
EOF
I've escaped the code inside your while loop using \, if it's doesn't works you can use ; instead.
If you want help for using a pipeline job, let me know but i might be a bit more complex.

Need help escaping from awk quotations in bash script

I have an alias in my bashrc file that outputs current folder contents and system available storage, updated continuously by the watch function.
alias wtch='watch -n 0 -t "du -sch * -B 1000000 2>/dev/null | sort -h && df -h -B 1000000| head -2 | awk '{print \$4}'"'
The string worked fine until I put in the awk part. I know I need to escape the single quotation marks, while still staying in the double quotation marks and the $4 but I haven't been able to get it to work. What am I doing wrong?
This is the error I get
-bash: alias: $4}": not found
Since the quoting for the alias is making it tough, you could just make it a function instead:
wtch() {
watch -n 0 -t "du -sch * -B 1000000 2>/dev/null | sort -h && df -h -B 1000000| head -2 | awk '{print $4}'"
}
This is a lot like issue 2 in the BashFAQ/050
Also, a minor thing but you can skip the head process at the end and just have awk do it, even exiting after the second row like
wtch() {
watch -n 0 -t "du -sch * -B 1000000 2>/dev/null | sort -h && df -h -B 1000000| awk '{print $4} NR >= 3 {exit}'"
}
In this case you can use cut instead of awk. And you'll have the same effect.
alias wtch="watch -n 0 -t 'du -sch * -B 1000000 2>/dev/null | sort -h && df -h -B 1000000| head -2 | cut -d\ -f4'"
Explaining cut:
-d option defines a delimiter
-d\ means that my delimiter is space
-f selects a column
-f4 gives you the fourth column

OpenLDAP: get `directory` from cn=config

How can I get directory for specified DN by one ldapsearch request?
I mean - I have few databases. OpenLDAP configured with cn=config. For each DN - it hve own ldif-file, where it's olcDbDirectory specified.
Can I obtain olcDbDirectory value for each DN?
For backup script - I need to set varibale which contains directory, and this variable changes every time for every DN, wich backuped/restored at this moment.
So - in bash I just found solution to create function like:
#!/bin/bash
getDir () {
file=`grep -R "$1" /etc/openldap/slapd.d/ | cut -d":" -f 1 | tail -n 1`
echo $file
dir=`cat $file | grep "olcDbDirectory" | awk '{print $2}'`
echo $dir
}
getDir testdb;
$ ./dn.sh
/etc/openldap/slapd.d/cn=config/olcDatabase={9}bdb.ldif
/var/lib/ldap/testdb
But this solution seems not tidy... And I'd preffered to use something like:
getDir () {
dir=`ldapsearch -x -D "cn-root,cn=config" "*somefilter*"
}
Here it is:
$ ldapsearch -x -LLL -D 'cn=root,cn=config' -w PassWord -b 'cn=config' '(&(olcDbDirectory=*)(olcSuffix='testdb'))' olcDbDirectory | grep "olcDbDirectory" | cut -d":" -f 2
/var/lib/ldap/testdb
Of in bash function:
#!/bin/bash
getDir () {
dirtodel=`ldapsearch -x -LLL -D 'cn=root,cn=config' -w PassWord -b 'cn=config' '(&(olcDbDirectory=*)(olcSuffix='${1}'))' olcDbDirectory | grep "olcDbDirectory" | cut -d":" -f 2`
echo $dirtodel
}
getDir 'dc=testdb'
Result:
$ ./dn.sh
/var/lib/ldap/testdb

Resources