services: add --keep flag

This commit is contained in:
Bo Anderson 2025-03-25 03:43:54 +00:00
parent ad75e9b337
commit 0b58e8fd37
No known key found for this signature in database
4 changed files with 38 additions and 12 deletions

View File

@ -38,8 +38,9 @@ module Homebrew
[`sudo`] `brew services start` (<formula>|`--all`|`--file=`): [`sudo`] `brew services start` (<formula>|`--all`|`--file=`):
Start the service <formula> immediately and register it to launch at login (or boot). Start the service <formula> immediately and register it to launch at login (or boot).
[`sudo`] `brew services stop` (<formula>|`--all`): [`sudo`] `brew services stop` (`--keep`) (`--no-wait`|`--max-wait=`) (<formula>|`--all`):
Stop the service <formula> immediately and unregister it from launching at login (or boot). Stop the service <formula> immediately and unregister it from launching at login (or boot),
unless `--keep` is specified.
[`sudo`] `brew services kill` (<formula>|`--all`): [`sudo`] `brew services kill` (<formula>|`--all`):
Stop the service <formula> immediately but keep it registered to launch at login (or boot). Stop the service <formula> immediately but keep it registered to launch at login (or boot).
@ -57,6 +58,7 @@ module Homebrew
switch "--all", description: "Run <subcommand> on all services." switch "--all", description: "Run <subcommand> on all services."
switch "--json", description: "Output as JSON." switch "--json", description: "Output as JSON."
switch "--no-wait", description: "Don't wait for `stop` to finish stopping the service." switch "--no-wait", description: "Don't wait for `stop` to finish stopping the service."
switch "--keep", description: "When stopped, don't unregister the service from launching at login (or boot)."
conflicts "--max-wait=", "--no-wait" conflicts "--max-wait=", "--no-wait"
named_args named_args
end end
@ -117,6 +119,14 @@ module Homebrew
end end
end end
unless Homebrew::Services::Commands::Stop::TRIGGERS.include?(subcommand)
raise UsageError, "The `#{subcommand}` subcommand does not accept the --keep argument!" if args.keep?
raise UsageError, "The `#{subcommand}` subcommand does not accept the --no-wait argument!" if args.no_wait?
if args.max_wait
raise UsageError, "The `#{subcommand}` subcommand does not accept the --max-wait= argument!"
end
end
opoo "The --all argument overrides provided formula argument!" if formulae.present? && args.all? opoo "The --all argument overrides provided formula argument!" if formulae.present? && args.all?
targets = if args.all? targets = if args.all?
@ -162,8 +172,13 @@ module Homebrew
when *Homebrew::Services::Commands::Start::TRIGGERS when *Homebrew::Services::Commands::Start::TRIGGERS
Homebrew::Services::Commands::Start.run(targets, args.file, verbose: args.verbose?) Homebrew::Services::Commands::Start.run(targets, args.file, verbose: args.verbose?)
when *Homebrew::Services::Commands::Stop::TRIGGERS when *Homebrew::Services::Commands::Stop::TRIGGERS
max_wait = args.max_wait.to_f Homebrew::Services::Commands::Stop.run(
Homebrew::Services::Commands::Stop.run(targets, verbose: args.verbose?, no_wait: args.no_wait?, max_wait:) targets,
verbose: args.verbose?,
no_wait: args.no_wait?,
max_wait: args.max_wait.to_f,
keep: args.keep?,
)
when *Homebrew::Services::Commands::Kill::TRIGGERS when *Homebrew::Services::Commands::Kill::TRIGGERS
Homebrew::Services::Commands::Kill.run(targets, verbose: args.verbose?) Homebrew::Services::Commands::Kill.run(targets, verbose: args.verbose?)
else else

View File

@ -159,12 +159,13 @@ module Homebrew
verbose: T::Boolean, verbose: T::Boolean,
no_wait: T::Boolean, no_wait: T::Boolean,
max_wait: T.nilable(T.any(Integer, Float)), max_wait: T.nilable(T.any(Integer, Float)),
keep: T::Boolean,
).void ).void
} }
def self.stop(targets, verbose: false, no_wait: false, max_wait: 0) def self.stop(targets, verbose: false, no_wait: false, max_wait: 0, keep: false)
targets.each do |service| targets.each do |service|
unless service.loaded? unless service.loaded?
rm service.dest if service.dest.exist? # get rid of installed service file anyway, dude rm service.dest if !keep && service.dest.exist? # get rid of installed service file anyway, dude
if service.service_file_present? if service.service_file_present?
odie <<~EOS odie <<~EOS
Service `#{service.name}` is started as `#{service.owner}`. Try: Service `#{service.name}` is started as `#{service.owner}`. Try:
@ -188,7 +189,11 @@ module Homebrew
end end
if System.systemctl? if System.systemctl?
if keep
System::Systemctl.quiet_run(*systemctl_args, "stop", service.service_name)
else
System::Systemctl.quiet_run(*systemctl_args, "disable", "--now", service.service_name) System::Systemctl.quiet_run(*systemctl_args, "disable", "--now", service.service_name)
end
elsif System.launchctl? elsif System.launchctl?
quiet_system System.launchctl, "bootout", "#{System.domain_target}/#{service.service_name}" quiet_system System.launchctl, "bootout", "#{System.domain_target}/#{service.service_name}"
unless no_wait unless no_wait
@ -204,9 +209,11 @@ module Homebrew
quiet_system System.launchctl, "stop", "#{System.domain_target}/#{service.service_name}" if service.pid? quiet_system System.launchctl, "stop", "#{System.domain_target}/#{service.service_name}" if service.pid?
end end
unless keep
rm service.dest if service.dest.exist? rm service.dest if service.dest.exist?
# Run daemon-reload on systemctl to finish unloading stopped and deleted service. # Run daemon-reload on systemctl to finish unloading stopped and deleted service.
System::Systemctl.run(*systemctl_args, "daemon-reload") if System.systemctl? System::Systemctl.run(*systemctl_args, "daemon-reload") if System.systemctl?
end
if service.pid? || service.loaded? if service.pid? || service.loaded?
opoo "Unable to stop `#{service.name}` (label: #{service.service_name})" opoo "Unable to stop `#{service.name}` (label: #{service.service_name})"

View File

@ -15,11 +15,12 @@ module Homebrew
verbose: T::Boolean, verbose: T::Boolean,
no_wait: T::Boolean, no_wait: T::Boolean,
max_wait: T.nilable(Float), max_wait: T.nilable(Float),
keep: T::Boolean,
).void ).void
} }
def self.run(targets, verbose:, no_wait:, max_wait:) def self.run(targets, verbose:, no_wait:, max_wait:, keep:)
Services::Cli.check(targets) Services::Cli.check(targets)
Services::Cli.stop(targets, verbose:, no_wait:, max_wait:) Services::Cli.stop(targets, verbose:, no_wait:, max_wait:, keep:)
end end
end end
end end

View File

@ -20,6 +20,9 @@ class Homebrew::Cmd::Services::Args < Homebrew::CLI::Args
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
def json?; end def json?; end
sig { returns(T::Boolean) }
def keep?; end
sig { returns(T.nilable(String)) } sig { returns(T.nilable(String)) }
def max_wait; end def max_wait; end