-
-
Notifications
You must be signed in to change notification settings - Fork 206
/
services.rb
executable file
·158 lines (131 loc) · 6.71 KB
/
services.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# typed: true
# frozen_string_literal: true
homebrew_version = if HOMEBREW_VERSION.present?
HOMEBREW_VERSION.delete_prefix(">=")
.delete_suffix(" (shallow or no git repository)")
else
"0.0.1"
end
if !Process.euid.zero? && Version.new(homebrew_version) < Version.new("4.2.15")
odie "Your Homebrew is too outdated for `brew services`. Please run `brew update`!"
end
require "abstract_command"
require "service"
module Homebrew
module Cmd
class Services < AbstractCommand
cmd_args do
usage_banner <<~EOS
`services` [<subcommand>]
Manage background services with macOS' `launchctl`(1) daemon manager or
Linux's `systemctl`(1) service manager.
If `sudo` is passed, operate on `/Library/LaunchDaemons` or `/usr/lib/systemd/system` (started at boot).
Otherwise, operate on `~/Library/LaunchAgents` or `~/.config/systemd/user` (started at login).
[`sudo`] `brew services` [`list`] (`--json`) (`--debug`):
List information about all managed services for the current user (or root).
Provides more output from Homebrew and `launchctl`(1) or `systemctl`(1) if run with `--debug`.
[`sudo`] `brew services info` (<formula>|`--all`|`--json`):
List all managed services for the current user (or root).
[`sudo`] `brew services run` (<formula>|`--all`):
Run the service <formula> without registering to launch at login (or boot).
[`sudo`] `brew services start` (<formula>|`--all`|`--file=`):
Start the service <formula> immediately and register it to launch at login (or boot).
[`sudo`] `brew services stop` (<formula>|`--all`):
Stop the service <formula> immediately and unregister it from launching at login (or boot).
[`sudo`] `brew services kill` (<formula>|`--all`):
Stop the service <formula> immediately but keep it registered to launch at login (or boot).
[`sudo`] `brew services restart` (<formula>|`--all`):
Stop (if necessary) and start the service <formula> immediately and register it to launch at login (or boot).
[`sudo`] `brew services cleanup`:
Remove all unused services.
EOS
flag "--file=", description: "Use the service file from this location to `start` the service."
flag "--sudo-service-user=", description: "When run as root on macOS, run the service(s) as this user."
switch "--all", description: "Run <subcommand> on all services."
switch "--json", description: "Output as JSON."
switch "--no-wait", description: "Don't wait for `stop` to finish stopping the service."
named_args max: 2
end
def run
# pbpaste's exit status is a proxy for detecting the use of reattach-to-user-namespace
if ENV["HOMEBREW_TMUX"] && (File.exist?("/usr/bin/pbpaste") && !quiet_system("/usr/bin/pbpaste"))
raise UsageError,
"`brew services` cannot run under tmux!"
end
# Keep this after the .parse to keep --help fast.
require_relative "../lib/service"
require "utils"
if !::Service::System.launchctl? && !::Service::System.systemctl?
raise UsageError,
"`brew services` is supported only on macOS or Linux (with systemd)!"
end
if (sudo_service_user = args.sudo_service_user)
unless ::Service::System.root?
raise UsageError,
"`brew services` is supported only when running as root!"
end
unless ::Service::System.launchctl?
raise UsageError,
"`brew services --sudo-service-user` is currently supported only on macOS " \
"(but we'd love a PR to add Linux support)!"
end
::Service::ServicesCli.sudo_service_user = sudo_service_user
end
# Parse arguments.
subcommand, formula, = args.named
if [*::Service::Commands::List::TRIGGERS, *::Service::Commands::Cleanup::TRIGGERS].include?(subcommand)
raise UsageError, "The `#{subcommand}` subcommand does not accept a formula argument!" if formula
raise UsageError, "The `#{subcommand}` subcommand does not accept the --all argument!" if args.all?
end
if args.file
if ::Service::Commands::Start::TRIGGERS.exclude?(subcommand)
raise UsageError, "The `#{subcommand}` subcommand does not accept the --file= argument!"
elsif args.all?
raise UsageError, "The start subcommand does not accept the --all and --file= arguments at the same time!"
end
end
opoo "The --all argument overrides provided formula argument!" if formula.present? && args.all?
targets = if args.all?
if subcommand == "start"
::Service::Formulae.available_services(loaded: false, skip_root: !::Service::System.root?)
elsif subcommand == "stop"
::Service::Formulae.available_services(loaded: true, skip_root: !::Service::System.root?)
else
::Service::Formulae.available_services
end
elsif formula
[::Service::FormulaWrapper.new(Formulary.factory(formula))]
else
[]
end
# Exit successfully if --all was used but there is nothing to do
return if args.all? && targets.empty?
if ::Service::System.systemctl?
ENV["DBUS_SESSION_BUS_ADDRESS"] = ENV.fetch("HOMEBREW_DBUS_SESSION_BUS_ADDRESS", nil)
ENV["XDG_RUNTIME_DIR"] = ENV.fetch("HOMEBREW_XDG_RUNTIME_DIR", nil)
end
# Dispatch commands and aliases.
case subcommand.presence
when *::Service::Commands::List::TRIGGERS
::Service::Commands::List.run(json: args.json?)
when *::Service::Commands::Cleanup::TRIGGERS
::Service::Commands::Cleanup.run
when *::Service::Commands::Info::TRIGGERS
::Service::Commands::Info.run(targets, verbose: args.verbose?, json: args.json?)
when *::Service::Commands::Restart::TRIGGERS
::Service::Commands::Restart.run(targets, verbose: args.verbose?)
when *::Service::Commands::Run::TRIGGERS
::Service::Commands::Run.run(targets, verbose: args.verbose?)
when *::Service::Commands::Start::TRIGGERS
::Service::Commands::Start.run(targets, args.file, verbose: args.verbose?)
when *::Service::Commands::Stop::TRIGGERS
::Service::Commands::Stop.run(targets, verbose: args.verbose?, no_wait: args.no_wait?)
when *::Service::Commands::Kill::TRIGGERS
::Service::Commands::Kill.run(targets, verbose: args.verbose?)
else
raise UsageError, "unknown subcommand: `#{subcommand}`"
end
end
end
end
end