Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 SQL Server Administration (2000)
 Determining space on drives

Author  Topic 

Wanderer
Master Smack Fu Yak Hacker

1168 Posts

Posted - 2006-05-22 : 05:31:01
Hi all,

Done a bit of searching, trying to find out where/how I might get the size of drives/partitions on a machine. I'm specifically looking for drives size, and not usage, so sp_spaceused etc. is not what I'm looking for. Similarly, while xp_fixeddrives is useful info, it's not what I'm looking for - I guess I'm looking for a 'xp_fixeddrivessize' sp, or technique.

Any ideas other than using a cumulation of space used per directory, and space free?

TIA

*##* *##* *##* *##*

Chaos, Disorder and Panic ... my work is done here!

schuhtl
Posting Yak Master

102 Posts

Posted - 2006-05-22 : 07:43:07
I did not write the sp below and I can't remember where I found it but I think it will work for you...you might have to tweak it a bit to get exactly what you are looking for!

use master
go

CREATE PROCEDURE sp_diskspace
AS
/*
Displays the free space,free space percentage
plus total drive size for a server
*/
SET NOCOUNT ON

DECLARE @hr int
DECLARE @fso int
DECLARE @drive char(1)
DECLARE @odrive int
DECLARE @TotalSize varchar(20)
DECLARE @MB bigint ; SET @MB = 1048576

CREATE TABLE #drives (drive char(1) PRIMARY KEY,
FreeSpace int NULL,
TotalSize int NULL)

INSERT #drives(drive,FreeSpace)
EXEC master.dbo.xp_fixeddrives

EXEC @hr=sp_OACreate 'Scripting.FileSystemObject',@fso OUT
IF @hr <> 0 EXEC sp_OAGetErrorInfo @fso

DECLARE dcur CURSOR LOCAL FAST_FORWARD
FOR SELECT drive from #drives
ORDER by drive

OPEN dcur

FETCH NEXT FROM dcur INTO @drive

WHILE @@FETCH_STATUS=0
BEGIN

EXEC @hr = sp_OAMethod @fso,'GetDrive', @odrive OUT, @drive
IF @hr <> 0 EXEC sp_OAGetErrorInfo @fso

EXEC @hr = sp_OAGetProperty @odrive,'TotalSize', @TotalSize OUT
IF @hr <> 0 EXEC sp_OAGetErrorInfo @odrive

UPDATE #drives
SET TotalSize=@TotalSize/@MB
WHERE drive=@drive

FETCH NEXT FROM dcur INTO @drive

END

CLOSE dcur
DEALLOCATE dcur

EXEC @hr=sp_OADestroy @fso
IF @hr <> 0 EXEC sp_OAGetErrorInfo @fso

SELECT drive,
FreeSpace as 'Free(MB)',
TotalSize as 'Total(MB)',
CAST((FreeSpace/(TotalSize*1.0))*100.0 as int) as 'Free(%)'
FROM #drives
ORDER BY drive

DROP TABLE #drives

RETURN
go


Go to Top of Page

Wanderer
Master Smack Fu Yak Hacker

1168 Posts

Posted - 2006-05-22 : 08:13:58
Thanks - that pretty much did what I wanted. Now I need to weigh up the pro's and con's of using sp_OA* stored proc's, especially if it was to be on a production procedure. Anyone got any insight/opinions?

*##* *##* *##* *##*

Chaos, Disorder and Panic ... my work is done here!
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

7020 Posts

Posted - 2006-05-22 : 10:22:35
You can use the PSInfo command line utility with the -d option to get this info. You can get this utility here:
http://www.sysinternals.com/Utilities/PsInfo.html

You can get the whole suite of PSTools command line utilities here:
http://www.sysinternals.com/utilities/pstools.html






CODO ERGO SUM
Go to Top of Page

Wanderer
Master Smack Fu Yak Hacker

1168 Posts

Posted - 2006-05-22 : 10:35:05
Thanks Michael. Note sure, but I think I'd rather go the route of invoking sp_OA* than using xp_cmdshell to run PSInfo to get the data. My gut says that it'll be less intrusive, and it certain will be easier to store that data into a table and track trends, usage etc., using the sp_diskspace stored procedure...

*##* *##* *##* *##*

Chaos, Disorder and Panic ... my work is done here!
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

7020 Posts

Posted - 2006-05-22 : 12:02:00
quote:
Originally posted by Wanderer
...My gut says that it'll be less intrusive, and it certain will be easier to store that data into a table and track trends, usage etc., using the sp_diskspace stored procedure...



Perhaps, but how do you know until you have looked into it?

One advantage of PsInfo is that it is also designed to run against remote servers, so you can collect info on all your servers in one spot.


drop table #t
go
create table #t (
output varchar(2000) null,
seq int not null identity(1,1) primary key clustered )
go
set nocount on
insert into #t ( output )
exec master.dbo.xp_cmdshell 'psinfo \\MYSERVER -d'

