- SolarWinds Server Performance and Configuration Bundle - Tue, Jun 18 2019
- SolarWinds Patch Manager: Updating Windows and third-party software - Tue, Apr 30 2019
- Monitor file changes in Windows with PowerShell and pswatch - Fri, Feb 1 2019
The answer to this question is: quite a lot! In this article I will show you two very simple PowerShell scripts you can use on CentOS.
PowerShell Core does not have the fancy cmdlets Windows users are familiar with, such as manipulating the firewall, services, or storage since these are native only to Windows. In fact, at the time of this article there are only 352 commands in PowerShell Core as Get-Command shows.
PS /root> Get-Command | Measure-Object | Select-Object -Property Count Count ----- 352
So how can we use PowerShell to create scripts on Linux like we are used to on Windows? We have to use native Linux commands like crontab, df, and systemctl that perform tasks for which PowerShell does not have cmdlets. Since PowerShell is just another shell on Linux, it can run these Linux commands within PowerShell.
Adding a PowerShell module in Linux
While you can create PowerShell functions in a .ps1 file on Linux and run them within the console, I prefer to create modules. Currently, PowerShell Core on CentOS has three directories in which to store modules:
PS /root> ($env:PSModulePath).split(':') /root/.local/share/powershell/Modules /usr/local/share/powershell/Modules /opt/microsoft/powershell/6.0.0-beta.4/Modules
To make a module available to all users on my computer, I will store it in the /opt/microsoft/powershell/6.0.0-beta.4/Modules directory. To create a module for Get-DiskSpace, I will store the function in the Get-DiskSpace.psm1 file under the Get-DiskSpace directory, just as I would on Windows. This is the minimum needed to create a PowerShell module.
Now I just need to add the actual code for the Get-DiskSpace module. To do this from the Linux command line, we use the vi editor to run this command:
vi /opt/microsoft/powershell/6.0.0-beta.4/Modules/Get-DiskSpace/Get-DiskSpace.psm1
Tip: For those new to vi, the "i" key lets you insert text into the editor, the escape key brings you out of insert mode, and finally, typing ":wq" exits the editor and saves your file.
Now if we run Get-Module -ListAvailable, we see this lists the Get-DiskSpace module:
Going forward, my Get-DiskSpace module will load after launching PowerShell each time on my computer. Note that if you want to create more professional modules in production scenarios, you should use New-ModuleManifest just as you would in Windows.
Monitoring disk space
Now that we know how to create a simple module, I will show two examples of scripts I have written in Linux. In this first example, I wanted to write a PowerShell script that will monitor the boot partition on a CentOS server for usage, and if it is over a certain amount, send an email alert.
This is a perfect example of how we need to combine native Linux commands and PowerShell to accomplish a task. To see the disk usage on your local disks in Linux, you can use df -h. The -h argument means outputting the results into a human readable format.
Obviously, /boot is the boot partition on Linux, so I will try to parse this with PowerShell to grab the "Use%" value, in this case 25%.
PS /root> df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/cl-root 44G 2.2G 42G 5% / devtmpfs 2.9G 0 2.9G 0% /dev tmpfs 2.9G 0 2.9G 0% /dev/shm tmpfs 2.9G 8.5M 2.9G 1% /run tmpfs 2.9G 0 2.9G 0% /sys/fs/cgroup /dev/sda1 1014M 148M 867M 25% /boot tmpfs 581M 0 581M 0% /run/user/0
To grab the 25% value, I will use df -h, pipe it to Select-String, split that line at the percentage character, and split it again at the last empty space.
(df -h | Select-String -Pattern '/boot' | Out-String).Split('%')[0].Split(' ')[-1]
I have parsed the output of df to get the percentage used for /boot. Now I will compare that to a threshold value in this function and use Send-MailMessage (yes, this cmdlet is available now in PowerShell Core). This will alert me if that value is over the threshold.
function Get-DiskSpace { param ( [string]$MaxSize = '95', [string[]]$Disks = '/boot' ) $HostName = hostname ##Check to ensure OS is Linux if (!$IsLinux) { Write-Output 'Exiting; not a Linux computer.' } #foreach disk specified get usage and compare to max value foreach ($Disk in $Disks) { $Size = (df -h | Select-String -Pattern $Disk | Out-String).Split('%')[0].Split(' ')[-1] if ($Size -gt $MaxSize) { Write-Warning -Message "Sending mail $Disk is $Size %" Send-MailMessage -Body "$Disk usage is $Size on $HostName" -From '[email protected]' -SmtpServer smtp.mail.com -Subject "$HostName disk is over limit" -To '[email protected]' } } }
Here, I run Get-DiskSpace while specifying the maximum size threshold of 10 GB of the boot partition. As you can see, the output states it is sending a mail alert since it is over that threshold.
Checking the status of a service
Unfortunately, Get-Service is not a cmdlet in PowerShell core, and neither are the other service-oriented cmdlets. Thus, we cannot use it to start, stop, or restart services on a Linux computer. To do this on current Red Hat and CentOS distributions, for instance, we must use the systemctl command.
For example, if we would like to check whether the sshd service is running, we can run systemctl with is-active:
As you can see, the status is "active," which means the service is currently running. So to combine PowerShell Core and native Linux again, we can write another simple function. Get-ServiceStatus will check the status of a specified service, and if it is not active, send an email with Send-MailMessage.
Note that it is also possible to show whether the service is enabled or has failed. We can do this by using systemctl --is-enabled and systemctl --is-failed. For the sake of simplicity, I have left these out of the script.
In this function we will also use the hostname command. The hostname command simply prints the hostname of the local computer; we will use it in the $HostName variable shown in the email alert.
function Get-ServiceStatus { param ( [string[]]$ServiceName ) $HostName = hostname ##Check to ensure OS is Linux if (!$IsLinux) { Write-Warning -Message 'Exiting; not a Linux computer.' } foreach ($Service in $ServiceName) { if ((systemctl is-active $Service) -eq 'active') { Continue } if ((systemctl is-active $Service) -eq 'unknown') { Write-Warning -Message "$Service does not exist on $HostName." } else { Write-Warning -Message "$Service is not running on $HostName. Send email." Send-MailMessage -Body "Do something!" -From '[email protected]' -SmtpServer smtp.mail.com -Subject "$Service on $HostName is not running" -To '[email protected]' } } }
Below, I ran Get-ServiceStatus against the service "foo." The "foo" service obviously does not exist on the system ja warning message.
Next, I will try the Get-ServiceStatus function on the "nfs-service" service. Since it exists but is not running, the function sends an email.
Subscribe to 4sysops newsletter!
Note that in the Get-ServiceStatus function, we combine the use of an "if" statement with systemctl to verify the service is "active." If it is active, the function will do nothing, so it continues to the next value in the $ServiceName array. As you can see, PowerShell and Linux commands integrate gracefully.
if ((systemctl is-active $Service) -eq 'active') { Continue }
I hope these examples give the average Windows system administrator a little jump-start to dive into using PowerShell with Linux. We now live in a cross-platform, hybrid cloud world where having knowledge of one platform just isn't going to cut it anymore. If you use PowerShell on your Windows systems, there is no excuse not to learn Linux as well!
IT Administration News
- Windows 10 KB5036979 pushes Microsoft account (direct download .msu)
- Windows 11 KB5036980 turns on Start menu ads (direct download .msu)
- Microsoft wants to hide the ‘Sign out’ button in Windows 11 behind a Microsoft 365 ad – Neowin
- Llama 3 is now avaialble on 4sysops
- Why is Windows 11 so annoying? – The Verge