BookmarkSubscribeRSS Feed
Acf2
Obsidian | Level 7

I need to provide some SAS admin tools to non-SAS admins for a very basic Windows2019 server with about 25 occasional EG users. Due to shared disk, Environment Manager is not reliable and does not integrate with the IT team. cleanwork.exe is scheduled but sometimes a lot of users need a lot of space at the same time.

 

This powershell script can be supported by IT operations and the output is sufficient for basic capacity planning but it needs some tweaking. Hopefully, I am not missing something obvious:

 

# Write owner and aggregate SASwork usage to csv
# D:\sas\Batch\scripts\SASWorkDirUse2csv.ps1
# Nearly there but array($owner) values are weird
<#
tree /A D:\SASWork
Folder PATH listing for volume Data
Volume serial number is EE9D-7C3D
D:\SASWORK
+---SAS_util0001000008C0_WIN2019SRV
+---SAS_util000100007504_WIN2019SRV
+---SAS_util000100008B28_WIN2019SRV
+---SAS_util0001000095B4_WIN2019SRV
+---_TD2240_WIN2019SRV_
|   +---EC_4qh9k9re
|   \---Prc2
+---_TD29956_WIN2019SRV_
|   +---EC_jh9gtz1t
|   \---Prc2
+---_TD35624_WIN2019SRV_
|   +---EC_1gt8bc1d
|   \---Prc2
+---_TD38324_WIN2019SRV_
|   +---EC_nb5qr46m
|   \---Prc2
\---_TD4000_WIN2019SRV_
#>

$folder = 'D:\SASWork'

$DirUseArray = @()
 
# Get a list of first level sub-folders
$firstLevel = Get-ChildItem $folder -directory
 
$firstLevel | foreach {
   Echo "Reading $_"
   # Read the size of this folder and all its sub folders.
   $size = (Get-ChildItem $folder\$_\* -recurse) | measure-object -property length -sum | Select-Object -expand sum
   # Convert from Bytes to GB and round to 2 decimal places
   $size =  [math]::Round($(0 + $size /1GB),2)
   $owner = (Get-ChildItem $folder\$_ -directory) | select @{Name="Owner";Expression={ (Get-ACL $_.Fullname).Owner }}
   Echo $owner $size
 
   # Add to an array
   $DirUseArray += New-Object PsObject -property @{
      'Owner' = $owner
      'Folder' = $_
      'Size (GB)' = $size
   }
}
# $DirUseArray | Export-Csv -path D:\sas\Batch\datafiles\SASWorkDirUse.csv -NoTypeInformation
$DirUseArray

#<
Size (GB) Folder                            Owner                                            
--------- ------                            -----                                            
        0 SAS_util0001000008C0_WIN2019SRV                                                  
        0 SAS_util000100007504_WIN2019SRV                                                  
        0 SAS_util000100008B28_WIN2019SRV                                                  
        0 SAS_util0001000095B4_WIN2019SRV                                                  
     4.59 _TD2240_WIN2019SRV_             {@{Owner=SASUSER1}, @{Owner=SASUSER1}}    
     1.14 _TD29956_WIN2019SRV_            {@{Owner=SASUSER1}, @{Owner=SASUSER1}}    
    19.76 _TD35624_WIN2019SRV_            {@{Owner=SASUSER2}, @{Owner=SASUSER2}}
    19.76 _TD38324_WIN2019SRV_            {@{Owner=SASUSER2}, @{Owner=SASUSER2}}
        0 _TD4000_WIN2019SRV_                                                              
#>
 
 

I am testing using an account that is a member of the Administrators group but I have noticed that get-acl can be erratic if not run as Administrator. Still testing that aspect. The original script came from DirUse Directory size - PowerShell - SS64.com

An excellent resource for powershell amateurs

 

2 REPLIES 2
Acf2
Obsidian | Level 7

Getting the owners sometimes needs Admin rights but not always. Here are 4 different outputs :

 


# Compact view for pasting into email
Get-ChildItem "D:\SASWork" -File -recurse | select Directory, Name, length, <# path, filename,#> lastwritetime, @{Name="Owner";
Expression={ (Get-ACL $_.Fullname).Owner }} | Sort-Object -Descending length | Out-GridView

# Write to standard output for selecting details
Get-ChildItem "D:\SASWork" -File -recurse | select Directory, Name, length, <# path, filename,#> lastwritetime, @{Name="Owner";
Expression={ (Get-ACL $_.Fullname).Owner }} | Sort-Object -Descending length | Format-Table


# Write to csv for DSD parsing with SAS
Get-ChildItem "D:\SASWork" -File -recurse | select Directory, Name, length, <# path, filename,#> lastwritetime, @{Name="Owner";
Expression={ (Get-ACL $_.Fullname).Owner }} | Export-CSV -Path D:\sas\Batch\datafiles\D_SASWork_Files_$(get-date -f "yyyyMMdd").csv -NoTypeInformation

# Pre-req : Install-Module ImportExcel -AllowClobber -Force

# Write to xlsx
Get-ChildItem "D:\SASWork" -File -recurse | select Directory, Name, length, <# path, filename,#> lastwritetime, @{Name="Owner";
Expression={ (Get-ACL $_.Fullname).Owner }} | Export-Excel -Path D:\SAS_Users\AFarrer\xlsx\D_SASWork_Files_$(get-date -f "yyyyMMdd").xlsx

