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 :)
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
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.
Thanks Fred! This is very handy. The output is well formatted. Love it!
Very useful, Thanks!
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
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.
Nice script, sir.
Can you please update the script to show individual file size?
Thanks.
Excellent Script. Very Helpful.
Hi,
this is clever and very good – thank you for sharing.
thanks
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
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
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) ;} ‘
Solaris also has awk and for this simple script it should be working. no ?
This is a great script!! thanks!!!
HI,
Thank you very much for this script. It is very useful.
That is beautiful. Congrats
Very nice and sweet one , Thanks for the script.