{"id":184,"date":"2020-07-19T11:35:03","date_gmt":"2020-07-19T16:35:03","guid":{"rendered":"https:\/\/mtu.net\/~jpschewe\/blog\/?p=184"},"modified":"2020-07-19T11:35:03","modified_gmt":"2020-07-19T16:35:03","slug":"tracking-packages-installed","status":"publish","type":"post","link":"https:\/\/mtu.net\/~jpschewe\/blog\/2020\/07\/tracking-packages-installed\/","title":{"rendered":"Tracking packages installed"},"content":{"rendered":"\n<p>To help with restores or migration to another piece of hardware I find it useful to keep track of which packages are installed on my Linux systems. This isn&#8217;t very difficult, but it has taken a bit of experimenting to come up with with something that works fairly well and is automated. <\/p>\n\n\n\n<p>Create in \/etc\/systemd\/system\/status-email-root@.service. This is a helper service for sending emails on service failures.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;Unit]\nDescription=status email for %i to Jon\n\n&#91;Service]\nType=oneshot\nExecStart=\/usr\/local\/sbin\/systemd-email.sh root %i\n<\/code><\/pre>\n\n\n\n<p>\/usr\/local\/sbin\/systemd-email.sh looks like this<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/sh\n\ndebug() { ! \"${log_debug-false}\" || log \"DEBUG: $*\" >&amp;2; }\nlog() { printf '%s\\n' \"$*\"; }\nwarn() { log \"WARNING: $*\" >&amp;2; }\nerror() { log \"ERROR: $*\" >&amp;2; }\nfatal() { error \"$*\"; exit 1; }\ntry() { \"$@\" || fatal \"'$@' failed\"; }\n\nmydir=$(cd \"$(dirname \"$0\")\" &amp;&amp; pwd -L) || fatal \"Unable to determine script directory\"\n\n\n\/usr\/sbin\/sendmail -t &lt;&lt;ERRMAIL\nTo: $1\nFrom: systemd &lt;root@$HOSTNAME>\nSubject: $2\nContent-Transfer-Encoding: 8bit\nContent-Type: text\/plain; charset=UTF-8\n\n$(systemctl status --full \"$2\")\nERRMAIL<\/code><\/pre>\n\n\n\n<p>Create in \/etc\/systemd\/system\/track-installed-packages.service with the content. Note the &#8220;showmanual&#8221; argument to &#8220;apt-mark&#8221;. This makes sure to only output the packages that were manually installed and not include those that were installed as dependencies. This keeps the list short and if dependencies change later keeps from installed unneeded packages later.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;Unit]\nDescription=track installed packages\nOnFailure=status-email-root@%n.service\n\n&#91;Service]\nType=oneshot\nExecStart=\/usr\/bin\/apt-mark showmanual\nStandardOutput=file:\/home\/installed-packages.txt<\/code><\/pre>\n\n\n\n<p>Now create \/etc\/systemd\/system\/track-installed-packages.timer<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;Unit]\nDescription=track installed packages daily\n\n&#91;Timer]\nOnCalendar=daily\nPersistent=true\n\n&#91;Install]\nWantedBy=timers.target<\/code><\/pre>\n\n\n\n<p>Now enable the timer with<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>systemctl daemon-reload\nsystemctl enable track-installed-packages.timer\nsystemctl start track-installed-packages.timer<\/code><\/pre>\n\n\n\n<p>Now if you backup \/home, you&#8217;ll always have the most recent list of installed packages.<\/p>\n\n\n\n<p>I have a similar pair of systemd files for snaps that calls &#8220;snap list&#8221; and outputs to &#8220;\/home\/snap-packages.txt&#8221;.  Snap doesn&#8217;t appear to have an option to specify only manually installed snaps. This may also error out if there are no snaps installed.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>To help with restores or migration to another piece of hardware I find it useful to keep track of which packages are installed on my Linux systems. This isn&#8217;t very difficult, but it has taken a bit of experimenting to come up with with something that works fairly well and is automated. Create in \/etc\/systemd\/system\/status-email-root@.service. &hellip; <a href=\"https:\/\/mtu.net\/~jpschewe\/blog\/2020\/07\/tracking-packages-installed\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Tracking packages installed<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[],"class_list":["post-184","post","type-post","status-publish","format-standard","hentry","category-tech-tips"],"_links":{"self":[{"href":"https:\/\/mtu.net\/~jpschewe\/blog\/wp-json\/wp\/v2\/posts\/184","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mtu.net\/~jpschewe\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mtu.net\/~jpschewe\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mtu.net\/~jpschewe\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mtu.net\/~jpschewe\/blog\/wp-json\/wp\/v2\/comments?post=184"}],"version-history":[{"count":1,"href":"https:\/\/mtu.net\/~jpschewe\/blog\/wp-json\/wp\/v2\/posts\/184\/revisions"}],"predecessor-version":[{"id":185,"href":"https:\/\/mtu.net\/~jpschewe\/blog\/wp-json\/wp\/v2\/posts\/184\/revisions\/185"}],"wp:attachment":[{"href":"https:\/\/mtu.net\/~jpschewe\/blog\/wp-json\/wp\/v2\/media?parent=184"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mtu.net\/~jpschewe\/blog\/wp-json\/wp\/v2\/categories?post=184"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mtu.net\/~jpschewe\/blog\/wp-json\/wp\/v2\/tags?post=184"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}