Now that PowerShell is available on various Linux distributions (such as CentOS, Red Hat, and Ubuntu), it is natural for Windows sysadmins to begin tinkering on Linux machines. One of the first thoughts I had after hearing the news that PowerShell was cross-platform was "I wonder what I can script with PowerShell on Linux?"
Dan Franciscus

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:

Get-Module ListAvailable

Get-Module ListAvailable

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.

Get-Disk example

Get-Disk example

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:

systemctl command

systemctl command

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.

hostname command

hostname command


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.

Get ServiceStatus on foo

Get ServiceStatus on foo

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!

Get ServiceStatus on nfs service

Get ServiceStatus on nfs service

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!

avatar

11 Comments

Leave a reply

Please enclose code in pre tags: <pre></pre>

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

*

© 4sysops 2006 - 2024

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending
WindowsUpdatePreventer

Log in with your credentials

or    

Forgot your details?

Create Account