asmcmd> a better “du”

Posted in: Oracle, Technical Track

I discovered ASM with a 10.1.0.3 RAC running on Linux Itanium and that was a big adventure. At this time there was no asmcmd. In 2005, Oracle released Oracle 10gR2 and asmcmd came into the place and we figured out how to make it work with a 10gR1 ASM. We were very excited to have a command line for ASM until… we tried it ! let’s call a spade a spade,  it was very poor…

10 years after, Oracle has released 11gR1, 11gR2, 12cR1, asmcmd has been improved but the “ASM shell” remains very weak and specially the “du” command :

ASMCMD> du
Used_MB Mirror_used_MB
556178 556178
ASMCMD> du .
Used_MB Mirror_used_MB
556178 556178
ASMCMD> du *
Used_MB Mirror_used_MB
556265 556265
ASMCMD> ls
ASM_CONFIG/
DATA/
FRA/
LOG/
ASMCMD>

Why “du *” does not act as it acts in any Unix shell ? How do I know the size of each subdirectory in my current directory ?

 

Nowadays, we use to have dozens of instances running on the same server sharing the same ASM :

[[email protected] ~]$ ps -ef | grep pmon | wc -l
30
[[email protected] ~]$

so should I use one “du” per database (directory) to know the size used by each database ? what if I keep one month of archivelogs in my FRA ? should I wait for the month of February to have only 28 “du” to perform if I want to know the size of archivelogs generated each day (if this is a non-leap year !) ?

 

This is why I wrote this piece of code to have a “du” under ASM that makes my life easier everyday :

[[email protected] ~]$ cat asmdu.sh
#!/bin/bash
#
# du of each subdirectory in a directory for ASM
#
D=$1
if [[ -z $D ]]
then
echo "Please provide a directory !"
exit 1
fi
(for DIR in `asmcmd ls ${D}`
do
echo ${DIR} `asmcmd du ${D}/${DIR} | tail -1`
done) | awk -v D="$D" ' BEGIN { printf("\n\t\t%40s\n\n", D " subdirectories size") ;
printf("%25s%16s%16s\n", "Subdir", "Used MB", "Mirror MB") ;
printf("%25s%16s%16s\n", "------", "-------", "---------") ;}
{
printf("%25s%16s%16s\n", $1, $2, $3) ;
use += $2 ;
mir += $3 ;
}
END { printf("\n\n%25s%16s%16s\n", "------", "-------", "---------");
printf("%25s%16s%16s\n\n", "Total", use, mir) ;} '
[[email protected] ~]$
Let's see it in action with some real life examples :
[[email protected] ~]$. oraenv
ORACLE_SID = [+ASM] ? +ASM
The Oracle base remains unchanged with value /oracle
[[email protected] ~]$./asmdu.sh DATA
DATA subdirectories size
Subdir  Used MB Mirror MB
------  ------- --------
DB01/ 2423 2423
DB02/ 2642    2642
DB03/ 321201  321201
DB04/ 39491   39491
DB05/ 180753  180753
DB06/ 4672    4672
DB07/ 1431    1431
DB08/ 2653    2653
DB09/ 70942   70942
DB10/ 96001   96001
DB11/ 57322   57322
DB12/ 70989   70989
DB13/ 4639    4639
DB14/ 40800   40800
DB15/ 13397   13397
DB16/ 15279 15279
DB17/ 19020 19020
DB18/ 8886 8886
DB19/ 4671 4671
DB20/ 14994 14994
DB21/ 502245 502245
DB22/ 4839 4839
DB23/ 10169 10169
DB24/ 7772 7772
DB25/ 7828 7828
DB26/ 112109 112109
DB27/ 5564 5564
DB28/ 16895 16895
------ ------- ---------
Total 1639627 1639627
[[email protected] ~]$

 

