Module: OS::Linux::Diagnostic::Checks Private

Extended by:
T::Helpers
Included in:
Homebrew::Diagnostic::Checks
Defined in:
extend/os/linux/diagnostic.rb

Overview

This module is part of a private API. This module may only be used in the Homebrew/brew repository. Third parties should avoid using this module if possible, as it may be removed or changed without warning.

Linux-specific diagnostic checks for Homebrew.

Instance Method Summary collapse

Instance Method Details

#check_cask_software_versions::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



356
357
358
359
360
361
# File 'extend/os/linux/diagnostic.rb', line 356

def check_cask_software_versions
  super
  add_info "Linux", OS::Linux.os_version

  nil
end

#check_for_symlinked_home::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'extend/os/linux/diagnostic.rb', line 289

def check_for_symlinked_home
  return unless File.symlink?("/home")

  ::Homebrew::Diagnostic::Finding.new(
    <<~EOS,
    tier:        2,
    links:       ["https://github.com/Homebrew/brew/issues/18036"],
    remediation: <<~EOS,
      If you encounter linking issues, you may need to manually create conflicting
      directories or use `brew link --overwrite` as a workaround.
      We'd welcome a PR to fix this functionality.
    EOS
  )
end

#check_gcc_dependent_linkage::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'extend/os/linux/diagnostic.rb', line 312

def check_gcc_dependent_linkage
  gcc_dependents = ::Formula.installed.select do |formula|
    next false unless formula.tap&.core_tap?

    # FIXME: This includes formulae that have no runtime dependency on GCC.
    formula.recursive_dependencies.map(&:name).include? "gcc"
  rescue TapFormulaUnavailableError
    false
  end
  return if gcc_dependents.empty?

  badly_linked = gcc_dependents.select do |dependent|
    dependent_prefix = dependent.any_installed_prefix
    # Keg.new() may raise an error if it is not a directory.
    # As the result `brew doctor` may display `Error: <keg> is not a directory`
    # instead of proper `doctor` information.
    # There are other checks that test that, we can skip broken kegs.
    next if dependent_prefix.nil? || !dependent_prefix.exist? || !dependent_prefix.directory?

    keg = ::Keg.new(dependent_prefix)
    keg.binary_executable_or_library_files.any? do |binary|
      paths = binary.rpaths
      versioned_linkage = paths.any? { |path| path.match?(%r{lib/gcc/\d+$}) }
      unversioned_linkage = paths.any? { |path| path.match?(%r{lib/gcc/current$}) }

      versioned_linkage && !unversioned_linkage
    end
  end

  return if badly_linked.empty?

  remediation = ::Homebrew::Diagnostic::Finding::Remediation.new(
    commands: ["brew reinstall #{badly_linked.join(" ")}"],
  )
  ::Homebrew::Diagnostic::Finding.new(
    <<~EOS,
      Formulae which link to GCC through a versioned path were found. These formulae
      are prone to breaking when GCC is updated.
    EOS
    remediation:,
  )
end

#check_glibc_minimum_version::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'extend/os/linux/diagnostic.rb', line 116

def check_glibc_minimum_version
  return unless OS::Linux::Glibc.below_minimum_version?

  ::Homebrew::Diagnostic::Finding.new(
    <<~EOS,
    tier:        :unsupported,
    remediation: <<~EOS,
      We recommend updating to a newer version via your distribution's
      package manager, upgrading your distribution to the latest version,
      or changing distributions.
    EOS
  )
end

#check_glibc_next_version::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'extend/os/linux/diagnostic.rb', line 155

def check_glibc_next_version
  return if OS::LINUX_GLIBC_NEXT_CI_VERSION.blank?
  return if OS::Linux::Glibc.below_ci_version?
  return if OS::Linux::Glibc.system_version >= OS::LINUX_GLIBC_NEXT_CI_VERSION

  # We want to bypass this check in some tests.
  return if ENV["HOMEBREW_GLIBC_TESTING"] || ENV["CI"] || ENV["HOMEBREW_TEST_BOT"].present?

  ::Homebrew::Diagnostic::Finding.new(
    <<~EOS,
    remediation: <<~EOS,
      We recommend updating to a newer version via your distribution's
      package manager, upgrading your distribution to the latest version,
      or changing distributions.
    EOS
  )