select
drive_info = substring(output,1,80)
from #t
where
left(output,11) = 'Volume Type' or
substring(output,6,7) = ': Fixed'

Results:

drive_info
--------------------------------------------------------------------------------
Volume Type Format Label Size Free Free
C: Fixed NTFS LOCAL_C 33.91 GB 26.29 GB 77.5%
D: Fixed NTFS LOCAL_D 102.11 GB 64.83 GB 63.5%
E: Fixed NTFS LOCAL_E 102.11 GB 74.73 GB 73.2%
F: Fixed NTFS LOCAL_F 102.11 GB 65.72 GB 64.4%
G: Fixed NTFS LOCAL_G 102.11 GB 65.37 GB 64.0%
H: Fixed NTFS LOCAL_H 34.04 GB 27.54 GB 80.9%
R: Fixed NTFS LOCAL_R 399.96 GB 374.34 GB 93.6%






CODO ERGO SUM
Go to Top of Page

Wanderer
Master Smack Fu Yak Hacker

1168 Posts

Posted - 2006-05-22 : 12:15:20
oooh - that is quite nice. So, if I use the dual-evils of cursors and dynamic SQL, I could use a local table to create a list of servers to check, then have the cursor go through that list of enables servers, and dynamically generate the xp_cmdshell command. Interesting... let me go and play....

*##* *##* *##* *##*

Chaos, Disorder and Panic ... my work is done here!
Go to Top of Page

Wanderer
Master Smack Fu Yak Hacker

1168 Posts

Posted - 2006-05-22 : 13:02:20
hmm - it does work - takes quite a long time to run, though. The following is a mock-up, using Michael's coide as base. I've just used a few table variables rather than going and creating tables.



set nocount on

declare @ServerToCheck table
(LineId Int identity (1,1),
ServerName varchar(250),
enabled bit)
Declare
@ServerCheck varchar(250),
@DynamicSQL varchar(500)

Create table #TemporaryDiskTable
(LineOutput varchar(2000) null, seq int not null identity(1,1) primary key clustered )

Insert into @ServerToCheck (ServerName, Enabled) values ('\\Rgalbraith',1)
Insert into @ServerToCheck (ServerName, Enabled) values ('\\Rgalbraith',1)

declare ServerSpaceDetailsCursor cursor for
select ServerName from @ServerToCheck where Enabled = 1

open ServerSpaceDetailsCursor
fetch next from ServerSpaceDetailsCursor into @ServerCheck

While @@fetch_status = 0
begin
set @DynamicSQL = 'master.dbo.xp_cmdshell ''psinfo ' + @ServerCheck + ' -d'''
-- set @DynamicSQL = @DynamicSQL
-- select @DynamicSQL
insert into #TemporaryDiskTable ( LineOutput )
exec (@DynamicSQL)

fetch next from ServerSpaceDetailsCursor into @ServerCheck
end

select
drive_info = substring(LineOutput,1,80)
from #TemporaryDiskTable
where
left(LineOutput,11) = 'Volume Type' or
substring(LineOutput,6,7) = ': Fixed'

drop table #TemporaryDiskTable


results

drive_info
--------------------------------------------------------------------------------
Volume Type Format Label Size Free Free
C: Fixed NTFS 28.31 GB 15.84 GB 55.9%
D: Fixed NTFS New 13.67 GB 10.39 GB 76.0%
E: Fixed NTFS New 13.80 GB 11.84 GB 85.8%
Volume Type Format Label Size Free Free
C: Fixed NTFS 28.31 GB 15.84 GB 55.9%
D: Fixed NTFS New 13.67 GB 10.39 GB 76.0%
E: Fixed NTFS New 13.80 GB 11.84 GB 85.8%


*##* *##* *##* *##*

Chaos, Disorder and Panic ... my work is done here!
Go to Top of Page

Wanderer
Master Smack Fu Yak Hacker

1168 Posts

Posted - 2006-05-22 : 13:03:32
I just did my laptop twice, rather than linking to any server's - but it proves the concept. Execution time was 50 seconds on my 2 Ghz laptop - wonder what it would be for a larger set of server's, across a network....

*##* *##* *##* *##*

Chaos, Disorder and Panic ... my work is done here!
Go to Top of Page

TRACEYSQL
Aged Yak Warrior

594 Posts

Posted - 2006-05-23 : 14:23:03
Hi would that work if my databases are held on a SAN and not the local server Drives..

i.e get the size left on the I drive

Thanks
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2006-05-23 : 14:29:00
quote:
Originally posted by TRACEYSQL

Hi would that work if my databases are held on a SAN and not the local server Drives..

i.e get the size left on the I drive

Thanks



The server actually thinks that the SAN drives are local. So yes.

Tara Kizer
aka tduggan
Go to Top of Page

TRACEYSQL
Aged Yak Warrior

594 Posts