Another one with many archivelogs directories :
[[email protected] ~]$./asmdu.sh FRA/THE_DB/ARCHIVELOG/
FRA/THE_DB/ARCHIVELOG/ subdirectories size
Subdir Used MB Mirror MB
------ ------ ---------
2015_02_19/ 114 114
2015_02_20/ 147 147
2015_02_21/ 112 112
2015_02_22/ 137 137
2015_02_23/ 150 150
2015_02_24/ 126 126
2015_02_25/ 135 135
2015_02_26/ 130 130
2015_02_27/ 129 129
2015_02_28/ 119 119
2015_03_01/ 146 146
2015_03_02/ 150 150
2015_03_03/ 128 128
2015_03_04/ 134 134
2015_03_05/ 44 44
2015_05_27/ 28 28
2015_05_28/ 95 95
2015_05_29/ 76 76
2015_05_30/ 187 187
2015_05_31/ 78 78
2015_06_01/ 111 111
2015_06_02/ 105 105
2015_06_03/ 43 43
2015_06_04/ 142 142
2015_06_05/ 42 42
2015_06_06/ 84 84
2015_06_07/ 70 70
2015_06_08/ 134 134
2015_06_09/ 77 77
2015_06_10/ 143 143
2015_06_11/ 2 2
2015_06_21/ 14 14
2015_06_22/ 14918 14918
------ ------- ---------
Total 18250 18250
[[email protected] ~]$

This example is a very nice one as it shows us that 2015 is not a leap year and that some archivelogs are still on disk even if they probably shouldn’t and that’s a good information as v$log_history do not contain these information anymore :

SQL> select trunc(FIRST_TIME), count(*) from v$log_history group by trunc(FIRST_TIME) order by 1 ;
TRUNC(FIR COUNT(*)
--------- ----------
22-JUN-15 402
SQL>

Hope it will also makes your life easier,

Have a good day :)

email
Want to talk with an expert? Schedule a call with our team to get the conversation started.

17 Comments. Leave new

That’s pretty cool Fred, thanks for sharing.
Here’s a tip for ps that I learned long ago:
ps -fe | grep [p]mon
The regular expression prevents the ‘ps’ command from appearing

oravm02-jkstill-~-10:07:43
> ps -fe| grep pmon
oracle 20436 1 0 Jul22 ? 00:00:03 asm_pmon_+ASM2
jkstill 20703 20513 0 10:07 pts/6 00:00:00 grep pmon
oracle 20845 1 0 Jul22 ? 00:00:22 ora_pmon_oravm2

oravm02-jkstill-~-10:07:49
> ps -fe| grep [p]mon
oracle 20436 1 0 Jul22 ? 00:00:03 asm_pmon_+ASM2
oracle 20845 1 0 Jul22 ? 00:00:22 ora_pmon_oravm2

Reply

Hi Jared,

Thanks for your comment.

The ps I wrote to count the number of instances also count the grep on purpose. This was to show that nowadays we use to have “lots” of instances sharing the same ASM, no matter if it’s 29, 30 or 31.

Anyway, thanks for your nice tip. I however found a server where it doesn’t work ( I don’t know why, this is a RH 5.9) :

[[email protected]_linux ~]$ ps -ef | grep [p]mon
oracle 880 1 0 Aug30 ? 00:00:00 ora_pmon_DB1
oracle 8886 1 0 Aug30 ? 00:00:00 ora_pmon_DB2
oracle 9411 1 0 Aug30 ? 00:00:00 asm_pmon_+ASM
oracle 14300 1 0 Aug30 ? 00:00:00 ora_pmon_DB3
oracle 14302 1 0 Aug30 ? 00:00:00 ora_pmon_DB4
oracle 14476 1 0 Aug30 ? 00:00:00 ora_pmon_DB5
oracle 14586 1 0 Aug30 ? 00:00:00 ora_pmon_DB6
oracle 14900 1 0 Aug30 ? 00:00:00 ora_pmon_DB7
oracle 20380 1 0 Aug30 ? 00:00:00 ora_pmon_DB8
oracle 22341 1 0 Aug30 ? 00:00:00 ora_pmon_DB9
oracle 22627 1 0 Aug30 ? 00:00:00 ora_pmon_DB10
oracle 25516 10636 0 00:36 pts/2 00:00:00 grep pmon <= !?
oracle 28860 1 0 Aug30 ? 00:00:00 ora_pmon_DB11
[[email protected]_linux ~]$

To remove the grep in the list, I use to use :

$ ps -ef | grep pmon | grep -v grep
or
$ ps -ef | egrep "(asm|ora)_pmon_"

Never found a server where it didn't work.

Reply

Thanks Fred! This is very handy. The output is well formatted. Love it!

Reply

Very useful, Thanks!

