asmcmd> a better “du”

Posted in: Oracle, Technical Track

Edit April 2018 : a new version of this script is available here

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 :

[oracle@higgins ~]$ ps -ef | grep pmon | wc -l
30
[oracle@higgins ~]$

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 :

[oracle@higgins ~]$ 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)                 ;} '
[oracle@higgins ~]$
Let's see it in action with some real life examples :
[oracle@higgins ~]$. oraenv
ORACLE_SID = [+ASM] ? +ASM
The Oracle base remains unchanged with value /oracle
[oracle@higgins ~]$./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
[oracle@higgins ~]$

 

Another one with many archivelogs directories :
[oracle@higgins ~]$./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
[oracle@higgins ~]$

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

Author

Interested in working with Fred? Schedule a tech call.

15 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) :

[oracle@a_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
[oracle@a_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.

grid@aavutord10:~$ 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) ;} ‘

grid@aavutord10:~$ ./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

Leave a Reply

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