end

#check_glibc_version::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'extend/os/linux/diagnostic.rb', line 134

def check_glibc_version
  return unless OS::Linux::Glibc.below_ci_version?

  # We want to bypass this check in some tests.
  return if ENV["HOMEBREW_GLIBC_TESTING"]

  ::Homebrew::Diagnostic::Finding.new(
    <<~EOS,
    tier:        2,
    remediation: <<~EOS,
      We recommend updating to a newer version via your distribution's
      package manager, upgrading your distribution to the latest version,
      or changing distributions.
    EOS
  )
end

#check_kernel_minimum_version::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'extend/os/linux/diagnostic.rb', line 177

def check_kernel_minimum_version
  return unless OS::Linux::Kernel.below_minimum_version?

  ::Homebrew::Diagnostic::Finding.new(
    <<~EOS,
    tier:        3,
    remediation: <<~EOS,
      We recommend updating to a newer version via your distribution's
      package manager, upgrading your distribution to the latest version,
      or changing distributions.
    EOS
  )
end

#check_linux_sandbox::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'extend/os/linux/diagnostic.rb', line 196

def check_linux_sandbox
  return unless Homebrew::EnvConfig.sandbox_linux?

  inside_docker = OS::Linux.inside_docker?
  return if inside_docker && !GitHub::Actions.env_set?

  state = ::Sandbox.state
  return if state == :available

  reason = ::Sandbox.failure_reason || "The Linux sandbox is not available."
  state = :landlock if OS::Linux::Sandbox.landlock?
  reason_append = case state
  when :setuid
    "\n\nHomebrew's Linux sandbox requires a rootless `bwrap` executable."
  when :unavailable
    "\n\nHomebrew's Linux sandbox requires rootless Bubblewrap and unprivileged user namespaces."
  else
    ""
  end
  reason += reason_append

  fix_lines = case state
  when :missing
    missing_lines = [
      reason,
      "",
      "Install Bubblewrap and ensure a rootless `bwrap` executable is available on `PATH`.",
    ]
    if (install_command = ::Sandbox.sandbox_install_command)
      missing_lines.push("", "On this system, install it with:", "  #{install_command}")
    end
    missing_lines
  when :setuid
    [
      "Install a non-setuid Bubblewrap or put it earlier on `PATH`.",
    ]
  when :unavailable
    [
      reason,
      "",
      "Homebrew's Linux sandbox requires rootless Bubblewrap and unprivileged",
      "user namespaces. Run `sudo brew setup-sandbox` or check and update this system configuration:",
      *::Sandbox.configuration_command_messages,
    ]
  else
    []
  end
  if state == :unavailable && inside_docker && GitHub::Actions.env_set?
    fix_lines.push("",
                   "If this is a GitHub Actions container, add `options: --privileged` to the job's " \
                   "`container` configuration.")
  end

  ::Homebrew::Diagnostic::Finding.new(
    reason,
    remediation: [
      *fix_lines,
      "",
      "As a final workaround, disable the Linux sandbox:",
      "  export HOMEBREW_NO_SANDBOX_LINUX=1",
    ].join("\n").to_s,
  )
end

#check_linuxbrew_bottle_domain::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



279
280
281
282
283
284
285
286
# File 'extend/os/linux/diagnostic.rb', line 279

def check_linuxbrew_bottle_domain
  return unless Homebrew::EnvConfig.bottle_domain.include?("linuxbrew")

  ::Homebrew::Diagnostic::Finding.new(
    'Your `$HOMEBREW_BOTTLE_DOMAIN` still contains "linuxbrew".',
    remediation: "You must unset `$HOMEBREW_BOTTLE_DOMAIN` or adjust it to not contain \"linuxbrew\".",
  )
