gc.scm 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2012-2013, 2015-2020, 2022 Ludovic Courtès <ludo@gnu.org>
  3. ;;;
  4. ;;; This file is part of GNU Guix.
  5. ;;;
  6. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; GNU Guix is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (guix scripts gc)
  19. #:use-module (guix ui)
  20. #:use-module (guix scripts)
  21. #:use-module (guix store)
  22. #:use-module (guix store roots)
  23. #:autoload (guix build syscalls) (free-disk-space)
  24. #:autoload (guix profiles) (generation-profile
  25. profile-generations
  26. generation-number)
  27. #:autoload (guix scripts package) (delete-generations)
  28. #:autoload (gnu home) (home-generation-base)
  29. #:use-module (ice-9 match)
  30. #:use-module (ice-9 regex)
  31. #:use-module (srfi srfi-1)
  32. #:use-module (srfi srfi-11)
  33. #:use-module (srfi srfi-26)
  34. #:use-module (srfi srfi-37)
  35. #:export (guix-gc))
  36. ;;;
  37. ;;; Command-line options.
  38. ;;;
  39. (define %default-options
  40. ;; Alist of default option values.
  41. `((action . collect-garbage)))
  42. (define (show-help)
  43. (display (G_ "Usage: guix gc [OPTION]... PATHS...
  44. Invoke the garbage collector.\n"))
  45. (display (G_ "
  46. -C, --collect-garbage[=MIN]
  47. collect at least MIN bytes of garbage"))
  48. (display (G_ "
  49. -F, --free-space=FREE attempt to reach FREE available space in the store"))
  50. (display (G_ "
  51. -d, --delete-generations[=PATTERN]
  52. delete profile generations matching PATTERN"))
  53. (display (G_ "
  54. -D, --delete attempt to delete PATHS"))
  55. (display (G_ "
  56. --list-roots list the user's garbage collector roots"))
  57. (display (G_ "
  58. --list-busy list store items used by running processes"))
  59. (display (G_ "
  60. --optimize optimize the store by deduplicating identical files"))
  61. (display (G_ "
  62. --list-dead list dead paths"))
  63. (display (G_ "
  64. --list-live list live paths"))
  65. (newline)
  66. (display (G_ "
  67. --references list the references of PATHS"))
  68. (display (G_ "
  69. -R, --requisites list the requisites of PATHS"))
  70. (display (G_ "
  71. --referrers list the referrers of PATHS"))
  72. (display (G_ "
  73. --derivers list the derivers of PATHS"))
  74. (newline)
  75. (display (G_ "
  76. --verify[=OPTS] verify the integrity of the store; OPTS is a
  77. comma-separated combination of 'repair' and
  78. 'contents'"))
  79. (display (G_ "
  80. --list-failures list cached build failures"))
  81. (display (G_ "
  82. --clear-failures remove PATHS from the set of cached failures"))
  83. (newline)
  84. (display (G_ "
  85. -h, --help display this help and exit"))
  86. (display (G_ "
  87. -V, --version display version information and exit"))
  88. (newline)
  89. (show-bug-report-information))
  90. (define argument->verify-options
  91. (let ((not-comma (char-set-complement (char-set #\,)))
  92. (validate (lambda (option)
  93. (unless (memq option '(repair contents))
  94. (leave (G_ "~a: invalid '--verify' option~%")
  95. option)))))
  96. (lambda (arg)
  97. "Turn ARG into a list of symbols denoting '--verify' options."
  98. (if arg
  99. (let ((lst (map string->symbol
  100. (string-tokenize arg not-comma))))
  101. (for-each validate lst)
  102. lst)
  103. '()))))
  104. (define (delete-old-generations store profile pattern)
  105. "Remove the generations of PROFILE that match PATTERN, a duration pattern;
  106. do nothing if none matches. If PATTERN is #f, delete all generations but the
  107. current one."
  108. (let* ((current (generation-number profile))
  109. (numbers (if (not pattern)
  110. (profile-generations profile)
  111. (matching-generations pattern profile
  112. #:duration-relation >))))
  113. ;; Make sure we don't inadvertently remove the current generation.
  114. (delete-generations store profile (delv current numbers))))
  115. (define %options
  116. ;; Specification of the command-line options.
  117. (list (option '(#\h "help") #f #f
  118. (lambda args
  119. (show-help)
  120. (exit 0)))
  121. (option '(#\V "version") #f #f
  122. (lambda args
  123. (show-version-and-exit "guix gc")))
  124. (option '(#\C "collect-garbage") #f #t
  125. (lambda (opt name arg result)
  126. (let ((result (alist-cons 'action 'collect-garbage
  127. (alist-delete 'action result))))
  128. (match arg
  129. ((? string?)
  130. (let ((amount (size->number arg)))
  131. (if arg
  132. (alist-cons 'min-freed amount result)
  133. (leave (G_ "invalid amount of storage: ~a~%")
  134. arg))))
  135. (#f result)))))
  136. (option '(#\F "free-space") #t #f
  137. (lambda (opt name arg result)
  138. (alist-cons 'free-space (size->number arg) result)))
  139. (option '(#\D "delete") #f #f ;used to be '-d' (lower case)
  140. (lambda (opt name arg result)
  141. (alist-cons 'action 'delete
  142. (alist-delete 'action result))))
  143. (option '(#\d "delete-generations") #f #t
  144. (lambda (opt name arg result)
  145. (if (and arg (store-path? arg))
  146. (begin
  147. (warning (G_ "'-d' as an alias for '--delete' \
  148. is deprecated; use '-D'~%"))
  149. `((action . delete)
  150. (argument . ,arg)
  151. (alist-delete 'action result)))
  152. (begin
  153. (when (and arg (not (string->duration arg)))
  154. (leave (G_ "~s does not denote a duration~%")
  155. arg))
  156. (alist-cons 'delete-generations arg result)))))
  157. (option '("optimize") #f #f
  158. (lambda (opt name arg result)
  159. (alist-cons 'action 'optimize
  160. (alist-delete 'action result))))
  161. (option '("verify") #f #t
  162. (lambda (opt name arg result)
  163. (let ((options (argument->verify-options arg)))
  164. (alist-cons 'action 'verify
  165. (alist-cons 'verify-options options
  166. (alist-delete 'action
  167. result))))))
  168. (option '("list-roots") #f #f
  169. (lambda (opt name arg result)
  170. (alist-cons 'action 'list-roots
  171. (alist-delete 'action result))))
  172. (option '("list-busy") #f #f
  173. (lambda (opt name arg result)
  174. (alist-cons 'action 'list-busy
  175. (alist-delete 'action result))))
  176. (option '("list-dead") #f #f
  177. (lambda (opt name arg result)
  178. (alist-cons 'action 'list-dead
  179. (alist-delete 'action result))))
  180. (option '("list-live") #f #f
  181. (lambda (opt name arg result)
  182. (alist-cons 'action 'list-live
  183. (alist-delete 'action result))))
  184. (option '("references") #f #f
  185. (lambda (opt name arg result)
  186. (alist-cons 'action 'list-references
  187. (alist-delete 'action result))))
  188. (option '(#\R "requisites") #f #f
  189. (lambda (opt name arg result)
  190. (alist-cons 'action 'list-requisites
  191. (alist-delete 'action result))))
  192. (option '("referrers") #f #f
  193. (lambda (opt name arg result)
  194. (alist-cons 'action 'list-referrers
  195. (alist-delete 'action result))))
  196. (option '("derivers") #f #f
  197. (lambda (opt name arg result)
  198. (alist-cons 'action 'list-derivers
  199. (alist-delete 'action result))))
  200. (option '("list-failures") #f #f
  201. (lambda (opt name arg result)
  202. (alist-cons 'action 'list-failures
  203. (alist-delete 'action result))))
  204. (option '("clear-failures") #f #f
  205. (lambda (opt name arg result)
  206. (alist-cons 'action 'clear-failures
  207. (alist-delete 'action result))))))
  208. ;;;
  209. ;;; Entry point.
  210. ;;;
  211. (define-command (guix-gc . args)
  212. (synopsis "invoke the garbage collector")
  213. (define (parse-options)
  214. ;; Return the alist of option values.
  215. (parse-command-line args %options (list %default-options)
  216. #:build-options? #f))
  217. (define (symlink-target file)
  218. (let ((s (false-if-exception (lstat file))))
  219. (if (and s (eq? 'symlink (stat:type s)))
  220. (symlink-target (readlink file))
  221. file)))
  222. (define (store-directory file)
  223. ;; Return the store directory that holds FILE if it's in the store,
  224. ;; otherwise return FILE.
  225. (or (and=> (string-match (string-append "^" (regexp-quote (%store-prefix))
  226. "/([^/]+)")
  227. file)
  228. (compose (cut string-append (%store-prefix) "/" <>)
  229. (cut match:substring <> 1)))
  230. file))
  231. (define (ensure-free-space store space)
  232. ;; Attempt to have at least SPACE bytes available in STORE.
  233. (let ((free (free-disk-space (%store-prefix))))
  234. (if (> free space)
  235. (info (G_ "already ~h MiBs available on ~a, nothing to do~%")
  236. (/ free 1024. 1024.) (%store-prefix))
  237. (let ((to-free (- space free)))
  238. (info (G_ "freeing ~h MiBs~%") (/ to-free 1024. 1024.))
  239. (collect-garbage store to-free)))))
  240. (define (delete-generations store pattern)
  241. ;; Delete the generations matching PATTERN of all the user's profiles.
  242. (let ((profiles (delete-duplicates
  243. (filter-map (lambda (root)
  244. (and (or (zero? (getuid))
  245. (user-owned? root))
  246. (or (generation-profile root)
  247. (home-generation-base root))))
  248. (gc-roots)))))
  249. (for-each (lambda (profile)
  250. (delete-old-generations store profile pattern))
  251. profiles)))
  252. (define (list-roots)
  253. ;; List all the user-owned GC roots.
  254. (let ((roots (filter (if (zero? (getuid)) (const #t) user-owned?)
  255. (gc-roots))))
  256. (for-each (lambda (root)
  257. (display root)
  258. (newline))
  259. roots)))
  260. (define (list-busy)
  261. ;; List store items used by running processes.
  262. (for-each (lambda (item)
  263. (display item) (newline))
  264. (busy-store-items)))
  265. (with-error-handling
  266. (let* ((opts (parse-options))
  267. (store (open-connection))
  268. (paths (filter-map (match-lambda
  269. (('argument . arg) arg)
  270. (_ #f))
  271. opts)))
  272. (define (assert-no-extra-arguments)
  273. (unless (null? paths)
  274. (leave (G_ "extraneous arguments: ~{~a ~}~%") paths)))
  275. (define (list-relatives relatives)
  276. (for-each (compose (lambda (path)
  277. (for-each (cut simple-format #t "~a~%" <>)
  278. (relatives store path)))
  279. store-directory
  280. symlink-target)
  281. paths))
  282. (case (assoc-ref opts 'action)
  283. ((collect-garbage)
  284. (assert-no-extra-arguments)
  285. (let ((min-freed (assoc-ref opts 'min-freed))
  286. (free-space (assoc-ref opts 'free-space)))
  287. (match (assq 'delete-generations opts)
  288. (#f #t)
  289. ((_ . pattern)
  290. (delete-generations store pattern)))
  291. (cond
  292. (free-space
  293. (ensure-free-space store free-space))
  294. (min-freed
  295. (let-values (((paths freed) (collect-garbage store min-freed)))
  296. (info (G_ "freed ~h MiBs~%") (/ freed 1024. 1024.))))
  297. (else
  298. (let-values (((paths freed) (collect-garbage store)))
  299. (info (G_ "freed ~h MiBs~%") (/ freed 1024. 1024.)))))))
  300. ((list-roots)
  301. (assert-no-extra-arguments)
  302. (list-roots))
  303. ((list-busy)
  304. (assert-no-extra-arguments)
  305. (list-busy))
  306. ((delete)
  307. (delete-paths store (map direct-store-path paths)))
  308. ((list-references)
  309. (list-relatives references))
  310. ((list-requisites)
  311. (list-relatives (lambda (store item)
  312. (requisites store (list item)))))
  313. ((list-referrers)
  314. (list-relatives referrers))
  315. ((list-derivers)
  316. (list-relatives valid-derivers))
  317. ((optimize)
  318. (assert-no-extra-arguments)
  319. (optimize-store store))
  320. ((verify)
  321. (assert-no-extra-arguments)
  322. (let ((options (assoc-ref opts 'verify-options)))
  323. (exit
  324. (verify-store store
  325. #:check-contents? (memq 'contents options)
  326. #:repair? (memq 'repair options)))))
  327. ((list-failures)
  328. (for-each (cut simple-format #t "~a~%" <>)
  329. (query-failed-paths store)))
  330. ((clear-failures)
  331. (clear-failed-paths store (map direct-store-path paths)))
  332. ((list-dead)
  333. (for-each (cut simple-format #t "~a~%" <>)
  334. (dead-paths store)))
  335. ((list-live)
  336. (for-each (cut simple-format #t "~a~%" <>)
  337. (live-paths store)))))))