Reply
JayaKishore Udayagiri
January 24, 2018 8:11 pm

Hi Fred,

Thank You So Much for this script. But could you please enlarge it . As of Now it is doing DU on directories on immediate level. But if we want to see inside them too.
What I mean is If I have 3 databases running and want to See FLASH diskgroup utilization it gives only for DB level not in inside each directory of DB. It is asking too much but could you please write script for that also. Because in shot We get all details and clear picture who is using how much.

Thanks
JK

Reply

FYI, the script will not work on Solaris. I’m assuming you wrote it on Linux. It would be nice to add a note about that stating the supported OS.

Thanks.

Reply

Nice script, sir.

Can you please update the script to show individual file size?

Thanks.

Reply

Excellent Script. Very Helpful.

Reply

Hi,

this is clever and very good – thank you for sharing.

thanks

Reply
Karunakar Reddy
July 5, 2019 7:07 pm

Excellent script very helpfull it is not working on solaris.

[email protected]:~$ cat asmdu.sh
+ cat asmdu.sh
#
# asmdu.sh of each subdirectory in a directory for ASM
# Usage Ex1 : ./asmdu.sh DATA
# Usage Ex2: ./asmdu.sh FRA/THE_DB/ARCHIVELOG/
#
D=$1

if [[ -z $D ]]
then
echo “Please provide a directory !”
exit 1
fi

(for DIR in `asmcmd ls ${D}`
do
echo ${DIR} `asmcmd du ${D}/${DIR} | tail -1`
done) | awk -v D=”$D” ‘ BEGIN { printf(“\n\t\t%40s\n\n”, D ” subdirectories size”) ;
printf(“%25s%16s%16s\n”, “Subdir”, “Used MB”, “Mirror MB”) ;
printf(“%25s%16s%16s\n”, “——“, “——-“, “———“) ;}
{
printf(“%25s%16s%16s\n”, $1, $2, $3) ;
use += $2 ;
mir += $3 ;
}
END { printf(“\n\n%25s%16s%16s\n”, “——“, “——-“, “———“);
printf(“%25s%16s%16s\n\n”, “Total”, use, mir) ;} ‘

[email protected]:~$ ./asmdu.sh DATA04
+ ./asmdu.sh DATA04
awk: syntax error near line 1
awk: bailing out near line 1

Reply

Hi,

Please use the latest version : https://unknowndba.blogspot.com/2018/03/asmdush-far-better-du-for-asmcmd.html?m=1 and let me know.

Fred

Reply
Karunakar Reddy
July 11, 2019 10:18 pm

solaris not taking awk insted it is taking nawk. Worked script on solaris is below

cat asmdu.sh
#!/usr/bin/bash
#
# asmdu.sh of each subdirectory in a directory for ASM
# Usage Ex1 : ./asmdu.sh DATA
# Ex2: ./asmdu.sh FRA/THE_DB/ARCHIVELOG/
#
D=$1

if [[ -z $D ]]
then
echo “Please provide a directory !”
exit 1
fi

(for DIR in `asmcmd ls ${D}`
do
echo ${DIR} `asmcmd du ${D}/${DIR} | tail -1`
done) | nawk -v D=”$D” ‘ BEGIN { printf(“\n\t\t%40s\n\n”, D ” subdirectories size”) ;
printf(“%25s%16s%16s\n”, “Subdir”, “Used MB”, “Mirror MB”) ;
printf(“%25s%16s%16s\n”, “——“, “——-“, “———“) ;}
{
printf(“%25s%16s%16s\n”, $1, $2, $3) ;
use += $2 ;
mir += $3 ;
}
END { printf(“\n\n%25s%16s%16s\n”, “——“, “——-“, “———“);
printf(“%25s%16s%16s\n\n”, “Total”, use, mir) ;} ‘

Reply

Solaris also has awk and for this simple script it should be working. no ?

Reply

This is a great script!! thanks!!!

Reply
NAGARAJU PEETA
January 16, 2021 12:39 am

HI,
Thank you very much for this script. It is very useful.

Reply

That is beautiful. Congrats

Reply
Sakthivel Govindasamy
October 5, 2022 12:00 pm

Very nice and sweet one , Thanks for the script.

Reply

Leave a Reply

Your email address will not be published. Required fields are marked *