end

#check_linuxbrew_core::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'extend/os/linux/diagnostic.rb', line 261

def check_linuxbrew_core
  return unless Homebrew::EnvConfig.no_install_from_api?
  return unless CoreTap.instance.linuxbrew_core?

  ::Homebrew::Diagnostic::Finding.new(
    <<~EOS,
    remediation: <<~EOS,
      You can unset `$HOMEBREW_NO_INSTALL_FROM_API` or set
      the repository's remote to homebrew-core to update core formulae.
    EOS
  )
end

#check_supported_architecture::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



102
103
104
105
106
107
108
109
110
111
112
113
# File 'extend/os/linux/diagnostic.rb', line 102

def check_supported_architecture
  return if ::Hardware::CPU.intel?
  return if ::Hardware::CPU.arm64?

  ::Homebrew::Diagnostic::Finding.new(
    <<~EOS,
      Your CPU architecture (#{::Hardware::CPU.arch}) is not supported. We only support
      x86_64 or ARM64/AArch64 CPU architectures. You will be unable to use binary packages (bottles).
    EOS
    tier: 2,
  )
end

#check_tmpdir_executable::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



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
# File 'extend/os/linux/diagnostic.rb', line 56

def check_tmpdir_executable
  f = Tempfile.new(%w[homebrew_check_tmpdir_executable .sh], HOMEBREW_TEMP)
  f.write "#!/bin/sh\n"
  f.chmod 0700
  f.close
  return if system T.must(f.path)

  ::Homebrew::Diagnostic::Finding.new(
    <<~EOS,
    remediation: ::Homebrew::Diagnostic::Finding::Remediation.new(
      commands: ["export HOMEBREW_TEMP=~/tmp", "echo 'export HOMEBREW_TEMP=~/tmp' >> #{Utils::Shell.profile}"],
      text:     <<~EOS,
        Please set `$HOMEBREW_TEMP`
        in your #{Utils::Shell.profile} to a different directory, for example:
          export HOMEBREW_TEMP=~/tmp
          echo 'export HOMEBREW_TEMP=~/tmp' >> #{Utils::Shell.profile}
      EOS
    ),
  )
ensure
  f&.unlink
end

#check_tmpdir_sticky_bit::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'extend/os/linux/diagnostic.rb', line 40

def check_tmpdir_sticky_bit
  finding = super
  return if finding.nil?

  finding.remediation.text += <<~EOS
    If you don't have administrative privileges on this machine,
    create a directory and set the `$HOMEBREW_TEMP` environment variable,
    for example:
      install -d -m 1755 ~/tmp
      #{Utils::Shell.set_variable_in_profile("HOMEBREW_TEMP", "~/tmp")}
  EOS

  finding
end

#check_umask_not_zero::Homebrew::Diagnostic::Finding?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'extend/os/linux/diagnostic.rb', line 83

def check_umask_not_zero
  return unless File.umask.zero?

  ::Homebrew::Diagnostic::Finding.new(
    <<~EOS,
    remediation: ::Homebrew::Diagnostic::Finding::Remediation.new(
      text:     <<~EOS,
        This issue can be resolved by adding "umask 002" to
        your #{Utils::Shell.profile}:
      EOS
      commands: ["echo 'umask 002' >> #{Utils::Shell.profile}"],
    ),
  )
end

#fatal_preinstall_checksArray<String>

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



22
23
24
25
26
27
28
# File 'extend/os/linux/diagnostic.rb', line 22

def fatal_preinstall_checks
  %w[
    check_access_directories
    check_linuxbrew_core
    check_linuxbrew_bottle_domain
  ].freeze
end

#supported_configuration_checksArray<String>

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



31
32
33
34
35
36
37
# File 'extend/os/linux/diagnostic.rb', line 31

def supported_configuration_checks
  %w[
    check_glibc_minimum_version
    check_kernel_minimum_version
    check_supported_architecture
  ].freeze
end