GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Add Get-Service, Start-Service, Stop-Service and Restart-Service cmdlets on Unix by soroshsabz · Pull Request #28385 · PowerShell/PowerShell

Conversation

@soroshsabz

@soroshsabz soroshsabz commented Nov 10, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

PR Summary

This PR implements Get-Service, Start-Service, Stop-Service, and Restart-Service on Unix
(Linux and macOS), based on issue

  • Restart-Service should call systemctl restart on Linux OSes with SystemD present. #18863

These cmdlets previously did not exist on Unix at all, which made cross-platform service
management impossible.

The implementation follows the cmdlets WG recommendation recorded in
#18863 (comment):

  • a fallback system to search for common commands used by various distros (including macOS) to restart a service on those platforms and if no common command is found then fail the entire operation
  • looking if sudo exists and using that to avoid the inevitable permission problem as sudo cannot elevate cmdlets
  • check the exit code and if non-zero, emit STDERR as an ErrorRecord
  • We would expect Get-Service, Stop-Service and Start-Service to also use the same/similar code

Rather than duplicating the cmdlets, master's Service.cs is now also compiled on Unix. A
using ServiceController = Microsoft.PowerShell.Commands.UnixServiceController alias maps the
unqualified ServiceController name to a new Unix facade (UnixServiceController.cs) so the
shared cmdlet implementation works unchanged. Only a few places are platform-specific: the five
Windows-SCM-only cmdlets (Set-Service, New-Service, Remove-Service, Suspend-Service,
Resume-Service) and the SCM property/native sections stay guarded with #if !UNIX,
Get-Service's ProcessRecord has a small Unix branch, and DoStartService/DoStopService
surface sudo-unavailable failures as SudoRequired errors.

PR Context

Fixes #18863

Service manager fallback chain

The cmdlets resolve the service manager through PATH in this order and fail the operation with a
terminating error when none is found:

Priority Manager Covered init systems
1 systemctl systemd
2 launchctl launchd (macOS)
3 service sysvinit and compatible
4 rc-service OpenRC

Elevation

Mutating operations (Start-Service, Stop-Service, Restart-Service) are wrapped with
sudo -n when the process is not running as root, so they never hang on a password prompt. If
sudo would require a password, the cmdlet writes a non-terminating error with guidance to run
pwsh as root or configure passwordless sudo. Get-Service works unprivileged.

Error semantics

Non-zero exit codes surface the command's stderr as a non-terminating ErrorRecord per service
(exception type ServiceCommandException, mirroring Windows), with error IDs matching the Windows
cmdlets (CouldNotStartService, CouldNotStopService), plus SudoRequired when elevation is
unavailable. A missing service manager is reported as a terminating NoServiceManagerFound error,
and service-manager enumeration failures terminate the cmdlet.

Output type

Get-Service returns the new Microsoft.PowerShell.Commands.UnixServiceController type with
Name, DisplayName, Status, StartType, Description, SubState, and UnitFileState.
Status and StartType reuse the System.ServiceProcess.ServiceControllerStatus /
ServiceStartMode enums (the managed assembly ships cross-platform; only the Windows
implementation is RID-specific), so Where-Object Status -eq Running and other pipelines behave
identically on both platforms. Objects carry a DefaultDisplayPropertySet so the default table
view matches Windows.

Parameter behavior:

  • Wildcards, -DisplayName, -Include/-Exclude, -PassThru, -WhatIf/-Confirm and pipeline
    input (Get-Service foo | Stop-Service) work as on Windows.
  • On systemd, unit names are accepted with or without the .service suffix; other managers use
    the provided name verbatim.
  • -DependentServices / -RequiredServices are implemented via systemctl list-dependencies;
    other service managers return no results.
  • Stop-Service -NoWait skips the wait for the stopped state; the stop request itself is unchanged.
  • -Force is accepted for script compatibility; service managers handle dependency ordering
    themselves.
  • Set-Service, New-Service, Remove-Service, Suspend-Service and Resume-Service remain
    Windows-only, per the WG recommendation that capabilities beyond these four cmdlets belong in a
    separate module.

Supporting changes

  • The four cmdlets are exported by the Unix Microsoft.PowerShell.Management module manifest.
  • The gsv, sasv and spsv aliases are now defined on Unix (they do not conflict with native
    commands there).
  • New neutral resource strings in ServiceResources.resx.

Notes

Tests