Posted - 2006-05-23 : 14:56:17
Now i can go back.....look at which one...
Out of all the ones above which one to run...
Go to Top of Page

Wanderer
Master Smack Fu Yak Hacker

1168 Posts

Posted - 2006-05-24 : 06:38:45
@TracySQL: do you want to do it just for a server, or for many server's? Both version (sp_oa* and psinfo) will work for one server, but only the psinfo one (as above) will handle multiple server's.

Bear in mind that the psinfo solution is running:
(a) external application (sysinternals psinfo) - make sure you and your organization are happy to have that in your environment;
(b) using xp_cmdshell - this is an extremely useful, very powerful and possibly dangerous sql server xp that may or may not be locked down;
(c) permissions on target server's - if the userid running the sql server service is not a domain user, and cannot connect to the server's, I suspect you'll have issues.

With the sp_oa* version, you'll need to deploy and run on the specific server you want to check.

PLEASE NOTE - test this extensively and esnure you are happy it works, is safe, and does what you need. Like any code you get from the web, it has no guarantee's :-)

I have tested and used both on my laptop - so they should work - naturally after you change them for your local server's etc.

HTH

ADDED:

BTW - the last set of code I posted, with the sample results, was based on Michael's code.
*##* *##* *##* *##*

Chaos, Disorder and Panic ... my work is done here!
Go to Top of Page

TRACEYSQL
Aged Yak Warrior

594 Posts

Posted - 2006-05-24 : 08:07:26
Be one server i have 10 to monitor but only run statistics for each server on that server ...i know i do it 10 times and have 10 scripts...i change that one day.
So i built a table DBUSAGE this has my database growth
and i know which drives there on i.e MDF on M: and the LDF on I:
So the next step is to get the "physical space left on these drives"
which i can pass in the drive letter.....
and then i need to get the physical space left...so i can report that.
The servers are on C: but mdf and ldf are on SAN mapped \
Go to Top of Page

Wanderer
Master Smack Fu Yak Hacker

1168 Posts

Posted - 2006-05-24 : 12:31:54
quote:
Originally posted by schuhtl

I did not write the sp below and I can't remember where I found it but I think it will work for you...you might have to tweak it a bit to get exactly what you are looking for!

use master
go

CREATE PROCEDURE sp_diskspace
AS
/*
Displays the free space,free space percentage
plus total drive size for a server
*/
SET NOCOUNT ON

DECLARE @hr int
DECLARE @fso int
DECLARE @drive char(1)
DECLARE @odrive int
DECLARE @TotalSize varchar(20)
DECLARE @MB bigint ; SET @MB = 1048576

CREATE TABLE #drives (drive char(1) PRIMARY KEY,
FreeSpace int NULL,
TotalSize int NULL)

INSERT #drives(drive,FreeSpace)
EXEC master.dbo.xp_fixeddrives

EXEC @hr=sp_OACreate 'Scripting.FileSystemObject',@fso OUT
IF @hr <> 0 EXEC sp_OAGetErrorInfo @fso

DECLARE dcur CURSOR LOCAL FAST_FORWARD
FOR SELECT drive from #drives
ORDER by drive

OPEN dcur

FETCH NEXT FROM dcur INTO @drive

WHILE @@FETCH_STATUS=0
BEGIN

EXEC @hr = sp_OAMethod @fso,'GetDrive', @odrive OUT, @drive
IF @hr <> 0 EXEC sp_OAGetErrorInfo @fso

EXEC @hr = sp_OAGetProperty @odrive,'TotalSize', @TotalSize OUT
IF @hr <> 0 EXEC sp_OAGetErrorInfo @odrive

UPDATE #drives
SET TotalSize=@TotalSize/@MB
WHERE drive=@drive

FETCH NEXT FROM dcur INTO @drive

END

CLOSE dcur
DEALLOCATE dcur

EXEC @hr=sp_OADestroy @fso
IF @hr <> 0 EXEC sp_OAGetErrorInfo @fso

SELECT drive,
FreeSpace as 'Free(MB)',
TotalSize as 'Total(MB)',
CAST((FreeSpace/(TotalSize*1.0))*100.0 as int) as 'Free(%)'
FROM #drives
ORDER BY drive

DROP TABLE #drives

RETURN
go






@TracySQL: Sounds like you should consider using the code posted by schuhtl. iirc, I made almost no changes, or very little change, to it. Needless to say, you'll need to change the piece around the temp table, to push the data into your DBusage database.

If you have linked server's from those server's to a central server, it might be worth your while to look into have each of the 10 server's push that data into a central server, which you could use to event alerting etc.

HTH

*##* *##* *##* *##*

Chaos, Disorder and Panic ... my work is done here!
Go to Top of Page

TRACEYSQL
Aged Yak Warrior

594 Posts

Posted - 2006-05-25 : 08:39:54
Thanks i will give that a try...
Go to Top of Page
   

- Advertisement -