gc.scm 14 KB

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