Public/Invoke-Sudo.ps1

#!/usr/bin/env pwsh
Set-StrictMode -Version Latest

if ($IsLinux) {
    function Invoke-Sudo {
        <#
        .SYNOPSIS
            Runs a script block as root through sudo.

        .DESCRIPTION
            Passes the script block to the current pwsh binary under sudo with -NoProfile
            and returns its output. sudo may prompt for a password.

            PowerShell sends the script block and its arguments to the root process as
            base64 encoded CliXml and deserializes the output, so argument and output
            types are preserved as data, without methods. Variables from the calling
            session are not available; pass them through -ArgumentList instead.

            Arguments are visible in the process list while the command runs. Do not
            pass secrets through -ArgumentList.

        .PARAMETER ScriptBlock
            The script block to run as root. Declare a param() block to receive the
            values from -ArgumentList.

        .PARAMETER ArgumentList
            The arguments to pass to the script block, bound by position. Accepts values
            from the pipeline; the script block runs once for each piped value.

        .INPUTS
            System.Object. You can pipe values to this function. Each value is passed to the
            script block as its only argument.

        .OUTPUTS
            System.Object. The deserialized output of the script block. The type of each
            item depends on the script block, for example System.String for the text
            output of a Linux command.

        .EXAMPLE
            Invoke-Sudo { Get-ChildItem -Path /root }

            Lists the contents of /root as root.

        .EXAMPLE
            Invoke-Sudo { param($Path) Get-ChildItem -LiteralPath $Path } -ArgumentList '/root'

            Lists the contents of the path passed in -ArgumentList as root.

        .EXAMPLE
            '/root/.ssh', '/etc/ssh' | Invoke-Sudo { param($Path) Get-ChildItem -LiteralPath $Path -Force }

            Lists the contents of each piped path as root. sudo and pwsh start once per path.
        #>

        [CmdletBinding()]
        [OutputType([object])]
        param(
            [Parameter(Mandatory, HelpMessage = 'Enter the script block to run as root.')]
            [scriptblock]$ScriptBlock,

            [Parameter(ValueFromPipeline,
                HelpMessage = 'Enter the arguments to pass to the script block. Accepts values from the pipeline.')]
            [object[]]$ArgumentList
        )
        begin {
            $pwsh = Join-Path -Path $PSHOME -ChildPath 'pwsh'
        }
        process {
            if ($PSBoundParameters.ContainsKey('ArgumentList')) {
                (sudo $pwsh -NoProfile -Command $ScriptBlock -args $ArgumentList)
            }
            else {
                (sudo $pwsh -NoProfile -Command $ScriptBlock)
            }
        }
    }
}