New test/powershell/Modules/Microsoft.PowerShell.Management/Service.Tests.ps1 covers systemd
enumeration, name/display-name/wildcard matching, dependencies, the exact service-manager
invocation arguments for systemd, launchctl, sysvinit and OpenRC (including sudo wrapping), the
sudo error paths, and the no-service-manager and enumeration-failure errors. The manager
behaviors are exercised through command shims, so the suite does not require a real systemd
installation.

All 22 tests pass against a local Linux build of this PR (run in WSL Ubuntu as root; the 2
sudo-specific tests skip as root and run on non-root agents):

Total: 22  Passed: 20  Failed: 0  Skipped: 2

The Windows build is unchanged by this PR (#if !UNIX sections compile as before, verified by a
Windows cross-compile of the affected project).

Breaking Changes & Documentation

This is not a breaking change: the Windows behavior of all service cmdlets is unchanged. The
Resolve-Path-style documentation for the four cross-platform cmdlets has been updated to
describe the Unix support:

  • Documentation issue: Document Unix platform support for Get/Start/Stop/Restart-Service MicrosoftDocs/PowerShell-Docs#13385
  • Documentation PR: Document Unix platform support for Get/Start/Stop/Restart-Service (PowerShell 7.7) MicrosoftDocs/PowerShell-Docs#13383

PR Checklist

  • PR has a meaningful title
    • Use the present tense and imperative mood when describing your changes
  • Summarized changes
  • Make sure all .h, .cpp, .cs, .ps1 and .psm1 files have the correct copyright header
  • This PR is ready to merge. If this PR is a work in progress, please open this as a Draft Pull Request and mark it as Ready to Review when it is ready to merge.
  • Breaking changes
    • None
    • OR
    • Experimental feature(s) needed
      • Experimental feature name(s):
  • User-facing changes
    • Not Applicable
    • OR
    • Documentation needed
      • Issue filed: Document Unix platform support for Get/Start/Stop/Restart-Service MicrosoftDocs/PowerShell-Docs#13385
  • Testing - New and feature
    • N/A or can only be tested interactively
    • OR
    • Make sure you've added a new test if existing tests do not effectively test the code changed

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@soroshsabz
Add Get/Start/Stop/Restart-Service cmdlets on Unix
f4d99a6
Implements PowerShell#18863 as reviewed by the cmdlets WG:

- New Unix-only Service.cs implementation (#if UNIX) that discovers the
  service manager in this order: systemctl (systemd), launchctl (macOS),
  service (sysvinit), rc-service (OpenRC), and fails the entire operation
  with a terminating error when none is found.
- Start/Stop/Restart wrap the service manager with 'sudo -n' when not
  running as root (sudo cannot elevate cmdlets), and report a clear
  error when a password would be required.
- Non-zero exit codes surface the command stderr as a non-terminating
  ErrorRecord per service, with error IDs mirroring the Windows
  implementation.
- Get-Service returns UnixServiceController objects with Name,
  DisplayName, Status, StartType, Description, SubState and
  UnitFileState; Status/StartType reuse the System.ServiceProcess
  enums for pipeline compatibility with Windows. Wildcards,
  -DisplayName, -Include/-Exclude and -PassThru behave like Windows.
  -DependentServices/-RequiredServices are supported on systemd.
- Stop-Service -NoWait maps to 'systemctl --no-block'; -Force is
  accepted for script compatibility (service managers order services
  themselves).
- Exports the four cmdlets in the Unix Microsoft.PowerShell.Management
  module manifest and enables the gsv/sasv/spsv aliases on Unix.
- Adds Service.Tests.ps1 exercising the real command resolution and
  invocation paths against PATH shims for each service manager.
@soroshsabz
soroshsabz requested a review from a team as a code owner November 10, 2026 11:09
Copilot AI balanced review requested due to automatic review settings November 10, 2026 11:09
@azure-pipelines

azure-pipelines Bot commented Nov 10, 2026

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@soroshsabz soroshsabz mentioned this pull request Nov 10, 2026
Document Unix platform support for Get/Start/Stop/Restart-Service (PowerShell 7.7) MicrosoftDocs/PowerShell-Docs#13383
Open
4 tasks done
@soroshsabz

soroshsabz commented Nov 10, 2026

Copy link
Copy Markdown
Author

Companion documentation update: MicrosoftDocs/PowerShell-Docs#13383 (documents the Unix behavior, the new UnixServiceController output type, and parameter differences in the 7.7 version folder).

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Copilot started reviewing on behalf of soroshsabz November 10, 2026 11:26
View session
Copilot AI reviewed Nov 10, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

5 open issues
  • High severity For both SysV init (service) and OpenRC (rc-service), the argument order is typically… · New
  • Medium severity Since this exception type is intended to mirror the Windows shape and will be embedded in… · New
  • Medium severity When elevate is true, the process is not elevated, and sudo is not present (`SudoPath is… · New
  • Medium severity AddDefaultDisplayProperties unconditionally adds a PSStandardMember member set. If this helper… · New
  • Medium severity The tests cover enumeration/parsing for launchctl/service/rc-service fallbacks, but they don’t… · New
What changed in this PR

Adds cross-platform service management support by implementing Get-Service, Start-Service, Stop-Service, and Restart-Service on Unix platforms, aligning behavior and error semantics with Windows where practical.

Changes:

  • Introduces a Unix implementation of service cmdlets with service-manager discovery (systemctl/launchctl/service/rc-service) and sudo wrapping for mutating operations.
  • Exports the new cmdlets and adds Unix-only aliases (gsv, sasv, spsv).
  • Adds Pester coverage for Unix behavior via PATH shims and new resource strings for consistent error messaging.
File Description
test/​powershell/​Modules/​Microsoft.PowerShell.Management/​Service.Tests.ps1 Adds Pester tests for Unix service cmdlets using service-manager and sudo shims.
src/​System.Management.Automation/​engine/​InitialSessionState.cs Adds Unix-only aliases for the new service cmdlets.
src/​Modules/​Unix/​Microsoft.PowerShell.Management/​Microsoft.PowerShell.Management.psd1 Exports the service cmdlets from the Unix Management module.
src/​Microsoft.PowerShell.Commands.Management/​resources/​ServiceResources.resx Adds new resource strings for Unix service-manager and sudo/error scenarios.
src/​Microsoft.PowerShell.Commands.Management/​commands/​management/​ServiceUnix.cs Implements Unix service cmdlets, parsing, invocation, sudo wrapping, and output shaping.

Review effort: Lite

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/ServiceUnix.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/ServiceUnix.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/ServiceUnix.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/ServiceUnix.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread test/powershell/Modules/Microsoft.PowerShell.Management/Service.Tests.ps1 Resolved

Uh oh!

There was an error while loading. Please reload this page.

@soroshsabz
Address Copilot review comments
d52bdec
@soroshsabz
soroshsabz force-pushed the pr/unix-service-cmdlets branch from 60c00e1 to d52bdec Compare November 10, 2026 15:24
@soroshsabz
soroshsabz requested a balanced review from Copilot November 10, 2026 15:34
Copilot started reviewing on behalf of soroshsabz November 10, 2026 15:36
View session
Copilot AI reviewed Nov 10, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

OpenRC enumeration invokes rc-service --all instead of rc-status --all, causing enumeration to fail before named service operations can run.

3 open issues
  • High severity Use rc-status to enumerate OpenRC services · New
  • Medium severity Remove system sudo from PATH in missing-sudo test · New
  • Medium severity Retain all matching operation entries in tests · New
11 previously missed issues

In code that hasn't changed since last review

Medium severity Map systemd reloading state to Running

src/​Microsoft.PowerShell.Commands.Management/​commands/​management/​ServiceUnix.cs:623

reloading is a systemd ActiveState for a service that is still running, but it currently falls through to Stopped. A Get-Service query during systemctl reload therefore incorrectly reports the live service as stopped and breaks status-based filtering. Map reloading to Running as well.

Medium severity Map systemd disabled units to Manual

src/​Microsoft.PowerShell.Commands.Management/​commands/​management/​ServiceUnix.cs:640

A systemd disabled unit is still startable manually or through dependencies/socket activation; it is not equivalent to Windows ServiceStartMode.Disabled. Mapping it to Disabled misclassifies ordinary manually-started services in cross-platform StartType filters. Map disabled to Manual, and reserve Disabled for masked/masked-runtime; update the test that currently expects Disabled for foo.

Medium severity Suppress systemd unit markers when parsing list-units

src/​Microsoft.PowerShell.Commands.Management/​commands/​management/​ServiceUnix.cs:755

systemctl list-units can prefix failed/not-found units with a ● marker even with --no-legend. The parser assumes the first token is the unit name, so it discards those rows. Failed transient services disappear entirely, and file-backed ones lose their failure substate/description when recreated from list-unit-files. Add --plain to suppress the marker and cover a failed-unit row in the tests.

Medium severity Preserve launchd bootstrap domains for service mutations

src/​Microsoft.PowerShell.Commands.Management/​commands/​management/​ServiceUnix.cs:841

A non-root macOS process does not necessarily have a gui/<uid> bootstrap domain. In a headless/SSH session, launchctl list can enumerate jobs in user/<uid>, but every mutation here targets the nonexistent GUI domain and fails even with working sudo. Preserve or resolve the service's actual bootstrap domain instead of choosing it solely from root status and UID.

Medium severity Stop KeepAlive launchd jobs without automatic restart

src/​Microsoft.PowerShell.Commands.Management/​commands/​management/​ServiceUnix.cs:852

Sending SIGTERM to a launchd job does not keep it stopped. For a job configured with KeepAlive, launchd starts another process immediately, yet Stop-Service reports success (and -PassThru reports Stopped). Implement launchd lifecycle handling that actually leaves the job stopped and allows a subsequent Start-Service to restore it; test this with a KeepAlive job rather than only asserting the signal arguments.

Medium severity Capture the process reference before checking or killing it

src/​Microsoft.PowerShell.Commands.Management/​commands/​management/​ServiceUnix.cs:1165

StopProcessing runs concurrently with the invocation thread, whose finally block sets _currentProcess to null. The repeated field reads can therefore pass the null check and then dereference null in HasExited or Kill; the existing catches do not handle that exception. Capture the process reference once before checking and killing it.

Medium severity Apply service suffix handling only to systemd

src/​Microsoft.PowerShell.Commands.Management/​commands/​management/​ServiceUnix.cs:1449

Applying systemd's .service convention to every backend makes exact lookups miss labels such as com.example.service, while wildcard operations can select unintended services through synthesized names. Restrict both suffix removal here and the alternative suffixed match in MatchesServiceName at lines 1688–1690 to systemd.

Medium severity Use case-sensitive comparisons for Unix service identity

src/​Microsoft.PowerShell.Commands.Management/​commands/​management/​ServiceUnix.cs:1452

Unix service names can differ only by case, so this lookup can make Stop-Service foo stop Foo instead; case-insensitive identity maps also merge distinct services or omit dependencies. Use ordinal, case-sensitive comparisons for service identity here and in the dictionaries, deduplication, and self-dependency filter at lines 365, 527, 1642, 1993, and 2001.

Medium severity Resolve explicit systemd names outside the enumeration snapshot

src/​Microsoft.PowerShell.Commands.Management/​commands/​management/​ServiceUnix.cs:1461

An explicit systemd name is rejected unless it already appears in enumeration. A valid but never-started template instance such as [email protected] appears in neither list-units nor list-unit-files (which lists [email protected], deliberately filtered out here), so Start-Service worker@blue reports not found although systemctl can start it. Resolve exact names directly through systemd, validating LoadState, rather than treating the enumeration snapshot as exhaustive.

Medium severity Load systemd descriptions before filtering by display name

src/​Microsoft.PowerShell.Commands.Management/​commands/​management/​ServiceUnix.cs:1567

Services found only in list-unit-files have DisplayName set to their unit name. Only GetOneService refreshes their description, so Get-Service -DisplayName 'Example Worker' cannot find an unloaded service even though Get-Service worker retrieves that display name successfully. Refresh missing metadata before applying the display-name filter (preferably with a batched systemd query).

Medium severity Query actual service state for PassThru results

src/​Microsoft.PowerShell.Commands.Management/​commands/​management/​ServiceUnix.cs:1819

A successful manager exit does not establish this status. In particular, Stop-Service -NoWait -PassThru always returns Stopped even though --no-block only queues the stop, and a successful start of a oneshot unit can leave it inactive. This also leaves SubState inconsistent with Status. Query the actual service state for PassThru instead of overwriting the snapshot with the requested end state.

5 resolved since last review
  • High severity For both SysV init (service) and OpenRC (rc-service), the argument order is typically…
  • Medium severity The tests cover enumeration/parsing for launchctl/service/rc-service fallbacks, but they don’t…
  • Medium severity AddDefaultDisplayProperties unconditionally adds a PSStandardMember member set. If this helper…
  • Medium severity When elevate is true, the process is not elevated, and sudo is not present (`SudoPath is…
  • Medium severity Since this exception type is intended to mirror the Windows shape and will be embedded in…

Review effort: Balanced

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/ServiceUnix.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread test/powershell/Modules/Microsoft.PowerShell.Management/Service.Tests.ps1 Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread test/powershell/Modules/Microsoft.PowerShell.Management/Service.Tests.ps1 Resolved

Uh oh!

There was an error while loading. Please reload this page.

soroshsabz added 3 commits November 10, 2026 19:15
@soroshsabz
Refactor for static analysis: extract per-manager helpers and line pa…
45eea3c
…rsers, fix empty catches
@soroshsabz
Make UnixServiceController.cs StyleCop-default clean for CodeFactor
457eee5
@soroshsabz
Split UnixServiceController.cs into one type per file (SA1402)
a8d7b68
@soroshsabz
soroshsabz requested a balanced review from Copilot November 11, 2026 06:38
Copilot started reviewing on behalf of soroshsabz November 11, 2026 06:40
View session
Copilot AI reviewed Nov 11, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved service-identity bugs can target unintended Unix services, while non-root tests contain guaranteed assertion failures and can invoke the host’s real sudo.

5 open issues
  • High severity Restrict PATH when testing missing sudo · New
  • High severity Retain all logged operations in the non-root test · New
  • High severity Use rc-status to enumerate OpenRC services
  • Medium severity Retain all matching operation entries in tests
  • Medium severity Remove system sudo from PATH in missing-sudo test

Review effort: Balanced

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread test/powershell/Modules/Microsoft.PowerShell.Management/Service.Tests.ps1 Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread test/powershell/Modules/Microsoft.PowerShell.Management/Service.Tests.ps1 Resolved

Uh oh!

There was an error while loading. Please reload this page.

soroshsabz added 2 commits November 11, 2026 10:24
@soroshsabz
OpenRC enumeration via rc-status; harden sudo-missing and fallback te…
3ee3ab6
…sts (Copilot round 2)
@soroshsabz
Remove #region markers (SA1124)
34ce9db
@soroshsabz
soroshsabz requested a balanced review from Copilot November 11, 2026 16:13
Copilot started reviewing on behalf of soroshsabz November 11, 2026 16:28
View session
Copilot AI reviewed Nov 11, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Case-insensitive identity handling and backend-agnostic suffix stripping can stop the wrong service, while unresolved enumeration, state-reporting, and lifecycle defects further compromise service management.

10 open issues
  • High severity Restrict service suffix handling to systemd · New
  • High severity Preserve case-sensitive native service identity · New
  • Medium severity Check systemd for exact-name unit instances · New
  • Medium severity Load service descriptions before display-name filtering · New
  • Medium severity Capture the process reference before cancellation checks · New
  • Medium severity Discover launchd jobs' actual domains · New
  • Medium severity Prevent KeepAlive jobs from relaunching on stop · New
  • Medium severity Suppress systemd failure markers when listing units · New
  • Medium severity Query actual service state for PassThru results · New
  • Medium severity Map disabled systemd units to Manual · New
5 resolved since last review
  • High severity Retain all logged operations in the non-root test
  • High severity Restrict PATH when testing missing sudo
  • High severity Use rc-status to enumerate OpenRC services
  • Medium severity Retain all matching operation entries in tests
  • Medium severity Remove system sudo from PATH in missing-sudo test

Review effort: Balanced

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/MultipleServiceCommandBase.cs Outdated
{
Dbg.Assert(!WildcardPattern.ContainsWildcardCharacters(nameOfService), "Caller should verify that nameOfService doesn't contain wildcard characters");

string name = UnixServiceParser.RemoveServiceSuffix(nameOfService.Trim());

@soroshsabz soroshsabz Nov 11, 2026

Copy link
Copy Markdown
Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0637796: the facade strips the .service suffix only when the manager is systemd; launchd, SysV and OpenRC names are used verbatim, so Stop-Service -Name com.example.service on launchd targets the exact label. There is also no synthetic suffix alternative in wildcard matching anymore - the shared master code matches wildcards against the manager-reported name, and systemd enumeration names are suffix-stripped by the parser.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/MultipleServiceCommandBase.cs Outdated
string name = UnixServiceParser.RemoveServiceSuffix(nameOfService.Trim());
foreach (UnixServiceController service in AllServices)
{
if (string.Equals(service.Name, name, StringComparison.OrdinalIgnoreCase))

@soroshsabz soroshsabz Nov 11, 2026

Copy link
Copy Markdown
Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0483d24 and 0637796: the facade now prefers an exact ordinal name match and only falls back to a case-insensitive comparison when no exact match exists, and the parser's unit-file merge and OpenRC deduplication dictionaries compare names ordinally, so distinct units differing only in case are no longer conflated. (The duplicate detection in master's MultipleServiceCommandBase already compared names case-sensitively.)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/MultipleServiceCommandBase.cs Outdated
}
}

return null;

@soroshsabz soroshsabz Nov 11, 2026

Copy link
Copy Markdown
Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged: template instances that were never loaded (for example [email protected]) appear in neither list-units nor list-unit-files (only the [email protected] template is listed, and template instances are deliberately not synthesized), so an exact-name lookup reports NoServiceFoundForGivenName. Adding a targeted systemctl show <unit> existence check for enumeration misses is a possible follow-up; it is out of scope for this working-group PR, which focuses on basic Get/Start/Stop/Restart parity.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/MultipleServiceCommandBase.cs Outdated
bool found = false;
foreach (UnixServiceController service in AllServices)
{
if (!wildcard.IsMatch(service.DisplayName))

@soroshsabz soroshsabz Nov 11, 2026

Copy link
Copy Markdown
Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True: systemctl list-unit-files does not carry descriptions, so for units that were never loaded the facade exposes the unit name as DisplayName, and -DisplayName matching by description only works for loaded units (which come from list-units with a description). Populating descriptions for never-loaded units would require a metadata query (for example systemctl show) per unit; that cost is not justified for the working-group scope of this PR, and it is noted as a possible follow-up.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/ServiceBaseCommand.cs Outdated
Comment on lines +402 to +405
if (currentProcess is not null && !currentProcess.HasExited)
{
currentProcess.Kill(entireProcessTree: true);
}

@soroshsabz soroshsabz Nov 11, 2026

Copy link
Copy Markdown
Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code path no longer exists in the PR: the parallel-implementation files (including ServiceBaseCommand.cs with the currentProcess field and the custom StopProcessing) were removed in the rework, and master's ServiceBaseCommand is reused unchanged. Resolving as obsolete.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/ServiceBaseCommand.cs Outdated
Comment on lines +467 to +470
string domain = manager.IsElevated
? "system"
: $"gui/{UnixServiceNativeMethods.GetUserId()}";
string unitPath = domain + "/" + service.Name;

@soroshsabz soroshsabz Nov 11, 2026

Copy link
Copy Markdown
Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The facade enumerates with launchctl list in the caller's context and derives the mutation target from the same identity (the system domain for root, gui/<uid> otherwise), so enumeration and operations always address the same domain. Per-job domain discovery would require parsing launchctl print output for every job; that is beyond the working-group scope of this PR and is noted as a follow-up.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/ServiceBaseCommand.cs Outdated
return action switch
{
ServiceAction.Start => new List<string> { "kickstart", unitPath },
ServiceAction.Stop => new List<string> { "kill", "SIGTERM", unitPath },

@soroshsabz soroshsabz Nov 11, 2026

Copy link
Copy Markdown
Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged. Switching stop to bootout would prevent KeepAlive relaunches, but the facade only knows the job's label from launchctl list; re-starting a booted-out job requires bootstrap with the job's plist path, which is not tracked. The current label-based lifecycle (kickstart / kill SIGTERM / kickstart -k) operates on exactly the jobs that enumeration reported and is straightforwardly sudo-wrappable. Discovering each job's plist path (for example from launchctl print) so that stop can use bootout and start can use bootstrap is a reasonable follow-up beyond the working-group scope of this PR.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/ServiceBaseCommand.cs Outdated
private List<UnixServiceController> EnumerateSystemdServices()
{
ServiceCommandResult units = RunServiceManagerCommand(
new[] { "list-units", "--type=service", "--all", "--no-legend", "--no-pager" },

@soroshsabz soroshsabz Nov 11, 2026

Copy link
Copy Markdown
Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0637796: --plain was added to the list-units invocation so failed units are no longer prefixed with a marker, and the test now enumerates a failed unit and asserts its name, status and sub-state.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/ServiceOperationBaseCommand.cs Outdated
/// <returns>The service with the expected status.</returns>
internal static UnixServiceController ApplyExpectedStatus(UnixServiceController service, ServiceControllerStatus status)
{
service.Status = status;

@soroshsabz soroshsabz Nov 11, 2026

Copy link
Copy Markdown
Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Unix facade deliberately keeps Status as the state reported by the last enumeration or operation: mutating operations update it from the manager's exit status, and when waiting is requested the shared cmdlet code (DoWaitForStatus) confirms the transition. With -NoWait the caller explicitly opts out of waiting, so a point-in-time snapshot is the documented behavior; SubState likewise reflects the last enumeration. Note also that the referenced file (ServiceOperationBaseCommand.cs) no longer exists in this PR - master's implementation is reused unchanged and the Unix behavior lives in UnixServiceController.cs. Querying the live state for -NoWait -PassThru would add manager invocations and special-case oneshot units, so I would like to keep that as a possible follow-up.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/Microsoft.PowerShell.Commands.Management/commands/management/UnixServiceParser.cs Outdated
return unitFileState switch
{
"enabled" or "enabled-runtime" or "generated" or "generated-runtime" or "transient" => ServiceStartMode.Automatic,
"disabled" or "masked" => ServiceStartMode.Disabled,

@soroshsabz soroshsabz Nov 11, 2026

Copy link
Copy Markdown
Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0483d24 and 0637796: disabled now maps to ServiceStartMode.Manual (a disabled unit can still be started manually), masked/masked-runtime map to ServiceStartMode.Disabled, and the test expectation in Service.Tests.ps1 was updated accordingly.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
soroshsabz added 5 commits November 11, 2026 21:01
@soroshsabz
Reuse master Service.cs for Unix service cmdlets
a14dbb4
Compile the master Service.cs cmdlet implementation on Unix as well and
map the unqualified ServiceController name to a Unix service-manager
facade (UnixServiceController) via a using alias, so Get/Start/Stop/
Restart-Service work on Unix with only a few platform-specific branches:

- Service.cs: top '#if !UNIX' replaced by Unix aliases; the five
  Windows-SCM-only cmdlets (Set/New/Remove/Suspend/Resume-Service) and
  the SCM property/native sections stay guarded with '#if !UNIX'.
- Get-Service ProcessRecord gains a Unix branch that honors
  -DependentServices/-RequiredServices and reports NoServiceManagerFound.
- DoStartService/DoStopService surface sudo-unavailable failures as
  SudoRequired errors on Unix.
- UnixServiceNativeMethods gains the ERROR_SERVICE_* constants that the
  shared code compares against, aliased as NativeMethods on Unix.
@soroshsabz
Fix end-of-file newline in Service.cs
df8a97d
@soroshsabz
Assert the exact enumeration failure error id
ac69b72
@soroshsabz
Address Copilot review round: --plain, start mode semantics, name mat…
0637796
…ching

- 'systemctl list-units' gains --plain so failed units (prefixed with a
  marker without it) are still enumerated.
- systemd 'disabled' maps to ServiceStartMode.Manual (it can still be
  started manually); ServiceStartMode.Disabled is reserved for masked
  unit files, matching the Windows semantics of these values.
- The Unix service controller prefers an exact native name match and
  only falls back to the case-insensitive lookup when there is no exact
  match, so distinct units differing in case are not conflated.
- The '.service' suffix is only stripped for the systemd manager; other
  managers use the provided name verbatim.
@soroshsabz
Use ordinal name comparisons in the Unix service parser
0483d24
@soroshsabz
soroshsabz requested a balanced review from Copilot November 11, 2026 20:39
@soroshsabz soroshsabz mentioned this pull request Nov 11, 2026
Document Unix platform support for Get/Start/Stop/Restart-Service MicrosoftDocs/PowerShell-Docs#13385
Open
2 tasks done
Copilot AI reviewed Nov 11, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Note

This error may be related to your runner configuration. You can now configure runners for Copilot code review separately from Copilot cloud agent by creating a copilot-code-review.yml file with your setup steps. Read the docs for details.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

Copilot code review Copilot
Copilot review effort
Applies to this pull request for everyone.Learn more about Copilot code review.
Copilot left review comments

At least 1 approving review is required to merge this pull request.

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Restart-Service should call systemctl restart on Linux OSes with SystemD present.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@soroshsabz
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.