AhmedAl_Attar
Ammonite | Level 13

Hi @Acf2 

I've written this script for windows to display all existing SAS WORK Directories (_TD*), and SAS Utility directories (SAS_util*), then find their associated process id (PID), if active, with every found directory. This was inspired by the WORKtop freeware utility developed back in the day by the folks from Boemska 

 

:: -----------------------------------------------------------------------
::  Filename: getworkdirpid.bat
::  Description: Find all existing SAS WORK Directories (_TD*), and
::  SAS Utility directories (SAS_util*), then find their associated
::  process id (PID), if active, with every found directory
:: -----------------------------------------------------------------------
:: Syntax:
::
:: To generate output on the screen, just execute the script
::     > getworkdirpid.bat /v f: c: 
::
:: To store generated output into a text file, here is an example usage
::     > getworkdirpid.bat /v f: c: > c:\tmp\getworkdirpid_output.txt
::
:: -----------------------------------------------------------------------
@ECHO OFF

:: Ensure that I don’t clobber any existing variables after my script exits
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION 

:: Store the name of the script (without the file extension) 
SET scrpt=%~n0

:: Store the path of the folder for the script file for later user
SET parent=%~dp0

:: Command line parameter check 
ECHO.%* | FIND "?" >NUL 
IF NOT ERRORLEVEL 1 GOTO SYNTAX
IF "%1" == "/v" SET allArgs=%2
IF NOT defined allArgs GOTO SYNTAX

:: Initialize variable 
SET n=2
SET dirCount=0

:: Skip to the next argument
SHIFT

:LOOP
   :: Change directory, and try to find the SAS temporary directories
   %1
   ECHO.
   ECHO Searching _TD* directories on %1 ...
   FOR /F %%I IN ('DIR _TD* /s /ad /b') DO (
      SET /a dirCount+=1
      CALL :unifyLength %%~I, col
      SET argVec[!dirCount!].fullPath=!col!
	  
      CALL :getDirPid %%~nI, pid, w
      SET argVec[!dirCount!].pid=!pid!

	  CALL :getPidInfo !pid!, pidInfo
	  :: echo !pidInfo!
      SET argVec[!dirCount!].pidInfo=!pidInfo!
   )
   
   ECHO.
   ECHO Searching SAS_util* directories on %1 ...
   FOR /F %%I IN ('DIR SAS_util* /s /ad /b') DO (
      SET /a dirCount+=1
      CALL :unifyLength %%~I, col
      SET argVec[!dirCount!].fullPath=!col!
	  
      CALL :getDirPid %%~nI, pid, u
      SET argVec[!dirCount!].pid=!pid!
	  
      CALL :getPidInfo !pid!, pidInfo
      :: echo !pidInfo!
      SET argVec[!dirCount!].pidInfo=!pidInfo!
   )
   SET /a n+=1
   SHIFT
   SET param=%1
   if defined param (GOTO :LOOP) else (GOTO :REPORT)

:SYNTAX 
   ECHO.
   ECHO Display list of SAS Temporary directories, and their associated PID, if any 
   ECHO Usage: getworkdirpid [/v volume(s)] 
   ECHO Where: /v volume specifies the volume to search for SAS Temporary directories.
   ECHO Note: When specifying more than one volume, separate them with spaces.
   ENDLOCAL
   ECHO ON
   @EXIT /B 0

:unifyLength
   SETLOCAL ENABLEEXTENSIONS
   SET "spaces=                                                                             "
   SET "newCol=%1%spaces%"
   SET newCol=%newCol:~0,77%
   :: ECHO %newCol%
   ENDLOCAL&SET %2=%newCol%&GOTO :eof

:getDirPid
   SETLOCAL ENABLEEXTENSIONS
   SET lclPid=%~nx1
   IF "%3" == "w" (
      SET lclPid=%lclPid:~3,4%
   ) else (
      SET lclPid=%lclPid:~12,8%   
      SET /A lclPid=0X%lclPid%
   )
   :: echo %lclPid%
   ENDLOCAL&SET %2=%lclPid%&GOTO :eof

:getPidInfo
   SETLOCAL ENABLEEXTENSIONS
   tasklist /v /fi "PID eq %1" /nh /fo "CSV" > c:\temp\_tmp.txt
   ENDLOCAL&SET /p %2=<c:\temp\_tmp.txt&GOTO :eof
   
:REPORT
   ECHO.
   ECHO Number of found temporary directories: %dirCount%
   ECHO ------------------------------------------------------------------------------+-------+------------------------------------------------------
   ECHO Directory                                                                     :  PID  : Task / Process
   ECHO ------------------------------------------------------------------------------+-------+------------------------------------------------------
   for /L %%i in (1,1,%dirCount%) do (
      ECHO !argVec[%%i].fullPath! :  !argVec[%%i].pid! : !argVec[%%i].pidInfo!
   )
   ENDLOCAL
   ECHO ON
   @EXIT /B 0

suga badge.PNGThe SAS Users Group for Administrators (SUGA) is open to all SAS administrators and architects who install, update, manage or maintain a SAS deployment. 

Join SUGA 

Get Started with SAS Information Catalog in SAS Viya

SAS technical trainer Erin Winters shows you how to explore assets, create new data discovery agents, schedule data discovery agents, and much more.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 2 replies
  • 1104 views
  • 3 likes
  • 2 in conversation