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.
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 mastergoCREATE PROCEDURE sp_diskspace AS/* Displays the free space,free space percentage plus total drive size for a server*/SET NOCOUNT ONDECLARE @hr intDECLARE @fso intDECLARE @drive char(1)DECLARE @odrive intDECLARE @TotalSize varchar(20)DECLARE @MB bigint ; SET @MB = 1048576CREATE TABLE #drives (drive char(1) PRIMARY KEY, FreeSpace int NULL, TotalSize int NULL)INSERT #drives(drive,FreeSpace) EXEC master.dbo.xp_fixeddrivesEXEC @hr=sp_OACreate 'Scripting.FileSystemObject',@fso OUTIF @hr <> 0 EXEC sp_OAGetErrorInfo @fsoDECLARE dcur CURSOR LOCAL FAST_FORWARDFOR SELECT drive from #drivesORDER by driveOPEN dcurFETCH NEXT FROM dcur INTO @driveWHILE @@FETCH_STATUS=0BEGIN 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 @driveENDCLOSE dcurDEALLOCATE dcurEXEC @hr=sp_OADestroy @fsoIF @hr <> 0 EXEC sp_OAGetErrorInfo @fsoSELECT drive, FreeSpace as 'Free(MB)', TotalSize as 'Total(MB)', CAST((FreeSpace/(TotalSize*1.0))*100.0 as int) as 'Free(%)'FROM #drivesORDER BY driveDROP TABLE #drivesRETURNgo |
 |
|
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! |
 |
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
|
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! |
 |
|
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 #tgocreate table #t (output varchar(2000) null,seq int not null identity(1,1) primary key clustered )goset nocount oninsert into #t ( output )exec master.dbo.xp_cmdshell 'psinfo \\MYSERVER -d'select drive_info = substring(output,1,80) from #twhere 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 |
 |
|
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! |
 |
|
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 ondeclare @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 = 1open ServerSpaceDetailsCursorfetch next from ServerSpaceDetailsCursor into @ServerCheckWhile @@fetch_status = 0begin 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 @ServerCheckendselect drive_info = substring(LineOutput,1,80) from #TemporaryDiskTablewhere left(LineOutput,11) = 'Volume Type' or substring(LineOutput,6,7) = ': Fixed'drop table #TemporaryDiskTable resultsdrive_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! |
 |
|
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! |
 |
|
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 |
 |
|
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 Kizeraka tduggan |
 |
|
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... |
 |
|
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.HTHADDED: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! |
 |
|
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 growthand 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 \ |
 |
|
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 mastergoCREATE PROCEDURE sp_diskspace AS/* Displays the free space,free space percentage plus total drive size for a server*/SET NOCOUNT ONDECLARE @hr intDECLARE @fso intDECLARE @drive char(1)DECLARE @odrive intDECLARE @TotalSize varchar(20)DECLARE @MB bigint ; SET @MB = 1048576CREATE TABLE #drives (drive char(1) PRIMARY KEY, FreeSpace int NULL, TotalSize int NULL)INSERT #drives(drive,FreeSpace) EXEC master.dbo.xp_fixeddrivesEXEC @hr=sp_OACreate 'Scripting.FileSystemObject',@fso OUTIF @hr <> 0 EXEC sp_OAGetErrorInfo @fsoDECLARE dcur CURSOR LOCAL FAST_FORWARDFOR SELECT drive from #drivesORDER by driveOPEN dcurFETCH NEXT FROM dcur INTO @driveWHILE @@FETCH_STATUS=0BEGIN 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 @driveENDCLOSE dcurDEALLOCATE dcurEXEC @hr=sp_OADestroy @fsoIF @hr <> 0 EXEC sp_OAGetErrorInfo @fsoSELECT drive, FreeSpace as 'Free(MB)', TotalSize as 'Total(MB)', CAST((FreeSpace/(TotalSize*1.0))*100.0 as int) as 'Free(%)'FROM #drivesORDER BY driveDROP TABLE #drivesRETURNgo
@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! |
 |
|
TRACEYSQL
Aged Yak Warrior
594 Posts |
Posted - 2006-05-25 : 08:39:54
|
Thanks i will give that a try... |
 |
|
|
|
|
|
|