<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title></title>
    <description>A place for my random thoughts about software</description>
    <link>https://tookmund.com/</link>
    <atom:link href="https://tookmund.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Mon, 11 Nov 2024 21:01:46 +0000</pubDate>
    <lastBuildDate>Mon, 11 Nov 2024 21:01:46 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Linux&apos;s Bedtime Routine</title>
        <description>&lt;p&gt;How does Linux move from an awake machine to a hibernating one?
How does it then manage to restore all state?
These questions led me to read way too much C in trying to figure out
how this particular hardware/software boundary is navigated.&lt;/p&gt;

&lt;p&gt;This investigation will be split into a few parts, with the first one going
from invocation of hibernation to synchronizing all filesystems to disk.&lt;/p&gt;

&lt;p&gt;This article has been written using Linux version 6.9.9,
the source of which can be found in many places, but can be navigated
easily through the Bootlin Elixir Cross-Referencer:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source&quot;&gt;https://elixir.bootlin.com/linux/v6.9.9/source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each code snippet will begin with a link to the above giving
the file path and the line number of the beginning of the snippet.&lt;/p&gt;

&lt;h2 id=&quot;a-starting-point-for-investigation-syspowerstate-and-syspowerdisk&quot;&gt;A Starting Point for Investigation: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/sys/power/state&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/sys/power/disk&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;These two system files exist to &lt;a href=&quot;https://www.kernel.org/doc/html/latest/power/basic-pm-debugging.html&quot;&gt;allow debugging of hibernation&lt;/a&gt;,
and thus control the exact state used directly.
Writing specific values to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state&lt;/code&gt; file controls the exact sleep mode used
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disk&lt;/code&gt; controls the specific hibernation mode&lt;sup id=&quot;fnref:hibermode&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:hibermode&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;This is extremely handy as an entry point to understand how these systems work,
since we can just follow what happens when they are written to.&lt;/p&gt;

&lt;h3 id=&quot;show-and-store-functions&quot;&gt;Show and Store Functions&lt;/h3&gt;
&lt;p&gt;These two files are defined using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;power_attr&lt;/code&gt; macro:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/power.h#L80&quot;&gt;kernel/power/power.h:80&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define power_attr(_name) \
static struct kobj_attribute _name##_attr = {   \
    .attr   = {             \
        .name = __stringify(_name), \
        .mode = 0644,           \
    },                  \
    .show   = _name##_show,         \
    .store  = _name##_store,        \
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;show&lt;/code&gt; is called on reads and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;store&lt;/code&gt; on writes.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_show&lt;/code&gt; is a little boring for our purposes, as it just prints all the
available sleep states.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/main.c#L657&quot;&gt;kernel/power/main.c:657&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 * state - control system sleep states.
 *
 * show() returns available sleep state labels, which may be &quot;mem&quot;, &quot;standby&quot;,
 * &quot;freeze&quot; and &quot;disk&quot; (hibernation).
 * See Documentation/admin-guide/pm/sleep-states.rst for a description of
 * what they mean.
 *
 * store() accepts one of those strings, translates it into the proper
 * enumerated value, and initiates a suspend transition.
 */
static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
			  char *buf)
{
	char *s = buf;
#ifdef CONFIG_SUSPEND
	suspend_state_t i;

	for (i = PM_SUSPEND_MIN; i &amp;lt; PM_SUSPEND_MAX; i++)
		if (pm_states[i])
			s += sprintf(s,&quot;%s &quot;, pm_states[i]);

#endif
	if (hibernation_available())
		s += sprintf(s, &quot;disk &quot;);
	if (s != buf)
		/* convert the last space to a newline */
		*(s-1) = &apos;\n&apos;;
	return (s - buf);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state_store&lt;/code&gt;, however, provides our entry point.
If the string “disk” is written to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state&lt;/code&gt; file, it calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate()&lt;/code&gt;.
This is our entry point.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/main.c#L715&quot;&gt;kernel/power/main.c:715&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
			   const char *buf, size_t n)
{
	suspend_state_t state;
	int error;

	error = pm_autosleep_lock();
	if (error)
		return error;

	if (pm_autosleep_state() &amp;gt; PM_SUSPEND_ON) {
		error = -EBUSY;
		goto out;
	}

	state = decode_state(buf, n);
	if (state &amp;lt; PM_SUSPEND_MAX) {
		if (state == PM_SUSPEND_MEM)
			state = mem_sleep_current;

		error = pm_suspend(state);
	} else if (state == PM_SUSPEND_MAX) {
		error = hibernate();
	} else {
		error = -EINVAL;
	}

 out:
	pm_autosleep_unlock();
	return error ? error : n;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/main.c#L688&quot;&gt;kernel/power/main.c:688&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static suspend_state_t decode_state(const char *buf, size_t n)
{
#ifdef CONFIG_SUSPEND
	suspend_state_t state;
#endif
	char *p;
	int len;

	p = memchr(buf, &apos;\n&apos;, n);
	len = p ? p - buf : n;

	/* Check hibernation first. */
	if (len == 4 &amp;amp;&amp;amp; str_has_prefix(buf, &quot;disk&quot;))
		return PM_SUSPEND_MAX;

#ifdef CONFIG_SUSPEND
	for (state = PM_SUSPEND_MIN; state &amp;lt; PM_SUSPEND_MAX; state++) {
		const char *label = pm_states[state];

		if (label &amp;amp;&amp;amp; len == strlen(label) &amp;amp;&amp;amp; !strncmp(buf, label, len))
			return state;
	}
#endif

	return PM_SUSPEND_ON;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Could we have figured this out just via function names?
Sure, but this way we know for sure that nothing else is happening before this
function is called.&lt;/p&gt;

&lt;h3 id=&quot;autosleep&quot;&gt;Autosleep&lt;/h3&gt;

&lt;p&gt;Our first detour is into the autosleep system.
When checking the state above, you may notice that
the kernel grabs the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pm_autosleep_lock&lt;/code&gt; before checking the current
state.&lt;/p&gt;

&lt;p&gt;autosleep is a mechanism &lt;a href=&quot;https://lwn.net/Articles/479841/&quot;&gt;originally from Android&lt;/a&gt;
that sends the entire system to either suspend or hibernate whenever it is
not actively working on anything.&lt;/p&gt;

&lt;p&gt;This is not enabled for most desktop configurations, since it’s primarily
for mobile systems and inverts the standard suspend and hibernate interactions.&lt;/p&gt;

&lt;p&gt;This system is implemented as a workqueue&lt;sup id=&quot;fnref:workqueue&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:workqueue&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;
that checks the current number of wakeup events, processes and drivers that
need to run&lt;sup id=&quot;fnref:wakeupevent&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:wakeupevent&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, and if there aren’t any, then the system is put
into the autosleep state, typically suspend. However, it could be hibernate if
configured that way via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/sys/power/autosleep&lt;/code&gt; in a similar manner to
using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/sys/power/state&lt;/code&gt; to manually enable hibernation.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/main.c#L841&quot;&gt;kernel/power/main.c:841&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static ssize_t autosleep_store(struct kobject *kobj,
			       struct kobj_attribute *attr,
			       const char *buf, size_t n)
{
	suspend_state_t state = decode_state(buf, n);
	int error;

	if (state == PM_SUSPEND_ON
	    &amp;amp;&amp;amp; strcmp(buf, &quot;off&quot;) &amp;amp;&amp;amp; strcmp(buf, &quot;off\n&quot;))
		return -EINVAL;

	if (state == PM_SUSPEND_MEM)
		state = mem_sleep_current;

	error = pm_autosleep_set_state(state);
	return error ? error : n;
}

power_attr(autosleep);
#endif /* CONFIG_PM_AUTOSLEEP */
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/autosleep.c#L24&quot;&gt;kernel/power/autosleep.c:24&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static DEFINE_MUTEX(autosleep_lock);
static struct wakeup_source *autosleep_ws;

static void try_to_suspend(struct work_struct *work)
{
	unsigned int initial_count, final_count;

	if (!pm_get_wakeup_count(&amp;amp;initial_count, true))
		goto out;

	mutex_lock(&amp;amp;autosleep_lock);

	if (!pm_save_wakeup_count(initial_count) ||
		system_state != SYSTEM_RUNNING) {
		mutex_unlock(&amp;amp;autosleep_lock);
		goto out;
	}

	if (autosleep_state == PM_SUSPEND_ON) {
		mutex_unlock(&amp;amp;autosleep_lock);
		return;
	}
	if (autosleep_state &amp;gt;= PM_SUSPEND_MAX)
		hibernate();
	else
		pm_suspend(autosleep_state);

	mutex_unlock(&amp;amp;autosleep_lock);

	if (!pm_get_wakeup_count(&amp;amp;final_count, false))
		goto out;

	/*
	 * If the wakeup occurred for an unknown reason, wait to prevent the
	 * system from trying to suspend and waking up in a tight loop.
	 */
	if (final_count == initial_count)
		schedule_timeout_uninterruptible(HZ / 2);

 out:
	queue_up_suspend_work();
}

static DECLARE_WORK(suspend_work, try_to_suspend);

void queue_up_suspend_work(void)
{
	if (autosleep_state &amp;gt; PM_SUSPEND_ON)
		queue_work(autosleep_wq, &amp;amp;suspend_work);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-steps-of-hibernation&quot;&gt;The Steps of Hibernation&lt;/h2&gt;

&lt;h3 id=&quot;hibernation-kernel-config&quot;&gt;Hibernation Kernel Config&lt;/h3&gt;

&lt;p&gt;It’s important to note that most of the hibernate-specific functions below
do nothing unless you’ve defined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_HIBERNATION&lt;/code&gt; in your Kconfig&lt;sup id=&quot;fnref:kconfig&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:kconfig&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.
As an example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate&lt;/code&gt; itself is defined as the following if
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_HIBERNATE&lt;/code&gt; is not set.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/include/linux/suspend.h#L407&quot;&gt;include/linux/suspend.h:407&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static inline int hibernate(void) { return -ENOSYS; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;check-if-hibernation-is-available&quot;&gt;Check if Hibernation is Available&lt;/h3&gt;
&lt;p&gt;We begin by confirming that we actually can perform hibernation,
via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernation_available&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/hibernate.c#L742&quot;&gt;kernel/power/hibernate.c:742&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if (!hibernation_available()) {
	pm_pr_dbg(&quot;Hibernation not available.\n&quot;);
	return -EPERM;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/hibernate.c#L92&quot;&gt;kernel/power/hibernate.c:92&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bool hibernation_available(void)
{
	return nohibernate == 0 &amp;amp;&amp;amp;
		!security_locked_down(LOCKDOWN_HIBERNATION) &amp;amp;&amp;amp;
		!secretmem_active() &amp;amp;&amp;amp; !cxl_mem_active();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nohibernate&lt;/code&gt; is controlled by the kernel command line, it’s set via
either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nohibernate&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate=no&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;security_locked_down&lt;/code&gt; is a hook for Linux Security Modules to prevent
hibernation. This is used to prevent hibernating to an unencrypted storage
device, as specified in the manual page
&lt;a href=&quot;https://man7.org/linux/man-pages/man7/kernel_lockdown.7.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel_lockdown(7)&lt;/code&gt;&lt;/a&gt;.
Interestingly, either level of lockdown, integrity or confidentiality,
locks down hibernation because with the ability to hibernate you can extract
bascially anything from memory and even reboot into a modified kernel image.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secretmem_active&lt;/code&gt; checks whether there is any active use of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memfd_secret&lt;/code&gt;, and if so it prevents hibernation.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memfd_secret&lt;/code&gt; returns a file descriptor that can be mapped into a process
but is specifically unmapped from the kernel’s memory space.
Hibernating with memory that not even the kernel is supposed to
access would expose that memory to whoever could access the hibernation image.
This particular feature of secret memory was apparently
&lt;a href=&quot;https://lwn.net/Articles/865256/&quot;&gt;controversial&lt;/a&gt;, though not as
controversial as performance concerns around fragmentation when unmapping
kernel memory
(&lt;a href=&quot;https://lwn.net/Articles/865256/&quot;&gt;which did not end up being a real problem&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cxl_mem_active&lt;/code&gt; just checks whether any CXL memory is active.
A full explanation is provided in the
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9ea4dcf49878bb9546b8fa9319dcbdc9b7ee20f8&quot;&gt;commit introducing this check&lt;/a&gt;
but there’s also a shortened explanation from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cxl_mem_probe&lt;/code&gt; that
sets the relevant flag when initializing a CXL memory device.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/drivers/cxl/mem.c#L186&quot;&gt;drivers/cxl/mem.c:186&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;* The kernel may be operating out of CXL memory on this device,
* there is no spec defined way to determine whether this device
* preserves contents over suspend, and there is no simple way
* to arrange for the suspend image to avoid CXL memory which
* would setup a circular dependency between PCI resume and save
* state restoration.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;check-compression&quot;&gt;Check Compression&lt;/h3&gt;

&lt;p&gt;The next check is for whether compression support is enabled, and if so
whether the requested algorithm is enabled.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/hibernate.c#L747&quot;&gt;kernel/power/hibernate.c:747&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 * Query for the compression algorithm support if compression is enabled.
 */
if (!nocompress) {
	strscpy(hib_comp_algo, hibernate_compressor, sizeof(hib_comp_algo));
	if (crypto_has_comp(hib_comp_algo, 0, 0) != 1) {
		pr_err(&quot;%s compression is not available\n&quot;, hib_comp_algo);
		return -EOPNOTSUPP;
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nocompress&lt;/code&gt; flag is set via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate&lt;/code&gt; command line parameter,
setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate=nocompress&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If compression is enabled, then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate_compressor&lt;/code&gt; is copied to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hib_comp_algo&lt;/code&gt;. This synchronizes the current requested compression
setting (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate_compressor&lt;/code&gt;) with the current compression setting
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hib_comp_algo&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Both values are character arrays of size &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CRYPTO_MAX_ALG_NAME&lt;/code&gt;
(128 in this kernel).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/hibernate.c#L50&quot;&gt;kernel/power/hibernate.c:50&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static char hibernate_compressor[CRYPTO_MAX_ALG_NAME] = CONFIG_HIBERNATION_DEF_COMP;

/*
 * Compression/decompression algorithm to be used while saving/loading
 * image to/from disk. This would later be used in &apos;kernel/power/swap.c&apos;
 * to allocate comp streams.
 */
char hib_comp_algo[CRYPTO_MAX_ALG_NAME];
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate_compressor&lt;/code&gt; defaults to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lzo&lt;/code&gt; if that algorithm is enabled, otherwise to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lz4&lt;/code&gt; if
enabled&lt;sup id=&quot;fnref:choicedefault&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:choicedefault&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;. It can be overwritten using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate.compressor&lt;/code&gt; setting to
either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lzo&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lz4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/Kconfig#L95&quot;&gt;kernel/power/Kconfig:95&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;choice
	prompt &quot;Default compressor&quot;
	default HIBERNATION_COMP_LZO
	depends on HIBERNATION

config HIBERNATION_COMP_LZO
	bool &quot;lzo&quot;
	depends on CRYPTO_LZO

config HIBERNATION_COMP_LZ4
	bool &quot;lz4&quot;
	depends on CRYPTO_LZ4

endchoice

config HIBERNATION_DEF_COMP
	string
	default &quot;lzo&quot; if HIBERNATION_COMP_LZO
	default &quot;lz4&quot; if HIBERNATION_COMP_LZ4
	help
	  Default compressor to be used for hibernation.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/hibernate.c#L1425&quot;&gt;kernel/power/hibernate.c:1425&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static const char * const comp_alg_enabled[] = {
#if IS_ENABLED(CONFIG_CRYPTO_LZO)
	COMPRESSION_ALGO_LZO,
#endif
#if IS_ENABLED(CONFIG_CRYPTO_LZ4)
	COMPRESSION_ALGO_LZ4,
#endif
};

static int hibernate_compressor_param_set(const char *compressor,
		const struct kernel_param *kp)
{
	unsigned int sleep_flags;
	int index, ret;

	sleep_flags = lock_system_sleep();

	index = sysfs_match_string(comp_alg_enabled, compressor);
	if (index &amp;gt;= 0) {
		ret = param_set_copystring(comp_alg_enabled[index], kp);
		if (!ret)
			strscpy(hib_comp_algo, comp_alg_enabled[index],
				sizeof(hib_comp_algo));
	} else {
		ret = index;
	}

	unlock_system_sleep(sleep_flags);

	if (ret)
		pr_debug(&quot;Cannot set specified compressor %s\n&quot;,
			 compressor);

	return ret;
}
static const struct kernel_param_ops hibernate_compressor_param_ops = {
	.set    = hibernate_compressor_param_set,
	.get    = param_get_string,
};

static struct kparam_string hibernate_compressor_param_string = {
	.maxlen = sizeof(hibernate_compressor),
	.string = hibernate_compressor,
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We then check whether the requested algorithm is supported via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;crypto_has_comp&lt;/code&gt;.
If not, we bail out of the whole operation with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EOPNOTSUPP&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As part of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;crypto_has_comp&lt;/code&gt; we perform any needed initialization of the
algorithm, loading kernel modules and running initialization code as needed&lt;sup id=&quot;fnref:larval&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:larval&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h3 id=&quot;grab-locks&quot;&gt;Grab Locks&lt;/h3&gt;

&lt;p&gt;The next step is to grab the sleep and hibernation locks via
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lock_system_sleep&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate_acquire&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/hibernate.c#L758&quot;&gt;kernel/power/hibernate.c:758&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sleep_flags = lock_system_sleep();
/* The snapshot device should not be opened while we&apos;re running */
if (!hibernate_acquire()) {
	error = -EBUSY;
	goto Unlock;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;First, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lock_system_sleep&lt;/code&gt; marks the current thread as not freezable, which
will be important later&lt;sup id=&quot;fnref:procfreeze&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:procfreeze&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;. It then grabs the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system_transistion_mutex&lt;/code&gt;,
which locks taking snapshots or modifying how they are taken,
resuming from a hibernation image, entering any suspend state, or rebooting.&lt;/p&gt;

&lt;h4 id=&quot;the-gfp-mask&quot;&gt;The GFP Mask&lt;/h4&gt;
&lt;p&gt;The kernel also issues a warning if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gfp&lt;/code&gt; mask is changed via either
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pm_restore_gfp_mask&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pm_restrict_gfp_mask&lt;/code&gt;
without holding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system_transistion_mutex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;GFP flags tell the kernel how it is permitted to handle a request for memory.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/include/linux/gfp_types.h#L12&quot;&gt;include/linux/gfp_types.h:12&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; * GFP flags are commonly used throughout Linux to indicate how memory
 * should be allocated.  The GFP acronym stands for get_free_pages(),
 * the underlying memory allocation function.  Not every GFP flag is
 * supported by every function which may allocate memory.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the case of hibernation specifically we care about the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IO&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FS&lt;/code&gt; flags,
which are reclaim operators, ways the system is permitted to attempt to free
up memory in order to satisfy a specific request for memory.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/include/linux/gfp_types.h#L176&quot;&gt;include/linux/gfp_types.h:176&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; * Reclaim modifiers
 * -----------------
 * Please note that all the following flags are only applicable to sleepable
 * allocations (e.g. %GFP_NOWAIT and %GFP_ATOMIC will ignore them).
 *
 * %__GFP_IO can start physical IO.
 *
 * %__GFP_FS can call down to the low-level FS. Clearing the flag avoids the
 * allocator recursing into the filesystem which might already be holding
 * locks.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gfp_allowed_mask&lt;/code&gt; sets which flags are permitted to be set at the current time.&lt;/p&gt;

&lt;p&gt;As the comment below outlines, preventing these flags from being set
avoids situations where the kernel needs to do I/O to allocate memory
(e.g. read/writing swap&lt;sup id=&quot;fnref:swap&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:swap&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;) but the
devices it needs to read/write to/from are not currently available.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/main.c#L24&quot;&gt;kernel/power/main.c:24&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 * The following functions are used by the suspend/hibernate code to temporarily
 * change gfp_allowed_mask in order to avoid using I/O during memory allocations
 * while devices are suspended.  To avoid races with the suspend/hibernate code,
 * they should always be called with system_transition_mutex held
 * (gfp_allowed_mask also should only be modified with system_transition_mutex
 * held, unless the suspend/hibernate code is guaranteed not to run in parallel
 * with that modification).
 */
static gfp_t saved_gfp_mask;

void pm_restore_gfp_mask(void)
{
	WARN_ON(!mutex_is_locked(&amp;amp;system_transition_mutex));
	if (saved_gfp_mask) {
		gfp_allowed_mask = saved_gfp_mask;
		saved_gfp_mask = 0;
	}
}

void pm_restrict_gfp_mask(void)
{
	WARN_ON(!mutex_is_locked(&amp;amp;system_transition_mutex));
	WARN_ON(saved_gfp_mask);
	saved_gfp_mask = gfp_allowed_mask;
	gfp_allowed_mask &amp;amp;= ~(__GFP_IO | __GFP_FS);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;sleep-flags&quot;&gt;Sleep Flags&lt;/h4&gt;
&lt;p&gt;After grabbing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system_transition_mutex&lt;/code&gt; the kernel then returns and
captures the previous state of the threads flags in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sleep_flags&lt;/code&gt;.
This is used later to remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PF_NOFREEZE&lt;/code&gt; if it wasn’t previously set on the
current thread.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/main.c#L52&quot;&gt;kernel/power/main.c:52&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;unsigned int lock_system_sleep(void)
{
	unsigned int flags = current-&amp;gt;flags;
	current-&amp;gt;flags |= PF_NOFREEZE;
	mutex_lock(&amp;amp;system_transition_mutex);
	return flags;
}
EXPORT_SYMBOL_GPL(lock_system_sleep);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/include/linux/sched.h#L1633&quot;&gt;include/linux/sched.h:1633&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define PF_NOFREEZE		0x00008000	/* This thread should not be frozen */
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then we grab the hibernate-specific semaphore to ensure no one can open a
snapshot or resume from it while we perform hibernation.
Additionally this lock is used to prevent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate_quiet_exec&lt;/code&gt;,
which is used by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvdimm&lt;/code&gt; driver to active its firmware with all
processes and devices frozen, ensuring it is the only thing running at that
time&lt;sup id=&quot;fnref:nvdimm&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:nvdimm&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/hibernate.c#L82&quot;&gt;kernel/power/hibernate.c:82&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bool hibernate_acquire(void)
{
	return atomic_add_unless(&amp;amp;hibernate_atomic, -1, 0);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;prepare-console&quot;&gt;Prepare Console&lt;/h3&gt;
&lt;p&gt;The kernel next calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pm_prepare_console&lt;/code&gt;.
This function only does anything if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_VT_CONSOLE_SLEEP&lt;/code&gt; has been set.&lt;/p&gt;

&lt;p&gt;This prepares the virtual terminal for a suspend state, switching away to
a console used only for the suspend state if needed.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/console.c#L130&quot;&gt;kernel/power/console.c:130&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void pm_prepare_console(void)
{
	if (!pm_vt_switch())
		return;

	orig_fgconsole = vt_move_to_console(SUSPEND_CONSOLE, 1);
	if (orig_fgconsole &amp;lt; 0)
		return;

	orig_kmsg = vt_kmsg_redirect(SUSPEND_CONSOLE);
	return;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first thing is to check whether we actually need to switch the VT&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/console.c#L94&quot;&gt;kernel/power/console.c:94&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 * There are three cases when a VT switch on suspend/resume are required:
 *   1) no driver has indicated a requirement one way or another, so preserve
 *      the old behavior
 *   2) console suspend is disabled, we want to see debug messages across
 *      suspend/resume
 *   3) any registered driver indicates it needs a VT switch
 *
 * If none of these conditions is present, meaning we have at least one driver
 * that doesn&apos;t need the switch, and none that do, we can avoid it to make
 * resume look a little prettier (and suspend too, but that&apos;s usually hidden,
 * e.g. when closing the lid on a laptop).
 */
static bool pm_vt_switch(void)
{
	struct pm_vt_switch *entry;
	bool ret = true;

	mutex_lock(&amp;amp;vt_switch_mutex);
	if (list_empty(&amp;amp;pm_vt_switch_list))
		goto out;

	if (!console_suspend_enabled)
		goto out;

	list_for_each_entry(entry, &amp;amp;pm_vt_switch_list, head) {
		if (entry-&amp;gt;required)
			goto out;
	}

	ret = false;
out:
	mutex_unlock(&amp;amp;vt_switch_mutex);
	return ret;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There is an explanation of the conditions under which a switch is performed
in the comment above the function, but we’ll also walk through the steps here.&lt;/p&gt;

&lt;p&gt;Firstly we grab the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vt_switch_mutex&lt;/code&gt; to ensure nothing will modify the list
while we’re looking at it.&lt;/p&gt;

&lt;p&gt;We then examine the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pm_vt_switch_list&lt;/code&gt;.
This list is used to indicate the drivers that require a switch during suspend.
They register this requirement, or the lack thereof, via
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pm_vt_switch_required&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/console.c#L31&quot;&gt;kernel/power/console.c:31&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/**
 * pm_vt_switch_required - indicate VT switch at suspend requirements
 * @dev: device
 * @required: if true, caller needs VT switch at suspend/resume time
 *
 * The different console drivers may or may not require VT switches across
 * suspend/resume, depending on how they handle restoring video state and
 * what may be running.
 *
 * Drivers can indicate support for switchless suspend/resume, which can
 * save time and flicker, by using this routine and passing &apos;false&apos; as
 * the argument.  If any loaded driver needs VT switching, or the
 * no_console_suspend argument has been passed on the command line, VT
 * switches will occur.
 */
void pm_vt_switch_required(struct device *dev, bool required)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, we check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console_suspend_enabled&lt;/code&gt;. This is set to false
by the kernel parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;no_console_suspend&lt;/code&gt;, but defaults to true.&lt;/p&gt;

&lt;p&gt;Finally, if there are any entries in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pm_vt_switch_list&lt;/code&gt;, then we
check to see if any of them require a VT switch.&lt;/p&gt;

&lt;p&gt;Only if none of these conditions apply, then we return false.&lt;/p&gt;

&lt;p&gt;If a VT switch is in fact required, then we move first the currently active
virtual terminal/console&lt;sup id=&quot;fnref:console&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:console&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;10&lt;/a&gt;&lt;/sup&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vt_move_to_console&lt;/code&gt;)
and then the current location of kernel messages (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vt_kmsg_redirect&lt;/code&gt;)
to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SUSPEND_CONSOLE&lt;/code&gt;.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SUSPEND_CONSOLE&lt;/code&gt; is the last entry in the list of possible
consoles, and appears to just be a black hole to throw away messages.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/console.c#L16&quot;&gt;kernel/power/console.c:16&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define SUSPEND_CONSOLE	(MAX_NR_CONSOLES-1)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Interestingly, these are separate functions because you can use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TIOCL_SETKMSGREDIRECT&lt;/code&gt; (an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ioctl&lt;/code&gt;&lt;sup id=&quot;fnref:ioctl&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ioctl&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;) to send kernel messages to a specific virtual terminal,
but by default its the same as the currently active console.&lt;/p&gt;

&lt;p&gt;The locations of the previously active console and the previous kernel
messages location are stored in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;orig_fgconsole&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;orig_kmsg&lt;/code&gt;, to
restore the state of the console and kernel messages after the machine wakes
up again.
Interestingly, this means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;orig_fgconsole&lt;/code&gt; also ends up storing any errors,
so has to be checked to ensure it’s not less than zero before we try to do
anything with the kernel messages on both suspend and resume.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/drivers/tty/vt/vt_ioctl.c#L1268&quot;&gt;drivers/tty/vt/vt_ioctl.c:1268&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/* Perform a kernel triggered VT switch for suspend/resume */

static int disable_vt_switch;

int vt_move_to_console(unsigned int vt, int alloc)
{
	int prev;

	console_lock();
	/* Graphics mode - up to X */
	if (disable_vt_switch) {
		console_unlock();
		return 0;
	}
	prev = fg_console;

	if (alloc &amp;amp;&amp;amp; vc_allocate(vt)) {
		/* we can&apos;t have a free VC for now. Too bad,
		 * we don&apos;t want to mess the screen for now. */
		console_unlock();
		return -ENOSPC;
	}

	if (set_console(vt)) {
		/*
		 * We&apos;re unable to switch to the SUSPEND_CONSOLE.
		 * Let the calling function know so it can decide
		 * what to do.
		 */
		console_unlock();
		return -EIO;
	}
	console_unlock();
	if (vt_waitactive(vt + 1)) {
		pr_debug(&quot;Suspend: Can&apos;t switch VCs.&quot;);
		return -EINTR;
	}
	return prev;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unlike most other locking functions we’ve seen so far, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console_lock&lt;/code&gt;
needs to be careful to ensure nothing else is panicking and needs to
dump to the console before grabbing the semaphore for the console
and setting a couple flags.&lt;/p&gt;

&lt;h4 id=&quot;panics&quot;&gt;Panics&lt;/h4&gt;
&lt;p&gt;Panics are tracked via an atomic integer set to the id of the processor
currently panicking.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/printk/printk.c#L2649&quot;&gt;kernel/printk/printk.c:2649&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/**
 * console_lock - block the console subsystem from printing
 *
 * Acquires a lock which guarantees that no consoles will
 * be in or enter their write() callback.
 *
 * Can sleep, returns nothing.
 */
void console_lock(void)
{
	might_sleep();

	/* On panic, the console_lock must be left to the panic cpu. */
	while (other_cpu_in_panic())
		msleep(1000);

	down_console_sem();
	console_locked = 1;
	console_may_schedule = 1;
}
EXPORT_SYMBOL(console_lock);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/printk/printk.c#L362&quot;&gt;kernel/printk/printk.c:362&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 * Return true if a panic is in progress on a remote CPU.
 *
 * On true, the local CPU should immediately release any printing resources
 * that may be needed by the panic CPU.
 */
bool other_cpu_in_panic(void)
{
	return (panic_in_progress() &amp;amp;&amp;amp; !this_cpu_in_panic());
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/printk/printk.c#L345&quot;&gt;kernel/printk/printk.c:345&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static bool panic_in_progress(void)
{
	return unlikely(atomic_read(&amp;amp;panic_cpu) != PANIC_CPU_INVALID);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/printk/printk.c#L350&quot;&gt;kernel/printk/printk.c:350&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/* Return true if a panic is in progress on the current CPU. */
bool this_cpu_in_panic(void)
{
	/*
	 * We can use raw_smp_processor_id() here because it is impossible for
	 * the task to be migrated to the panic_cpu, or away from it. If
	 * panic_cpu has already been set, and we&apos;re not currently executing on
	 * that CPU, then we never will be.
	 */
	return unlikely(atomic_read(&amp;amp;panic_cpu) == raw_smp_processor_id());
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console_locked&lt;/code&gt; is a debug value, used to indicate that the lock should be
held, and our first indication that this whole virtual terminal system is
more complex than might initially be expected.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/printk/printk.c#L373&quot;&gt;kernel/printk/printk.c:373&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 * This is used for debugging the mess that is the VT code by
 * keeping track if we have the console semaphore held. It&apos;s
 * definitely not the perfect debug tool (we don&apos;t know if _WE_
 * hold it and are racing, but it helps tracking those weird code
 * paths in the console code where we end up in places I want
 * locked without the console semaphore held).
 */
static int console_locked;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console_may_schedule&lt;/code&gt; is used to see if we are permitted to sleep
and schedule other work while we hold this lock.
As we’ll see later, the virtual terminal subsystem is not re-entrant,
so there’s all sorts of hacks in here to ensure we don’t leave important
code sections that can’t be safely resumed.&lt;/p&gt;

&lt;h4 id=&quot;disable-vt-switch&quot;&gt;Disable VT Switch&lt;/h4&gt;
&lt;p&gt;As the comment below lays out, when another program is handling graphical
display anyway, there’s no need to do any of this, so the kernel provides
a switch to turn the whole thing off.
Interestingly, this appears to only be used by three drivers,
so the specific hardware support required must not be particularly common.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;drivers/gpu/drm/omapdrm/dss
drivers/video/fbdev/geode
drivers/video/fbdev/omap2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/drivers/tty/vt/vt_ioctl.c#L1308&quot;&gt;drivers/tty/vt/vt_ioctl.c:1308&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 * Normally during a suspend, we allocate a new console and switch to it.
 * When we resume, we switch back to the original console.  This switch
 * can be slow, so on systems where the framebuffer can handle restoration
 * of video registers anyways, there&apos;s little point in doing the console
 * switch.  This function allows you to disable it by passing it &apos;0&apos;.
 */
void pm_set_vt_switch(int do_switch)
{
	console_lock();
	disable_vt_switch = !do_switch;
	console_unlock();
}
EXPORT_SYMBOL(pm_set_vt_switch);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The rest of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vt_switch_console&lt;/code&gt; function is pretty normal,
however, simply allocating space if needed to create the requested
virtual terminal
and then setting the current virtual terminal via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set_console&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;virtual-terminal-set-console&quot;&gt;Virtual Terminal Set Console&lt;/h4&gt;
&lt;p&gt;With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set_console&lt;/code&gt;, we begin (as if we haven’t been already) to enter the
madness that is the virtual terminal subsystem.
As mentioned previously, modifications to its state must be made very
carefully, as other stuff happening at the same time could create complete
messes.&lt;/p&gt;

&lt;p&gt;All this to say, calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set_console&lt;/code&gt; does not actually perform any
work to change the state of the current console.
Instead it indicates what changes it wants and then schedules that work.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/drivers/tty/vt/vt.c#L3153&quot;&gt;drivers/tty/vt/vt.c:3153&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int set_console(int nr)
{
	struct vc_data *vc = vc_cons[fg_console].d;

	if (!vc_cons_allocated(nr) || vt_dont_switch ||
		(vc-&amp;gt;vt_mode.mode == VT_AUTO &amp;amp;&amp;amp; vc-&amp;gt;vc_mode == KD_GRAPHICS)) {

		/*
		 * Console switch will fail in console_callback() or
		 * change_console() so there is no point scheduling
		 * the callback
		 *
		 * Existing set_console() users don&apos;t check the return
		 * value so this shouldn&apos;t break anything
		 */
		return -EINVAL;
	}

	want_console = nr;
	schedule_console_callback();

	return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The check for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vc-&amp;gt;vc_mode == KD_GRAPHICS&lt;/code&gt; is where most end-user graphical
desktops will bail out of this change, as they’re in graphics mode and don’t
need to switch away to the suspend console.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vt_dont_switch&lt;/code&gt; is a flag used by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ioctl&lt;/code&gt;s&lt;sup id=&quot;fnref:ioctl:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ioctl&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;11&lt;/a&gt;&lt;/sup&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VT_LOCKSWITCH&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VT_UNLOCKSWITCH&lt;/code&gt; to prevent the system from switching virtual terminal
devices when the user has explicitly locked it.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VT_AUTO&lt;/code&gt; is a flag indicating that automatic virtual terminal switching is enabled&lt;sup id=&quot;fnref:vtauto&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:vtauto&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;12&lt;/a&gt;&lt;/sup&gt;,
and thus deliberate switching to a suspend terminal is not required.&lt;/p&gt;

&lt;p&gt;However, if you do run your machine from a virtual terminal, then we
indicate to the system that we want to change to the requested virtual terminal
via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;want_console&lt;/code&gt; variable
and schedule a callback via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;schedule_console_callback&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/drivers/tty/vt/vt.c#L315&quot;&gt;drivers/tty/vt/vt.c:315&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void schedule_console_callback(void)
{
	schedule_work(&amp;amp;console_work);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console_work&lt;/code&gt; is a workqueue&lt;sup id=&quot;fnref:workqueue:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:workqueue&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; that will execute the given task asynchronously.&lt;/p&gt;

&lt;h4 id=&quot;console-callback&quot;&gt;Console Callback&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/drivers/tty/vt/vt.c#L3109&quot;&gt;drivers/tty/vt/vt.c:3109&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 * This is the console switching callback.
 *
 * Doing console switching in a process context allows
 * us to do the switches asynchronously (needed when we want
 * to switch due to a keyboard interrupt).  Synchronization
 * with other console code and prevention of re-entrancy is
 * ensured with console_lock.
 */
static void console_callback(struct work_struct *ignored)
{
	console_lock();

	if (want_console &amp;gt;= 0) {
		if (want_console != fg_console &amp;amp;&amp;amp;
		    vc_cons_allocated(want_console)) {
			hide_cursor(vc_cons[fg_console].d);
			change_console(vc_cons[want_console].d);
			/* we only changed when the console had already
			   been allocated - a new console is not created
			   in an interrupt routine */
		}
		want_console = -1;
	}
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console_callback&lt;/code&gt; first looks to see if there is a console change wanted
via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;want_console&lt;/code&gt; and then changes to it if it’s not the current console and
has been allocated already.
We do first remove any cursor state with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hide_cursor&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/drivers/tty/vt/vt.c#L841&quot;&gt;drivers/tty/vt/vt.c:841&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static void hide_cursor(struct vc_data *vc)
{
	if (vc_is_sel(vc))
		clear_selection();

	vc-&amp;gt;vc_sw-&amp;gt;con_cursor(vc, false);
	hide_softcursor(vc);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A full dive into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tty&lt;/code&gt; driver is a task for another time, but this
should give a general sense of how this system interacts with hibernation.&lt;/p&gt;

&lt;h3 id=&quot;notify-power-management-call-chain&quot;&gt;Notify Power Management Call Chain&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/hibernate.c#L767&quot;&gt;kernel/power/hibernate.c:767&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pm_notifier_call_chain_robust(PM_HIBERNATION_PREPARE, PM_POST_HIBERNATION)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will call a chain of power management callbacks, passing first
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PM_HIBERNATION_PREPARE&lt;/code&gt; and then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PM_POST_HIBERNATION&lt;/code&gt; on startup or
on error with another callback.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/main.c#L98&quot;&gt;kernel/power/main.c:98&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int pm_notifier_call_chain_robust(unsigned long val_up, unsigned long val_down)
{
	int ret;

	ret = blocking_notifier_call_chain_robust(&amp;amp;pm_chain_head, val_up, val_down, NULL);

	return notifier_to_errno(ret);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The power management notifier is a blocking notifier chain, which means it
has the following properties.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/include/linux/notifier.h#L23&quot;&gt;include/linux/notifier.h:23&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; *	Blocking notifier chains: Chain callbacks run in process context.
 *		Callouts are allowed to block.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The callback chain is a linked list with each entry containing a priority
and a function to call. The function technically takes in a data value,
but it is always &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt; for the power management chain.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/include/linux/notifier.h#L49&quot;&gt;include/linux/notifier.h:49&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct notifier_block;

typedef	int (*notifier_fn_t)(struct notifier_block *nb,
			unsigned long action, void *data);

struct notifier_block {
	notifier_fn_t notifier_call;
	struct notifier_block __rcu *next;
	int priority;
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The head of the linked list is protected by a read-write semaphore.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/include/linux/notifier.h#L65&quot;&gt;include/linux/notifier.h:65&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct blocking_notifier_head {
	struct rw_semaphore rwsem;
	struct notifier_block __rcu *head;
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Because it is prioritized, appending to the list requires walking it until
an item with lower&lt;sup id=&quot;fnref:priority&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:priority&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;13&lt;/a&gt;&lt;/sup&gt; priority is found to insert the current item before.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/notifier.c#L252&quot;&gt;kernel/notifier.c:252&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 *	Blocking notifier chain routines.  All access to the chain is
 *	synchronized by an rwsem.
 */

static int __blocking_notifier_chain_register(struct blocking_notifier_head *nh,
					      struct notifier_block *n,
					      bool unique_priority)
{
	int ret;

	/*
	 * This code gets used during boot-up, when task switching is
	 * not yet working and interrupts must remain disabled.  At
	 * such times we must not call down_write().
	 */
	if (unlikely(system_state == SYSTEM_BOOTING))
		return notifier_chain_register(&amp;amp;nh-&amp;gt;head, n, unique_priority);

	down_write(&amp;amp;nh-&amp;gt;rwsem);
	ret = notifier_chain_register(&amp;amp;nh-&amp;gt;head, n, unique_priority);
	up_write(&amp;amp;nh-&amp;gt;rwsem);
	return ret;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/notifier.c#L20&quot;&gt;kernel/notifier.c:20&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 *	Notifier chain core routines.  The exported routines below
 *	are layered on top of these, with appropriate locking added.
 */

static int notifier_chain_register(struct notifier_block **nl,
				   struct notifier_block *n,
				   bool unique_priority)
{
	while ((*nl) != NULL) {
		if (unlikely((*nl) == n)) {
			WARN(1, &quot;notifier callback %ps already registered&quot;,
			     n-&amp;gt;notifier_call);
			return -EEXIST;
		}
		if (n-&amp;gt;priority &amp;gt; (*nl)-&amp;gt;priority)
			break;
		if (n-&amp;gt;priority == (*nl)-&amp;gt;priority &amp;amp;&amp;amp; unique_priority)
			return -EBUSY;
		nl = &amp;amp;((*nl)-&amp;gt;next);
	}
	n-&amp;gt;next = *nl;
	rcu_assign_pointer(*nl, n);
	trace_notifier_register((void *)n-&amp;gt;notifier_call);
	return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each callback can return one of a series of options.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/include/linux/notifier.h#L18&quot;&gt;include/linux/notifier.h:18&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define NOTIFY_DONE		0x0000		/* Don&apos;t care */
#define NOTIFY_OK		0x0001		/* Suits me */
#define NOTIFY_STOP_MASK	0x8000		/* Don&apos;t call further */
#define NOTIFY_BAD		(NOTIFY_STOP_MASK|0x0002)
						/* Bad/Veto action */
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When notifying the chain, if a function returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STOP&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BAD&lt;/code&gt; then
the previous parts of the chain are called again with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PM_POST_HIBERNATION&lt;/code&gt;&lt;sup id=&quot;fnref:pmpost&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:pmpost&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;14&lt;/a&gt;&lt;/sup&gt;
and an error is returned.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/notifier.c#L107&quot;&gt;kernel/notifier.c:107&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/**
 * notifier_call_chain_robust - Inform the registered notifiers about an event
 *                              and rollback on error.
 * @nl:		Pointer to head of the blocking notifier chain
 * @val_up:	Value passed unmodified to the notifier function
 * @val_down:	Value passed unmodified to the notifier function when recovering
 *              from an error on @val_up
 * @v:		Pointer passed unmodified to the notifier function
 *
 * NOTE:	It is important the @nl chain doesn&apos;t change between the two
 *		invocations of notifier_call_chain() such that we visit the
 *		exact same notifier callbacks; this rules out any RCU usage.
 *
 * Return:	the return value of the @val_up call.
 */
static int notifier_call_chain_robust(struct notifier_block **nl,
				     unsigned long val_up, unsigned long val_down,
				     void *v)
{
	int ret, nr = 0;

	ret = notifier_call_chain(nl, val_up, v, -1, &amp;amp;nr);
	if (ret &amp;amp; NOTIFY_STOP_MASK)
		notifier_call_chain(nl, val_down, v, nr-1, NULL);

	return ret;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each of these callbacks tends to be quite driver-specific, so we’ll cease
discussion of this here.&lt;/p&gt;

&lt;h3 id=&quot;sync-filesystems&quot;&gt;Sync Filesystems&lt;/h3&gt;
&lt;p&gt;The next step is to ensure all filesystems have been synchronized to disk.&lt;/p&gt;

&lt;p&gt;This is performed via a simple helper function that times how long the full
synchronize operation, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ksys_sync&lt;/code&gt; takes.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/main.c#L69&quot;&gt;kernel/power/main.c:69&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void ksys_sync_helper(void)
{
	ktime_t start;
	long elapsed_msecs;

	start = ktime_get();
	ksys_sync();
	elapsed_msecs = ktime_to_ms(ktime_sub(ktime_get(), start));
	pr_info(&quot;Filesystems sync: %ld.%03ld seconds\n&quot;,
		elapsed_msecs / MSEC_PER_SEC, elapsed_msecs % MSEC_PER_SEC);
}
EXPORT_SYMBOL_GPL(ksys_sync_helper);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ksys_sync&lt;/code&gt; wakes and instructs a set of flusher threads to write out
every filesystem, first their inodes&lt;sup id=&quot;fnref:inode&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:inode&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;15&lt;/a&gt;&lt;/sup&gt;, then the full filesystem, and
then finally all block devices, to ensure all pages are written out
to disk.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/fs/sync.c#L87&quot;&gt;fs/sync.c:87&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 * Sync everything. We start by waking flusher threads so that most of
 * writeback runs on all devices in parallel. Then we sync all inodes reliably
 * which effectively also waits for all flusher threads to finish doing
 * writeback. At this point all data is on disk so metadata should be stable
 * and we tell filesystems to sync their metadata via -&amp;gt;sync_fs() calls.
 * Finally, we writeout all block devices because some filesystems (e.g. ext2)
 * just write metadata (such as inodes or bitmaps) to block device page cache
 * and do not sync it on their own in -&amp;gt;sync_fs().
 */
void ksys_sync(void)
{
	int nowait = 0, wait = 1;

	wakeup_flusher_threads(WB_REASON_SYNC);
	iterate_supers(sync_inodes_one_sb, NULL);
	iterate_supers(sync_fs_one_sb, &amp;amp;nowait);
	iterate_supers(sync_fs_one_sb, &amp;amp;wait);
	sync_bdevs(false);
	sync_bdevs(true);
	if (unlikely(laptop_mode))
		laptop_sync_completion();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It follows an interesting pattern of using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iterate_supers&lt;/code&gt; to run both
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sync_inodes_one_sb&lt;/code&gt; and then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sync_fs_one_sb&lt;/code&gt; on each known filesystem&lt;sup id=&quot;fnref:superblock&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:superblock&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;16&lt;/a&gt;&lt;/sup&gt;.
It also calls both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sync_fs_one_sb&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sync_bdevs&lt;/code&gt; twice, first without waiting
for any operations to complete and then again waiting for completion&lt;sup id=&quot;fnref:fscode&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fscode&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;17&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;laptop_mode&lt;/code&gt; is enabled the system runs additional filesystem synchronization
operations after the specified delay without any writes.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/mm/page-writeback.c#L111&quot;&gt;mm/page-writeback.c:111&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 * Flag that puts the machine in &quot;laptop mode&quot;. Doubles as a timeout in jiffies:
 * a full sync is triggered after this time elapses without any disk activity.
 */
int laptop_mode;

EXPORT_SYMBOL(laptop_mode);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, when running a filesystem synchronization operation, the system will
add an additional timer to schedule more writes after the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;laptop_mode&lt;/code&gt; delay.
We don’t want the state of the system to change at all while performing
hibernation, so we cancel those timers.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/mm/page-writeback.c#L2198&quot;&gt;mm/page-writeback.c:2198&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
 * We&apos;re in laptop mode and we&apos;ve just synced. The sync&apos;s writes will have
 * caused another writeback to be scheduled by laptop_io_completion.
 * Nothing needs to be written back anymore, so we unschedule the writeback.
 */
void laptop_sync_completion(void)
{
	struct backing_dev_info *bdi;

	rcu_read_lock();

	list_for_each_entry_rcu(bdi, &amp;amp;bdi_list, bdi_list)
		del_timer(&amp;amp;bdi-&amp;gt;laptop_mode_wb_timer);

	rcu_read_unlock();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As a side note, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ksys_sync&lt;/code&gt; function is simply called when the
system call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sync&lt;/code&gt; is used.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/fs/sync.c#L111&quot;&gt;fs/sync.c:111&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SYSCALL_DEFINE0(sync)
{
	ksys_sync();
	return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-end-of-preparation&quot;&gt;The End of Preparation&lt;/h2&gt;
&lt;p&gt;With that the system has finished preparations for hibernation.
This is a somewhat arbitrary cutoff, but next the system will begin
a full freeze of userspace to then dump memory out to an image and finally
to perform hibernation. All this will be covered in future articles!&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:hibermode&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Hibernation modes are outside of scope for this article, see the &lt;a href=&quot;/2022/01/hibernate-docs&quot;&gt;previous article&lt;/a&gt; for a high-level description of the different types of hibernation. &lt;a href=&quot;#fnref:hibermode&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:workqueue&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Workqueues are a mechanism for running asynchronous tasks. A full description of them is a task for another time, but the kernel documentation on them is available here: &lt;a href=&quot;https://www.kernel.org/doc/html/v6.9/core-api/workqueue.html&quot;&gt;https://www.kernel.org/doc/html/v6.9/core-api/workqueue.html&lt;/a&gt; &lt;a href=&quot;#fnref:workqueue&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:workqueue:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:wakeupevent&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This is a bit of an oversimplification, but since this isn’t the main focus of this article this description has been kept to a higher level. &lt;a href=&quot;#fnref:wakeupevent&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:kconfig&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Kconfig is Linux’s build configuration system that sets many different macros to enable/disable various features. &lt;a href=&quot;#fnref:kconfig&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:choicedefault&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Kconfig defaults to the &lt;a href=&quot;https://www.kernel.org/doc/html/v6.9/kbuild/kconfig-language.html&quot;&gt;first default found&lt;/a&gt; &lt;a href=&quot;#fnref:choicedefault&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:larval&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Including checking whether the algorithm is larval? Which appears to indicate that it requires additional setup, but is an interesting choice of name for such a state. &lt;a href=&quot;#fnref:larval&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:procfreeze&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Specifically when we get to process freezing, which we’ll get to in the next article in this series. &lt;a href=&quot;#fnref:procfreeze&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:swap&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Swap space is outside the scope of this article, but in short it is a buffer on disk that the kernel uses to store memory not current in use to free up space for other things. See &lt;a href=&quot;https://www.kernel.org/doc/gorman/html/understand/understand014.html&quot;&gt;Swap Management&lt;/a&gt; for more details. &lt;a href=&quot;#fnref:swap&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:nvdimm&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;The code for this is lengthy and tangential, thus it has not been included here. If you’re curious about the details of this, see &lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/kernel/power/hibernate.c#L858&quot;&gt;kernel/power/hibernate.c:858&lt;/a&gt; for the details of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate_quiet_exec&lt;/code&gt;, and &lt;a href=&quot;https://elixir.bootlin.com/linux/v6.9.9/source/drivers/nvdimm/core.c#L451&quot;&gt;drivers/nvdimm/core.c:451&lt;/a&gt; for how it is used in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvdimm&lt;/code&gt;. &lt;a href=&quot;#fnref:nvdimm&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:console&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Annoyingly this code appears to use the terms “console” and “virtual terminal” interchangeably. &lt;a href=&quot;#fnref:console&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:ioctl&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ioctl&lt;/code&gt;s are special device-specific I/O operations that permit performing actions outside of the standard file interactions of read/write/seek/etc. &lt;a href=&quot;#fnref:ioctl&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:ioctl:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:vtauto&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’m not entirely clear on how this flag works, this subsystem is particularly complex. &lt;a href=&quot;#fnref:vtauto&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:priority&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;In this case a higher number is higher priority. &lt;a href=&quot;#fnref:priority&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:pmpost&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Or whatever the caller passes as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val_down&lt;/code&gt;, but in this case we’re specifically looking at how this is used in hibernation. &lt;a href=&quot;#fnref:pmpost&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:inode&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;An inode refers to a particular file or directory within the filesystem. See &lt;a href=&quot;https://en.wikipedia.org/wiki/Inode&quot;&gt;Wikipedia&lt;/a&gt; for more details. &lt;a href=&quot;#fnref:inode&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:superblock&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Each active filesystem is registed with the kernel through a structure known as a superblock, which contains references to all the inodes contained within the filesystem, as well as function pointers to perform the various required operations, like sync. &lt;a href=&quot;#fnref:superblock&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fscode&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’m including minimal code in this section, as I’m not looking to deep dive into the filesystem code at this time. &lt;a href=&quot;#fnref:fscode&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 08 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://tookmund.com/2024/09/hibernation-preparation</link>
        <guid isPermaLink="true">https://tookmund.com/2024/09/hibernation-preparation</guid>
        
        <category>hibernate</category>
        
        
      </item>
    
      <item>
        <title>What to Do When You Forget Your Root Password</title>
        <description>&lt;p&gt;Forgetting your root password would initially seem like a problem requiring
a full re-install, one that you can’t easily recover from without wiping
everything away.&lt;/p&gt;

&lt;p&gt;Forgetting your user password can of course be solved by changing it as root,
as in the following, which changes the password for user &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jacob&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# passwd jacob
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;but only the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; user can change their own password,
so you need to somehow get &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; access in order to do so.&lt;/p&gt;

&lt;h2 id=&quot;changing-roots-password-with-sudo&quot;&gt;Changing Root’s Password with Sudo&lt;/h2&gt;
&lt;p&gt;This one is probably obvious, but if you have a user with the ability to use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo&lt;/code&gt;, then you can change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt;’s password without access to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt;
account by running:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo passwd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;which will reset the password for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; account without requiring the
existing password.&lt;/p&gt;

&lt;h2 id=&quot;boot-directly-to-a-shell&quot;&gt;Boot Directly to a Shell&lt;/h2&gt;

&lt;p&gt;Getting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; access to any Linux machine you have physical access to
is surprisingly simple.
You can just boot the machine directly into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; shell without any access
control, i.e. passwords.&lt;/p&gt;

&lt;h3 id=&quot;why-you-should-always-encrypt-your-storage&quot;&gt;Why You Should Always Encrypt Your Storage&lt;sup id=&quot;fnref:encrypt&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:encrypt&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;

&lt;p&gt;To boot directly to a shell you need to append the following text to
the &lt;a href=&quot;https://www.kernel.org/doc/html/v4.14/admin-guide/kernel-parameters.html&quot;&gt;kernel command line&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;init=/bin/sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;(You could use pretty much any program here, but you’re putting your system into a weird state doing this, and so I’d recommend the simplest approach.)&lt;/p&gt;

&lt;h3 id=&quot;grub&quot;&gt;GRUB&lt;/h3&gt;

&lt;p&gt;GRUB will allow you to edit boot parameters on startup using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e&lt;/code&gt;
key. You’ll then be presented with a editor&lt;sup id=&quot;fnref:emacs&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:emacs&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; that you can
use to change the kernel command line by appending to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;linux&lt;/code&gt; line.&lt;/p&gt;

&lt;p&gt;E.g. If your editor looks like this:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        load_video
        insmod gzio
        if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
        insmod part_gpt
        insmod ext2
        search --no-floppy --fs-uuid --set=root abcd1234-5678-0910-1112-abcd12345678
        echo    &apos;Loading Linux 6.1.0-21-amd64 ...&apos;
        linux   /boot/vmlinuz-6.1.0-21-amd64 root=UUID=abcd1234-5678-0910-1112-abcd12345678 ro  quiet
        echo    &apos;Loading initial ramdisk ...&apos;
        initrd  /boot/initrd.img-6.1.0-21-amd64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Then you would add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init=/bin/sh&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        load_video
        insmod gzio
        if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
        insmod part_gpt
        insmod ext2
        search --no-floppy --fs-uuid --set=root abcd1234-5678-0910-1112-abcd12345678
        echo    &apos;Loading Linux 6.1.0-21-amd64 ...&apos;
        linux   /boot/vmlinuz-6.1.0-21-amd64 root=UUID=abcd1234-5678-0910-1112-abcd12345678 ro  quiet init=/bin/sh
        echo    &apos;Loading initial ramdisk ...&apos;
        initrd  /boot/initrd.img-6.1.0-21-amd64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once you’ve edited it you can start your machine with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+x&lt;/code&gt;, as you can
see from the prompt text under the editor.&lt;/p&gt;

&lt;h3 id=&quot;raspberry-pi-cmdlinetxt&quot;&gt;Raspberry Pi &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmdline.txt&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;On a Raspberry Pi you’ll want to append the above to only line of the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmdline.txt&lt;/code&gt; file on the boot partition of the SD card.
This is the first partition of the disk, the one that is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAT32&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You’ll need to do this on another machine, since if you had &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; access
to edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmdline.txt&lt;/code&gt; you could also just change your password.&lt;/p&gt;

&lt;p&gt;As it is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAT32&lt;/code&gt; partition on an SD card, it should be editable on any other
machine that supports SD cards.&lt;/p&gt;

&lt;p&gt;E.g. If your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmdline.txt&lt;/code&gt; looks like this&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;console=serial0,115200 console=tty1 root=PARTUUID=fb33757d-02 rootfstype=ext4 fsck.repair=yes rootwait quiet
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Then you would add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init=/bin/sh&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;console=serial0,115200 console=tty1 root=PARTUUID=fb33757d-02 rootfstype=ext4 fsck.repair=yes rootwait quiet init=/bin/sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;mount-read--write&quot;&gt;Mount Read / Write&lt;/h2&gt;

&lt;p&gt;Since you’re replacing the &lt;a href=&quot;https://en.wikipedia.org/wiki/Init&quot;&gt;init process&lt;/a&gt;
of the machine with a shell, no other processes will be running.&lt;/p&gt;

&lt;p&gt;Also, your root filesystem will be mounted read-only,
as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt; is expected to remount it read-write as needed.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# mount -o remount,rw /
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;change-root-password&quot;&gt;Change Root Password&lt;/h2&gt;

&lt;p&gt;Once you’ve remounted the root filesystem, all that’s needed is to
run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;passwd&lt;/code&gt; command.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# passwd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Since you’re running the command as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; you won’t need to provide your
existing password, and will only need to type a new password twice.&lt;/p&gt;

&lt;p&gt;Now of course you simply need to remember that password in order to
ensure you don’t need to do this again.&lt;/p&gt;

&lt;h2 id=&quot;reboot-safely&quot;&gt;Reboot Safely&lt;/h2&gt;

&lt;p&gt;You now cannot follow the standard reboot process here, as you’re only running
one process.&lt;/p&gt;

&lt;p&gt;Therefore it’s important to put your root filesystem back into read-only before
powering off your machine:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# mount -o remount,ro /
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once you’ve done that you just need to hold down the power button until the
machine completely powers off or pull the plug.&lt;/p&gt;

&lt;p&gt;And then you’re done! Boot the computer again and you’ll have everything
working as normal, with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; password you remember.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:encrypt&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Not that this is the only reason, anyone with physical access to your machine could also boot it into another operating system they control, or just remove your storage device and put it into another computer, or probably other things I’m not thinking of now. You should always encrypt your devices. &lt;a href=&quot;#fnref:encrypt&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:emacs&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;The editor uses emacs-like keybindings. &lt;a href=&quot;https://www.gnu.org/software/grub/manual/grub/grub.html#Command_002dline-interface&quot;&gt;The manual&lt;/a&gt; includes a list of all the options available. &lt;a href=&quot;#fnref:emacs&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 02 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://tookmund.com/2024/06/linux-forgot-password</link>
        <guid isPermaLink="true">https://tookmund.com/2024/06/linux-forgot-password</guid>
        
        <category>raspberry pi</category>
        
        <category>linux</category>
        
        <category>root</category>
        
        <category>password</category>
        
        
      </item>
    
      <item>
        <title>Regular Reboots</title>
        <description>&lt;p&gt;Uptime is often considered a measure of system reliability,
an indication that the running software is stable and can be counted on.&lt;/p&gt;

&lt;p&gt;However, this hides the insidious build-up of state throughout the system as
it runs, the slow drift from the expected to the strange.&lt;/p&gt;

&lt;p&gt;As Nolan Lawson highlights in an excellent post entitled
&lt;a href=&quot;https://nolanlawson.com/2020/12/29/programmers-are-bad-at-managing-state/&quot;&gt;Programmers are bad at managing state&lt;/a&gt;,
state is the most challenging part of programming.
It’s why “did you try turning it off and on again” is a classic tech support
response to any problem.&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;You: uptime&lt;br /&gt;&lt;br /&gt;Me: Every machine gets rebooted at 1AM to clear the slate for maintenance, and at 3:30AM to push through any pending updates.&lt;/p&gt;&amp;mdash; &lt;a href=&quot;https://twitter.com/SwiftOnSecurity/status/1343079557910433797&quot;&gt;@SwiftOnSecurity, December 27, 2020&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;In addition to the problem of state, installing regular updates periodically
requires a reboot, even if the rest of the process is automated through a
tool like &lt;a href=&quot;https://wiki.debian.org/UnattendedUpgrades&quot;&gt;unattended-upgrades&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For my personal homelab, I manage a handful of different machines running
various services.&lt;/p&gt;

&lt;p&gt;I used to just schedule a day to update and reboot all of them, but that
got very tedious very quickly.&lt;/p&gt;

&lt;p&gt;I then moved the reboot to a cronjob,
and then recently to a systemd timer and service.&lt;/p&gt;

&lt;p&gt;I figure that laying out my path to better management of this might help
others, and will almost certainly lead to someone telling me a better way
to do this.&lt;/p&gt;

&lt;p&gt;UPDATE: Turns out there’s another option for better systemd cron integration.
See &lt;a href=&quot;#systemd-cron&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cron&lt;/code&gt;&lt;/a&gt; below.&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Ultimately, uptime only measures the duration since you last proved you can turn the machine on and have it boot.&lt;/p&gt;&amp;mdash; &lt;a href=&quot;https://twitter.com/SwiftOnSecurity/status/728812283535626242&quot;&gt;@SwiftOnSecurity, May 7, 2016&lt;/a&gt;&lt;/blockquote&gt;

&lt;h2 id=&quot;stage-one-reboot-cron&quot;&gt;Stage One: Reboot Cron&lt;/h2&gt;

&lt;p&gt;The first, and easiest approach, is a simple cron job.
Just adding the following line to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/spool/cron/crontabs/root&lt;/code&gt;&lt;sup id=&quot;fnref:cronoptions&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:cronoptions&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
is enough to get your machine to reboot once a month&lt;sup id=&quot;fnref:monthly&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:monthly&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; on the 6th at 8:00 AM&lt;sup id=&quot;fnref:cronformat&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:cronformat&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0 8 6 * * reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I had this configured for many years and it works well.
But you have no indication as to whether it succeeds except for checking
your uptime regularly yourself.&lt;/p&gt;

&lt;h2 id=&quot;stage-two-reboot-systemd-timer&quot;&gt;Stage Two: Reboot systemd Timer&lt;/h2&gt;

&lt;p&gt;The next evolution of this approach for me was to use a systemd timer.
I created a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;regular-reboot.timer&lt;/code&gt; with the following contents:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Unit]
Description=Reboot on a Regular Basis

[Timer]
Unit=regular-reboot.service
OnBootSec=1month

[Install]
WantedBy=timers.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This timer will trigger the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;regular-reboot.service&lt;/code&gt; systemd unit
when the system reaches one month of uptime.&lt;/p&gt;

&lt;p&gt;I’ve seen some guides to creating timer units recommend adding
a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Wants=regular-reboot.service&lt;/code&gt; to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[Unit]&lt;/code&gt; section,
but this has the consequence of running that service every time it starts the
timer. In this case that will just reboot your system on startup which is
not what you want.&lt;/p&gt;

&lt;p&gt;Care needs to be taken to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OnBootSec&lt;/code&gt; directive instead of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OnCalendar&lt;/code&gt; or any of the other time specifications, as your system could
reboot, discover its still within the expected window and reboot again.
With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OnBootSec&lt;/code&gt; your system will not have that problem.
Technically, this same problem could have occurred with the cronjob approach,
but in practice it never did, as the systems took long enough to come back
up that they were no longer within the expected window for the job.&lt;/p&gt;

&lt;p&gt;I then added the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;regular-reboot.service&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Unit]
Description=Reboot on a Regular Basis
Wants=regular-reboot.timer

[Service]
Type=oneshot
ExecStart=shutdown -r 02:45
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You’ll note that this service is actually scheduling a specific reboot time
via the shutdown command instead of just immediately rebooting.
This is a bit of a hack needed because I can’t control when the timer
runs exactly when using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OnBootSec&lt;/code&gt;.
This way different systems have different reboot times so that everything
doesn’t just reboot and fail all at once. Were something to fail to come
back up I would have some time to fix it, as each machine has a few hours
between scheduled reboots.&lt;/p&gt;

&lt;p&gt;One you have both files in place, you’ll simply need to reload configuration
and then enable and start the timer unit:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;systemctl daemon-reload
systemctl enable --now regular-reboot.timer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can then check when it will fire next:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# systemctl status regular-reboot.timer
● regular-reboot.timer - Reboot on a Regular Basis
     Loaded: loaded (/etc/systemd/system/regular-reboot.timer; enabled; preset: enabled)
     Active: active (waiting) since Wed 2024-03-13 01:54:52 EDT; 1 week 4 days ago
    Trigger: Fri 2024-04-12 12:24:42 EDT; 2 weeks 4 days left
   Triggers: ● regular-reboot.service

Mar 13 01:54:52 dorfl systemd[1]: Started regular-reboot.timer - Reboot on a Regular Basis.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;sidenote-replacing-all-cron-jobs-with-systemd-timers&quot;&gt;Sidenote: Replacing all Cron Jobs with systemd Timers&lt;/h3&gt;
&lt;p&gt;More generally, I’ve now replaced all cronjobs on my personal systems with
systemd timer units, mostly because I can now actually track failures via
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prometheus-node-exporter&lt;/code&gt;. There are plenty of ways to hack in cron support
to the node exporter, but just moving to systemd units provides both
support for tracking failure and logging,
both of which make system administration much easier when things inevitably
go wrong.&lt;/p&gt;

&lt;h4 id=&quot;systemd-cron&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cron&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;An alternative to converting everything by hand, if you happen to have
a lot of cronjobs is
&lt;a href=&quot;https://github.com/systemd-cron/systemd-cron&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cron&lt;/code&gt;&lt;/a&gt;.
It will make each crontab and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/cron.*&lt;/code&gt; directory into automatic
service and timer units.&lt;/p&gt;

&lt;p&gt;Thanks to Alexandre Detiste for letting me know about this project.
I have few enough cron jobs that I’ve already converted, but
for anyone looking at a large number of jobs to convert
you’ll want to check it out!&lt;/p&gt;

&lt;h2 id=&quot;stage-three-monitor-that-its-working&quot;&gt;Stage Three: Monitor that it’s working&lt;/h2&gt;

&lt;p&gt;The final step here is confirm that these units actually work, beyond just
firing regularly.&lt;/p&gt;

&lt;p&gt;I now have the following rule in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prometheus-alertmanager&lt;/code&gt; rules:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  - alert: UptimeTooHigh
    expr: (time() - node_boot_time_seconds{job=&quot;node&quot;}) / 86400 &amp;gt; 35
    annotations:
      summary: &quot;Instance {{ $labels.instance }} Has Been Up Too Long!&quot;
      description: &quot;Instance {{ $labels.instance }} Has Been Up Too Long!&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will trigger an alert anytime that I have a machine up for more than 35
days. This actually helped me track down one machine that I had forgotten to
set up this new unit on&lt;sup id=&quot;fnref:configmanagement&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:configmanagement&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h2 id=&quot;not-everything-needs-to-scale&quot;&gt;Not everything needs to scale&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://imgs.xkcd.com/comics/is_it_worth_the_time.png&quot; alt=&quot;Is It Worth The Time&quot; /&gt;&lt;/p&gt;

&lt;p&gt;One of the most common fallacies programmers fall into is that we will jump
to automating a solution before we stop and figure out how much time it would even save.&lt;/p&gt;

&lt;p&gt;In taking a slow improvement route to solve this problem for myself,
I’ve managed not to invest too much time&lt;sup id=&quot;fnref:article&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:article&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; in worrying about this
but also achieved a meaningful improvement beyond my first approach of doing it
all by hand.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:cronoptions&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;You could also add a line to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/crontab&lt;/code&gt; or drop a script into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/cron.monthly&lt;/code&gt; depending on your system. &lt;a href=&quot;#fnref:cronoptions&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:monthly&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Why once a month? Mostly to avoid regular disruptions, but still be reasonably timely on updates. &lt;a href=&quot;#fnref:monthly&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:cronformat&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;If you’re looking to understand the cron time format I recommend &lt;a href=&quot;https://crontab.guru/&quot;&gt;crontab guru&lt;/a&gt;. &lt;a href=&quot;#fnref:cronformat&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:configmanagement&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;In the long term I really should set up something like ansible to automatically push fleetwide changes like this but with fewer machines than fingers this seems like overkill. &lt;a href=&quot;#fnref:configmanagement&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:article&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Of course by now writing about it, I’ve probably doubled the amount of time I’ve spent thinking about this topic but oh well… &lt;a href=&quot;#fnref:article&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 24 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://tookmund.com/2024/03/regular-reboot</link>
        <guid isPermaLink="true">https://tookmund.com/2024/03/regular-reboot</guid>
        
        <category>sysadmin</category>
        
        <category>systemd</category>
        
        <category>cron</category>
        
        <category>reboot</category>
        
        <category>state</category>
        
        
      </item>
    
      <item>
        <title>AAC and Debian</title>
        <description>&lt;p&gt;Currently, in a default installation of Debian with the GNOME desktop,
Bluetooth headphones that require the AAC codec&lt;sup id=&quot;fnref:apple&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:apple&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; cannot be used.
&lt;a href=&quot;https://wiki.debian.org/BluetoothUser/a2dp#AAC_codec&quot;&gt;As the Debian wiki outlines&lt;/a&gt;,
using the AAC codec over Bluetooth, while technically supported by
PipeWire, is explicitly disabled in Debian at this time.
This is because the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fdk-aac&lt;/code&gt; library needed to enable this support is currently
in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;non-free&lt;/code&gt; component of the repository, meaning that PipeWire, which
is in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; component, cannot depend on it.&lt;/p&gt;

&lt;h1 id=&quot;how-to-fix-it-yourself&quot;&gt;How to Fix it Yourself&lt;/h1&gt;

&lt;p&gt;If what you, like me, need is simply for Bluetooth Audio to work with AAC
in Debian’s default desktop environment&lt;sup id=&quot;fnref:default&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:default&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;,
then you’ll need to rebuild the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipewire&lt;/code&gt; package to include the
AAC codec. While the current version in Debian &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; has been built with AAC
deliberately disabled, it is trivial to enable if you can install a version
of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fdk-aac&lt;/code&gt; library.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I preface this with the usual caveats when it comes to patent
and licensing controversies. I am not a lawyer, building this package and/or
using it could get you into legal trouble.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These instructions have only been tested on an up-to-date copy of Debian 12.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipewire&lt;/code&gt;’s build dependencies
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt install build-essential devscripts
sudo apt build-dep pipewire
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libfdk-aac-dev&lt;/code&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt install libfdk-aac-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;If the above doesn’t work you’ll likely need to enable non-free and try again&lt;/p&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo sed -i &apos;s/main/main non-free/g&apos; /etc/apt/sources.list
sudo apt update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;Alternatively, if you wish to ensure you are maximally license-compliant and
patent un-infringing&lt;sup id=&quot;fnref:ianal&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ianal&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;,
you can instead build &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fdk-aac-free&lt;/code&gt; which includes only those components
of AAC that are known to be patent-free&lt;sup id=&quot;fnref:ianal:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ianal&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.
This is what should eventually end up in Debian to resolve this problem
(see below).&lt;/p&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt install git-buildpackage
mkdir fdk-aac-source
cd fdk-aac-source
git clone https://salsa.debian.org/multimedia-team/fdk-aac
cd fdk-aac
gbp buildpackage
sudo dpkg -i ../libfdk-aac2_*deb ../libfdk-aac-dev_*deb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Get the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipewire&lt;/code&gt; source code
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkdir pipewire-source
cd pipewire-source
apt source pipewire
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;This will create a bunch of files within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipewire-source&lt;/code&gt; directory,
but you’ll only need the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipewire-&amp;lt;version&amp;gt;&lt;/code&gt; folder, this contains all the
files you’ll need to build the package, with all the debian-specific patches
already applied.
Note that you don’t want to run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt source&lt;/code&gt; command as root, as it will
then create files that your regular user cannot edit.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Fix the dependencies and build options
To fix up the build scripts to use the fdk-aac library,
you need to save the following as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipewire-source/aac.patch&lt;/code&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;--- debian/control.orig
+++ debian/control
@@ -40,8 +40,8 @@
             modemmanager-dev,
             pkg-config,
             python3-docutils,
-               systemd [linux-any]
-Build-Conflicts: libfdk-aac-dev
+               systemd [linux-any],
+               libfdk-aac-dev
 Standards-Version: 4.6.2
 Vcs-Browser: https://salsa.debian.org/utopia-team/pipewire
 Vcs-Git: https://salsa.debian.org/utopia-team/pipewire.git
--- debian/rules.orig
+++ debian/rules
@@ -37,7 +37,7 @@
 		-Dauto_features=enabled \
 		-Davahi=enabled \
 		-Dbluez5-backend-native-mm=enabled \
-		-Dbluez5-codec-aac=disabled \
+		-Dbluez5-codec-aac=enabled \
 		-Dbluez5-codec-aptx=enabled \
 		-Dbluez5-codec-lc3=enabled \
 		-Dbluez5-codec-lc3plus=disabled \
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;Then you’ll need to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;patch&lt;/code&gt; from within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipewire-&amp;lt;version&amp;gt;&lt;/code&gt; folder
created by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt source&lt;/code&gt;:&lt;/p&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;patch -p0 &amp;lt; ../aac.patch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Build &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipewire&lt;/code&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd pipewire-*
debuild
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;Note that you will likely see an error from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debsign&lt;/code&gt; at the end of this process,
this is harmless, you simply don’t have a GPG key set up to sign your
newly-built package&lt;sup id=&quot;fnref:gpg-key&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:gpg-key&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. Packages don’t need to be signed to be installed,
and debsign uses a somewhat non-standard signing process that dpkg does not
check anyway.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;ol&gt;
  &lt;li&gt;Install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libspa-0.2-bluetooth&lt;/code&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo dpkg -i libspa-0.2-bluetooth_*.deb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Restart PipeWire and/or Reboot
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;Theoretically there’s a set of services to restart here that would
get pipewire to pick up the new library, probably just pipewire itself.
But it’s just as easy to restart and ensure everything is using the correct
library.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;why&quot;&gt;Why&lt;/h1&gt;

&lt;p&gt;This is a slightly unusual situation, as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fdk-aac&lt;/code&gt; library is licensed
under what
&lt;a href=&quot;https://www.gnu.org/licenses/license-list.html#fdk&quot;&gt;even the GNU project&lt;/a&gt;
acknowledges is a free software license.
However, &lt;a href=&quot;https://android.googlesource.com/platform/external/aac/+/master/NOTICE&quot;&gt;this license&lt;/a&gt;
explicitly informs the user that they need to acquire
a patent license to use this software&lt;sup id=&quot;fnref:correction&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:correction&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;3.    NO PATENT LICENSE&lt;/p&gt;

  &lt;p&gt;NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
Fraunhofer provides no warranty of patent non-infringement with respect to this
software.
You may use this FDK AAC Codec software or modifications thereto only for
purposes that are authorized by appropriate patent licenses.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To quote the GNU project:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Because of this, and because the license author is a known patent aggressor,
we encourage you to be careful about using or redistributing software under
this license: you should first consider whether the licensor might aim to
lure you into patent infringement.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AAC is covered by a number of patents, which expire at some point in the 2030s&lt;sup id=&quot;fnref:patentexpire&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:patentexpire&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.
As such the current version of the library is potentially legally dubious to ship with
any other software, as it could be considered patent-infringing&lt;sup id=&quot;fnref:ianal:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ianal&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h2 id=&quot;fedoras-solution&quot;&gt;Fedora’s solution&lt;/h2&gt;

&lt;p&gt;Since 2017, Fedora has included a modified version of the library
as fdk-aac-free, see the &lt;a href=&quot;https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/thread/F64JBJI2IZFT2A5QDXGHNMPALCQIVJAX/&quot;&gt;announcement&lt;/a&gt; and the &lt;a href=&quot;https://bugzilla.redhat.com/show_bug.cgi?id=1501522&quot;&gt;bugzilla bug requesting review&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This version of the library includes only the AAC LC profile, which is believed
to be entirely patent-free&lt;sup id=&quot;fnref:ianal:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ianal&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Based on this, there is an open bug report in Debian requesting that the
&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=981285&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fdk-aac&lt;/code&gt; package be moved to the main component&lt;/a&gt;
and that the
&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1021370&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipwire&lt;/code&gt; package be updated to build against it&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-debian-new-queue&quot;&gt;The Debian NEW queue&lt;/h2&gt;

&lt;p&gt;To resolve these bugs, a version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fdk-aac-free&lt;/code&gt; has been uploaded to Debian
by Jeremy Bicha.
However, to make it into Debian proper, it must first pass through the
&lt;a href=&quot;https://ftp-master.debian.org/new.html&quot;&gt;ftpmaster’s NEW queue&lt;/a&gt;.
The &lt;a href=&quot;https://ftp-master.debian.org/new/fdk-aac-free_2.0.2-3.html&quot;&gt;current version of fdk-aac-free&lt;/a&gt;
has been in the NEW queue since July 2023.&lt;/p&gt;

&lt;p&gt;Based on conversations in some of the bugs above, it’s been there since at least 2022&lt;sup id=&quot;fnref:jbicha&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:jbicha&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;I hope this helps anyone stuck with AAC to get their hardware working for them
while we wait for the package to eventually make it through the NEW queue.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=39503266&quot;&gt;Discuss on Hacker News&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:apple&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Such as, for example, any Apple AirPods, which only support AAC AFAICT. &lt;a href=&quot;#fnref:apple&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:default&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Which, as of Debian 12 is GNOME 3 under Wayland with PipeWire. &lt;a href=&quot;#fnref:default&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:ianal&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’m not a lawyer, I don’t know what kinds of infringement might or might not be possible here, do your own research, etc. &lt;a href=&quot;#fnref:ianal&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:ianal:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;#fnref:ianal:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;#fnref:ianal:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:gpg-key&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;And if you DO have a key setup with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debsign&lt;/code&gt; you almost certainly don’t need these instructions. &lt;a href=&quot;#fnref:gpg-key&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:correction&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This was originally phrased as “explicitly does not grant any patent rights.” It was &lt;a href=&quot;https://news.ycombinator.com/item?id=39503761&quot;&gt;pointed out on Hacker News&lt;/a&gt; that this is not exactly what it says, as it also includes a specific note that you’ll need to acquire your own patent license. I’ve now quoted the relevant section of the license for clarity. &lt;a href=&quot;#fnref:correction&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:patentexpire&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Wikipedia claims the “base” patents expire in 2031, with the extensions expiring in 2038, but its &lt;a href=&quot;https://hydrogenaud.io/index.php/topic,121109.0.html&quot;&gt;source for these claims&lt;/a&gt; is some guy’s spreadsheet in a forum. The same discussion also brings up Wikipedia’s claim and casts some doubt on it, so I’m not entirely sure what’s correct here, but I didn’t feel like doing a patent deep-dive today. If someone can provide a clear answer that would be much appreciated. &lt;a href=&quot;#fnref:patentexpire&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:jbicha&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;According to Jeremy Bícha: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1021370#17 &lt;a href=&quot;#fnref:jbicha&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 25 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://tookmund.com/2024/02/aac-and-debian</link>
        <guid isPermaLink="true">https://tookmund.com/2024/02/aac-and-debian</guid>
        
        <category>debian</category>
        
        <category>bluetooth</category>
        
        <category>patents</category>
        
        
      </item>
    
      <item>
        <title>Fixing My Shell</title>
        <description>&lt;p&gt;For an embarassingly long time, my shell has unnecessarily tried to
initialize a console font in every kind of interactive terminal.&lt;/p&gt;

&lt;p&gt;This leaves the following error message in my terminal:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Couldn&apos;t get a file descriptor referring to the console.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It even shows up twice when running tmux!&lt;/p&gt;

&lt;p&gt;Clearly I’ve done something horrible to my configuration,
and now I’ve got to clean it up.&lt;/p&gt;

&lt;h2 id=&quot;how-does-shell-initialization-work&quot;&gt;How does Shell Initialization Work?&lt;/h2&gt;

&lt;p&gt;The precise files a shell reads at start-up is somewhat complex, and defined
by this excellent chart &lt;sup id=&quot;fnref:chart&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:chart&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/shell-startup-actual.svg&quot; alt=&quot;Shell Startup Flowchart&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For the purposes of what I’m trying to fix, there are two paths that matter.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Interactive login shell startup&lt;/li&gt;
  &lt;li&gt;Interactive non-login shell startup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see from the above, trying to distinguish these two paths in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt;
is an absolute mess.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt;, in contrast, is much cleaner and allows for a clear distinction
between these two cases, with login shell configuration files as a superset of
configuration files used by non-login shells.&lt;/p&gt;

&lt;h2 id=&quot;how-did-we-get-here&quot;&gt;How did we get here?&lt;/h2&gt;

&lt;p&gt;I keep my configuration files in a &lt;a href=&quot;https://github.com/tookmund/config&quot;&gt;config&lt;/a&gt;
repository.&lt;/p&gt;

&lt;p&gt;Some time ago I got quite frustrated at this whole shell initialization thing,
and just linked everything together in one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;profile&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.mkshrc -&amp;gt; config/profile
.profile -&amp;gt; config/profile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This appears to have created this mess.&lt;/p&gt;

&lt;h2 id=&quot;move-to-zsh&quot;&gt;Move to ZSH&lt;/h2&gt;

&lt;p&gt;I’ve wanted to move to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt; for a while, and took this opportunity to do so.
So my new configuration files are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zprofile&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.mkshrc&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.profile&lt;/code&gt;
(though I’m going to retain those symlinks to allow my old configurations to
continue working).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.mirbsd.org/mksh.htm&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mksh&lt;/code&gt;&lt;/a&gt; is a nice simple shell,
but using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt; here allows for more consistency
between my home and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$WORK&lt;/code&gt; environments, and will allow a lot more powerful
extensions.&lt;/p&gt;

&lt;h2 id=&quot;updating-my-prompt&quot;&gt;Updating my Prompt&lt;/h2&gt;
&lt;p&gt;ZSH prompts use a totally different configuration via variable expansion.
However, it also uses the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROMPT&lt;/code&gt; variable, so I set that to the needed
values for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There’s an excellent ZSH prompt generator at
&lt;a href=&quot;https://zsh-prompt-generator.site/&quot;&gt;https://zsh-prompt-generator.site&lt;/a&gt;
that I used to get these variables, though I’m sure they’re in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt;
documentation somewhere as well.&lt;/p&gt;

&lt;p&gt;I wanted a simple prompt with user (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%n&lt;/code&gt;), host (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%m&lt;/code&gt;), and path (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%d&lt;/code&gt;).
I also wanted a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt; at the end to distinguish this from other shells.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;PROMPT=&quot;%n@%m%d%% &quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;fixing-mksh-prompts&quot;&gt;Fixing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mksh&lt;/code&gt; prompts&lt;/h3&gt;

&lt;p&gt;This worked but surprisingly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mksh&lt;/code&gt; also looks at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROMPT&lt;/code&gt;,
leaving my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mksh&lt;/code&gt; prompt as the literal prompt string without expansion.&lt;/p&gt;

&lt;p&gt;Fixing this requires setting up a proper &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shrc&lt;/code&gt; and linking it to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.mkshrc&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I chose to move my existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aliases&lt;/code&gt; script to this file,
as it also broke in non-login shells when moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;profile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Within this new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shrc&lt;/code&gt; file we can check what shell we’re running via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$0&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if [ &quot;$0&quot; = &quot;/bin/zsh&quot; ] || [ &quot;$0&quot; = &quot;zsh&quot; ] || [ &quot;$0&quot; = &quot;-zsh&quot; ]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I chose to add plain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt; here in case I run it manually for whatever reason.
I also added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-zsh&lt;/code&gt; to support tmux as that’s what it presents as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$0&lt;/code&gt;.
This also means you’ll need to be careful to quote &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$0&lt;/code&gt; or you’ll get fun shell
errors.&lt;/p&gt;

&lt;p&gt;There’s probably a better way to do this, but I couldn’t find something that
was compatible with POSIX shell, which is what most of this has to be written
in to be compatible with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mksh&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt;&lt;sup id=&quot;fnref:korn&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:korn&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;We can then setup different prompts for each:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if [ &quot;$0&quot; = &quot;/bin/zsh&quot; ] || [ &quot;$0&quot; = &quot;zsh&quot; ] || [ &quot;$0&quot; = &quot;-zsh&quot; ]
then
	PROMPT=&quot;%n@%m%d%% &quot;
else
	# Borrowed from
	# http://www.unixmantra.com/2013/05/setting-custom-prompt-in-ksh.html
	PS1=&apos;$(id -un)@$(hostname -s)$PWD$ &apos;
fi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;setting-console-font-in-a-better-way&quot;&gt;Setting Console Font in a Better Way&lt;/h2&gt;

&lt;p&gt;I’ve been setting console font via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setfont&lt;/code&gt; in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.profile&lt;/code&gt; for a while.
I’m not sure where I picked this up, but it’s not the right way.
I even tried to only run this in a console with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t&lt;/code&gt; but that only
checks that output is a terminal, not specifically a console.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if [ -t 1 ]
then
	setfont /usr/share/consolefonts/Lat15-Terminus20x10.psf.gz
fi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This also only runs once the console is logged into,
instead of initializing it on boot.
The correct way to set this up, on Debian-based systems,
is reconfiguring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console-setup&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dpkg-reconfigure console-setup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From there you get a menu of encoding, character set, font, and then font size
to configure for your consoles.&lt;/p&gt;

&lt;h2 id=&quot;vim-mode&quot;&gt;VIM mode&lt;/h2&gt;

&lt;p&gt;To enable VIM mode for ZSH, you simply need to set:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bindkeys -v
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This allows you to edit your shell commands with basic VIM keybinds.&lt;/p&gt;

&lt;h2 id=&quot;getting-back-ctrl--left-arrow-and-ctrl--right-arrow&quot;&gt;Getting back Ctrl + Left Arrow and Ctrl + Right Arrow&lt;/h2&gt;

&lt;p&gt;Moving around one word at a time with Ctrl and the arrow keys is broken by
vim mode unfortunately, so we’ll need to re-enable it:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bindkey &quot;^[[1;5C&quot; forward-word
bindkey &quot;^[[1;5D&quot; backward-word
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;better-history-search&quot;&gt;Better History Search&lt;/h2&gt;

&lt;p&gt;But of course we’re now using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt; so we can do better than just the same
configuration as we had before.&lt;/p&gt;

&lt;p&gt;There’s an excellent substring history search plugin that we can just
source without a plugin manager&lt;sup id=&quot;fnref:plugin&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:plugin&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;source $HOME/config/zsh-history-substring-search.zsh
# Keys are weird, should be ^[[ but it&apos;s not
bindkey &apos;^[[A&apos; history-substring-search-up
bindkey &apos;^[OA&apos; history-substring-search-up
bindkey &apos;^[[B&apos; history-substring-search-down
bindkey &apos;^[OB&apos; history-substring-search-down
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For some reason my system uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^[OA&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^[OB&lt;/code&gt; as up and down keys.
It seems &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^[[A&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^[[B&lt;/code&gt; are the defaults, so I’ve left them in,
but I’m confused as to what differences would lead to this.
If you know, please &lt;a href=&quot;mailto:fixmyshell@tookmund.com&quot;&gt;let me know&lt;/a&gt;
and I’ll add a footnote to this article explaining it.&lt;/p&gt;

&lt;p&gt;Back to history search.
For this to work, we also need to setup history logging:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export SAVEHIST=1000000
export HISTFILE=$HOME/.zsh_history
export HISTFILESIZE=1000000
export HISTSIZE=1000000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;why-did-it-show-up-twice-for-tmux&quot;&gt;Why did it show up twice for tmux?&lt;/h2&gt;

&lt;p&gt;Because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux&lt;/code&gt; creates a login shell.
Adding:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;echo PROFILE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;profile&lt;/code&gt; and:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;echo SHRC
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shrc&lt;/code&gt; confirms this with:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;PROFILE
SHRC
SHRC
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For now, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;profile&lt;/code&gt; sources &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shrc&lt;/code&gt; so that running twice is expected.&lt;/p&gt;

&lt;p&gt;But after this exploration and diagram,
it’s clear we don’t need that for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt;.
Removing this will break remote bash shells (see above diagram),
but I can live without those on my development laptop.&lt;/p&gt;

&lt;p&gt;Removing that line results in the expected output for a new terminal:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SHRC
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And the full output for a new tmux session or console:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;PROFILE
SHRC
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So finally we’re back to a normal state!&lt;/p&gt;

&lt;p&gt;This post is a bit unfocused but I hope it helps someone else repair or enhance
their shell environment.&lt;/p&gt;

&lt;p&gt;If you liked this&lt;sup id=&quot;fnref:typo&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:typo&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, or know of any other ways to manage this I could use,
let me know at &lt;a href=&quot;mailto:fixmyshell@tookmund.com&quot;&gt;fixmyshell@tookmund.com&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:chart&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This chart comes from the excellent &lt;a href=&quot;https://blog.flowblok.id.au/2013-02/shell-startup-scripts.html&quot;&gt;Shell Startup Scripts&lt;/a&gt; article by Peter Ward. I’ve generated the SVG from the &lt;a href=&quot;https://heptapod.host/flowblok/shell-startup/-/blob/branch/default/diagram/impl-actual.dot&quot;&gt;graphviz source&lt;/a&gt; linked in the article. &lt;a href=&quot;#fnref:chart&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:korn&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Technically it has be compatible with Korn shell, but a quick google seems to suggest that that’s actually a subset of POSIX shell. &lt;a href=&quot;#fnref:korn&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:plugin&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I use oh-my-zsh at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$WORK&lt;/code&gt; but for now I’m going to simplify my personal configuration. If I end up using a lot of plugins I’ll reconsider this. &lt;a href=&quot;#fnref:plugin&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:typo&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Or if you’ve found any typos or other issues that I should fix. &lt;a href=&quot;#fnref:typo&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 03 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://tookmund.com/2024/01/fixing-my-shell</link>
        <guid isPermaLink="true">https://tookmund.com/2024/01/fixing-my-shell</guid>
        
        
      </item>
    
      <item>
        <title>The Unexpected Importance of the Trailing Slash</title>
        <description>&lt;p&gt;For many using Unix-derived systems today, we take for granted
that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/some/path&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/some/path/&lt;/code&gt; are the same.
Most shells will even add a trailing slash for you when you press the Tab key
after the name of a directory or a symbolic link to one.&lt;/p&gt;

&lt;p&gt;However, many programs treat these two paths as subtly different in certain cases,
which I outline below, as all three have tripped me up
in various ways&lt;sup id=&quot;fnref:threetrailing&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:threetrailing&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h2 id=&quot;posix-and-coreutils&quot;&gt;POSIX and Coreutils&lt;/h2&gt;

&lt;p&gt;Perhaps the trickiest use of the trailing slash in a distinguishing way is in
&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13&quot;&gt;POSIX&lt;/a&gt;&lt;sup id=&quot;fnref:posixadditional&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:posixadditional&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;
which states:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;When the final component of a pathname is a symbolic link, the standard requires that a trailing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;slash&amp;gt;&lt;/code&gt; causes the link to be followed. This is the behavior of historical implementations&lt;sup id=&quot;fnref:historical&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:historical&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. For example, for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/a/b&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/a/b/&lt;/code&gt;, if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/a/b&lt;/code&gt; is a symbolic link to a directory, then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/a/b&lt;/code&gt; refers to the symbolic link, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/a/b/&lt;/code&gt; refers to the directory to which the symbolic link points.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This leads to some unexpected behavior.
For example, if you have the following structure
of a directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dir&lt;/code&gt; containing a file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dirfile&lt;/code&gt; with a symbolic link &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;link&lt;/code&gt; pointing to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dir&lt;/code&gt;.
(which will be used in all shell examples throughout this article):&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ls -lR
.:
total 4
drwxr-xr-x 2 jacob jacob 4096 Apr  3 00:00 dir
lrwxrwxrwx 1 jacob jacob    3 Apr  3 00:00 link -&amp;gt; dir

./dir:
total 0
-rw-r--r-- 1 jacob jacob 0 Apr  3 00:12 dirfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On Unixes such as MacOS, FreeBSD or Illumos&lt;sup id=&quot;fnref:otherunixes&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:otherunixes&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;,
you can move a directory through a symbolic link by using
a trailing slash:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ mv link/ otherdir
$ ls
link	otherdir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On Linux&lt;sup id=&quot;fnref:renametrailing&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:renametrailing&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mv&lt;/code&gt; will not “rename the indirectly referenced directory and not the symbolic link,”
when given a symbolic link with a trailing slash as the source to be renamed.
despite the &lt;a href=&quot;https://www.gnu.org/software/coreutils/manual/html_node/Trailing-slashes.html&quot;&gt;coreutils documentation’s claims to the contrary&lt;/a&gt;&lt;sup id=&quot;fnref:fairtocoreutils&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fairtocoreutils&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;, instead failing with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Not a directory&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ mv link/ other
mv: cannot move &apos;link/&apos; to &apos;other&apos;: Not a directory
$ mkdir otherdir
$ mv link/ otherdir
mv: cannot move &apos;link/&apos; to &apos;otherdir/link&apos;: Not a directory
$ mv link/ otherdir/
mv: cannot move &apos;link/&apos; to &apos;otherdir/link&apos;: Not a directory
$ mv link otherdirlink
$ ls -l otherdirlink
lrwxrwxrwx 1 jacob jacob 3 Apr  3 00:13 otherdirlink -&amp;gt; dir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is probably for the best, as it is very confusing behavior.
There is still one advantage the trailing slash has when using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mv&lt;/code&gt;,
even on Linux, in that is it does not allow you to move a file to
a non-existent directory, or move a file that you expect to be a directory
that isn’t.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ mv dir/dirfile nonedir/
mv: cannot move &apos;dir/dirfile&apos; to &apos;nonedir/&apos;: Not a directory
$ touch otherfile
$ mv otherfile/ dir
mv: cannot stat &apos;otherfile/&apos;: Not a directory
$ mv otherfile dir
$ ls dir
dirfile  otherfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, Linux still exhibits some confusing behavior of its own, like
when you attempt to remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;link&lt;/code&gt; recursively with a trailing slash:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rm -rvf link/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Neither &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;link&lt;/code&gt; nor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dir&lt;/code&gt; are removed, but the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dir&lt;/code&gt; are removed:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;removed &apos;link/dirfile&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Whereas if you remove the trailing slash, you just remove the symbolic link:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rm -rvf link
removed &apos;link&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While on MacOS, FreeBSD or Illumos&lt;sup id=&quot;fnref:otherunixes:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:otherunixes&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rm&lt;/code&gt; will also remove the
source directory:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rm -rvf link
link/dirfile
link/
$ ls
link
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt; commands, in contrast, behave the same on all
three operating systems.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find&lt;/code&gt; command only searches the contents of the
directory a symbolic link points to if the trailing slash is added:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ find link -name dirfile
$ find link/ -name dirfile
link/dirfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt; command acts similarly, showing information on just a symbolic link by
itself unless a trailing slash is added, at which point it shows the contents
of the directory that it links to:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ls -l link
lrwxrwxrwx 1 jacob jacob 3 Apr  3 00:13 link -&amp;gt; dir
$ ls -l link/
total 0
-rw-r--r-- 1 jacob jacob 0 Apr  3 00:13 dirfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;rsync&quot;&gt;rsync&lt;/h2&gt;

&lt;p&gt;The command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt; handles a trailing slash in an unusual way that
trips up many new users.
The &lt;a href=&quot;https://linux.die.net/man/1/rsync&quot;&gt;rsync man page&lt;/a&gt; notes:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;You can think of a trailing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; on a source as meaning “copy the contents of this directory” as opposed to “copy the directory
by name”, but in both cases the attributes of the containing directory are transferred to the containing  directory  on  the
destination.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is to say, if we had two folders &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; each of which contained some files:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ls -R .
.:
a  b

./a:
a1  a2

./b:
b1  b2

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync -av a b&lt;/code&gt; moves the entire directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; to directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rsync -av a b
sending incremental file list
a/
a/a1
a/a2

sent 181 bytes  received 58 bytes  478.00 bytes/sec
total size is 0  speedup is 0.00
$ ls -R b
b:
a  b1  b2

b/a:
a1  a2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;While running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync -av a/ b&lt;/code&gt; moves the contents of directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rsync -av a/ b
sending incremental file list
./
a1
a2

sent 170 bytes  received 57 bytes  454.00 bytes/sec
total size is 0  speedup is 0.00
$ ls b
a1  a2	b1  b2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;dockerfile-copy&quot;&gt;Dockerfile COPY&lt;/h2&gt;
&lt;p&gt;The Dockerfile &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COPY&lt;/code&gt; command also cares about the presence of the trailing slash,
using it to determine whether the destination should be considered a file or directory.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://docs.docker.com/engine/reference/builder/#copy&quot;&gt;Docker documentation&lt;/a&gt;
explains the rules of the command thusly:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COPY [--chown=&amp;lt;user&amp;gt;:&amp;lt;group&amp;gt;] &amp;lt;src&amp;gt;... &amp;lt;dest&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;…&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;src&amp;gt;&lt;/code&gt; is a directory, the entire contents of the directory are copied, including filesystem metadata.&lt;/p&gt;

  &lt;p&gt;Note: The directory itself is not copied, just its contents.&lt;/p&gt;

  &lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;src&amp;gt;&lt;/code&gt; is any other kind of file, it is copied individually along with its metadata. In this case, if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dest&amp;gt;&lt;/code&gt; ends with a trailing slash &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;, it will be considered a directory and the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;src&amp;gt;&lt;/code&gt; will be written at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dest&amp;gt;/base(&amp;lt;src&amp;gt;)&lt;/code&gt;.&lt;/p&gt;

  &lt;p&gt;If multiple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;src&amp;gt;&lt;/code&gt; resources are specified, either directly or due to the use of a wildcard, then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dest&amp;gt;&lt;/code&gt; must be a directory, and it must end with a slash &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;.&lt;/p&gt;

  &lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dest&amp;gt;&lt;/code&gt; does not end with a trailing slash, it will be considered a regular file and the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;src&amp;gt;&lt;/code&gt; will be written at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dest&amp;gt;&lt;/code&gt;.&lt;/p&gt;

  &lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dest&amp;gt;&lt;/code&gt; doesn’t exist, it is created along with all missing directories in its path.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means if you had a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COPY&lt;/code&gt; command that moved &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file&lt;/code&gt; to a nonexistent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;containerfile&lt;/code&gt;
without the slash, it would create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;containerfile&lt;/code&gt; as a file with the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;COPY file /containerfile
container$ stat -c %F containerfile
regular empty file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Whereas if you add a trailing slash, then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file&lt;/code&gt; will be added as a file under
the new directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;containerdir&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;COPY file /containerdir/
container$ stat -c %F containerdir
directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Interestingly, at no point can you copy a directory completely, only its contents.
Thus if you wanted to make a directory in the new container, you need to
specify its name in both the source and the destination:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;COPY dir /dirincontainer
container$ stat -c %F /dirincontainer
directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dockerfiles do also make good use of the trailing slash to ensure they’re
doing what you mean by requiring a trailing slash on the destination of
multiple files:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;COPY file otherfile /othercontainerdir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;results in the following error:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;When using COPY with more than one source file, the destination must be a directory and end with a /
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:threetrailing&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’m sure there are probably more than just these three cases, but these are the three I’m familiar with. If you know of more, please &lt;a href=&quot;mailto:trailingslash@tookmund.com&quot;&gt;tell me about them!&lt;/a&gt;. &lt;a href=&quot;#fnref:threetrailing&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:posixadditional&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Some additional relevant sections are the &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_13&quot;&gt;Path Resolution Appendix&lt;/a&gt; and the section on &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap03.html#tag_21_03_00_75&quot;&gt;Symbolic Links&lt;/a&gt;. &lt;a href=&quot;#fnref:posixadditional&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:historical&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;The sentence “This is the behavior of historical implementations” implies that this probably originated in some ancient Unix derivative, possibly BSD or even the original Unix. I don’t really have a source on that though, so please &lt;a href=&quot;mailto:trailingslash@tookmund.com&quot;&gt;reach out&lt;/a&gt; if you happen to have any more knowledge on what this refers to. &lt;a href=&quot;#fnref:historical&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:otherunixes&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I tested on MacOS 11.6.5, FreeBSD 12.0 and OmniOS 5.11 &lt;a href=&quot;#fnref:otherunixes&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:otherunixes:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:renametrailing&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/namei.c#n4797&quot;&gt;“unless the source is a directory trailing slashes give -ENOTDIR”&lt;/a&gt; &lt;a href=&quot;#fnref:renametrailing&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fairtocoreutils&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;In fairness to the coreutils maintainers, it seems to be true on all other Unix platforms, but it probably deserves a mention in the documentation when Linux is the most common platform on which coreutils is used. I should submit a patch. &lt;a href=&quot;#fnref:fairtocoreutils&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 08 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://tookmund.com/2022/04/importance-of-the-trailing-slash</link>
        <guid isPermaLink="true">https://tookmund.com/2022/04/importance-of-the-trailing-slash</guid>
        
        
      </item>
    
      <item>
        <title>A Lesson in Shortcuts</title>
        <description>&lt;p&gt;(The below was written by &lt;a href=&quot;https://en.wikipedia.org/wiki/Rob_Pike&quot;&gt;Rob Pike&lt;/a&gt;, copied here for posterity from &lt;a href=&quot;https://web.archive.org/web/20140803082229/https://plus.google.com/+RobPikeTheHuman/posts/R58WgWwN9jp&quot;&gt;The Wayback Machine&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Long ago, as the design of the Unix file system was being worked out, the entries . and .. appeared, to make navigation easier. I’m not sure but I believe .. went in during the Version 2 rewrite, when the file system became hierarchical (it had a very different structure early on).  When one typed ls, however, these files appeared, so either Ken or Dennis added a simple test to the program. It was in assembler then, but the code in question was equivalent to something like this:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   if (name[0] == &apos;.&apos;) continue;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This statement was a little shorter than what it should have been, which is&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   if (strcmp(name, &quot;.&quot;) == 0 || strcmp(name, &quot;..&quot;) == 0) continue;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;but hey, it was easy.&lt;/p&gt;

&lt;p&gt;Two things resulted.&lt;/p&gt;

&lt;p&gt;First, a bad precedent was set. A lot of other lazy programmers introduced bugs by making the same simplification. Actual files beginning with periods are often skipped when they should be counted.&lt;/p&gt;

&lt;p&gt;Second, and much worse, the idea of a “hidden” or “dot” file was created. As a consequence, more lazy programmers started dropping files into everyone’s home directory. I don’t have all that much stuff installed on the machine I’m using to type this, but my home directory has about a hundred dot files and I don’t even know what most of them are or whether they’re still needed. Every file name evaluation that goes through my home directory is slowed down by this accumulated sludge.&lt;/p&gt;

&lt;p&gt;I’m pretty sure the concept of a hidden file was an unintended consequence. It was certainly a mistake.&lt;/p&gt;

&lt;p&gt;How many bugs and wasted CPU cycles and instances of human frustration (not to mention bad design) have resulted from that one small shortcut about  40 years ago?&lt;/p&gt;

&lt;p&gt;Keep that in mind next time you want to cut a corner in your code.&lt;/p&gt;

&lt;p&gt;(For those who object that dot files serve a purpose, I don’t dispute that but counter that it’s the files that serve the purpose, not the convention for their names. They could just as easily be in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/cfg&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/lib&lt;/code&gt;, which is what we did in Plan 9, which had no dot files. Lessons can be learned.)&lt;/p&gt;
</description>
        <pubDate>Tue, 29 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://tookmund.com/2022/03/rob-pike-shortcuts</link>
        <guid isPermaLink="true">https://tookmund.com/2022/03/rob-pike-shortcuts</guid>
        
        
      </item>
    
      <item>
        <title>Linux Hibernation Documentation</title>
        <description>&lt;p&gt;Recently I’ve been curious about how hibernation works on Linux,
as it’s an interesting interaction between hardware and software.
There are some notes in the &lt;a href=&quot;https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate&quot;&gt;Arch wiki&lt;/a&gt;
and the &lt;a href=&quot;https://www.kernel.org/doc/html/latest/power/swsusp.html&quot;&gt;kernel documentation&lt;/a&gt;
(as well as some kernel documentation on &lt;a href=&quot;https://www.kernel.org/doc/html/latest/power/basic-pm-debugging.html&quot;&gt;debugging hibernation&lt;/a&gt;
and on &lt;a href=&quot;https://www.kernel.org/doc/html/latest/admin-guide/pm/sleep-states.html&quot;&gt;sleep states more generally&lt;/a&gt;),
and of course the &lt;a href=&quot;https://uefi.org/specs/ACPI/6.4/&quot;&gt;ACPI Specification&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-formal-definition&quot;&gt;The Formal Definition&lt;/h2&gt;
&lt;p&gt;ACPI (Advanced Configuration and Power Interface) is,
&lt;a href=&quot;https://uefi.org/specs/ACPI/6.4/Frontmatter/Overview/Overview.html&quot;&gt;according to the spec&lt;/a&gt;,
“an architecture-independent power management and configuration framework that
forms a subsystem within the host OS” which defines “a hardware register set to
define power states.”&lt;/p&gt;

&lt;p&gt;ACPI defines four &lt;a href=&quot;https://uefi.org/specs/ACPI/6.4/02_Definition_of_Terms/Definition_of_Terms.html#global-system-state-definitions&quot;&gt;global system states&lt;/a&gt;
G0, working/on, G1, sleeping, G2, soft off, and G3, mechanical off&lt;sup id=&quot;fnref:mechoff&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:mechoff&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
Within G1 there are 4 &lt;a href=&quot;https://uefi.org/specs/ACPI/6.4/16_Waking_and_Sleeping/sleeping-states.html&quot;&gt;sleep states&lt;/a&gt;,
numbered S1 through S4.
There are also S0 and S5, which are equivalent to G0 and G2 respectively&lt;sup id=&quot;fnref:gstates&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:gstates&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h3 id=&quot;sleep&quot;&gt;Sleep&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://uefi.org/specs/ACPI/6.4/16_Waking_and_Sleeping/sleeping-states.html&quot;&gt;According to the spec&lt;/a&gt;,
the ACPI S1-S4 states all do the same thing from the operating system’s perspective, but each saves progressively more power,
so the operating system is expected to pick the deepest of these states when entering sleep.
However, most operating systems&lt;sup id=&quot;fnref:machibernate&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:machibernate&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; distinguish between S1-S3, which are typically referred to as sleep or suspend,
and S4, which is typically referred to as hibernation.&lt;/p&gt;

&lt;h3 id=&quot;s1-cpu-stop-and-cache-wipe&quot;&gt;S1: CPU Stop and Cache Wipe&lt;/h3&gt;
&lt;p&gt;The CPU caches are wiped and then the CPU is stopped, which the spec notes is equivalent to the WBINVD instruction followed by
the STPCLK signal on x86.
However, nothing is powered off.&lt;/p&gt;

&lt;h3 id=&quot;s2-processor-power-off&quot;&gt;S2: Processor Power off&lt;/h3&gt;
&lt;p&gt;The system stops the processor and most system clocks (except the real time clock),
then powers off the processor.
Upon waking, the processor will not continue what it was doing before, but instead use its reset vector&lt;sup id=&quot;fnref:resetvector&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:resetvector&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h3 id=&quot;s3-suspendsleep-suspend-to-ram&quot;&gt;S3: Suspend/Sleep (Suspend-to-RAM)&lt;/h3&gt;
&lt;p&gt;Mostly equivalent to S2, but hardware ensures that only memory and whatever other hardware memory requires are powered.&lt;/p&gt;

&lt;h3 id=&quot;s4-hibernate-suspend-to-disk&quot;&gt;S4: Hibernate (Suspend-to-Disk)&lt;/h3&gt;
&lt;p&gt;In this state, all hardware is completely powered off and an image of the system is written to disk,
to be restored from upon reapplying power.
Writing the system image to disk can be handled by the operating system if supported, or by the firmware.&lt;/p&gt;

&lt;h2 id=&quot;linux-sleep-states&quot;&gt;Linux Sleep States&lt;/h2&gt;
&lt;p&gt;Linux has its own &lt;a href=&quot;https://www.kernel.org/doc/html/latest/admin-guide/pm/sleep-states.html&quot;&gt;set of sleep states&lt;/a&gt;
which mostly correspond with ACPI states.&lt;/p&gt;

&lt;h3 id=&quot;suspend-to-idle&quot;&gt;Suspend-to-Idle&lt;/h3&gt;
&lt;p&gt;This is a software only sleep that puts all hardware into the lowest power state it can, suspends timekeeping,
and &lt;a href=&quot;https://www.kernel.org/doc/html/latest/power/freezing-of-tasks.html&quot;&gt;freezes userspace processes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All userspace and some kernel threads&lt;sup id=&quot;fnref:kernelnofreeze&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:kernelnofreeze&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;, except those tagged with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PF_NOFREEZE&lt;/code&gt;,
are frozen before the system enters a sleep state.
Frozen tasks are sent to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__refrigerator()&lt;/code&gt;, where they set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TASK_UNINTERRUPTIBLE&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PF_FROZEN&lt;/code&gt; and infinitely loop until &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PF_FROZEN&lt;/code&gt; is unset&lt;sup id=&quot;fnref:freezer&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:freezer&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;This prevents these tasks from doing anything during the imaging process.
Any userspace process running on a different CPU while the kernel is trying to create a memory image would cause havoc.
This is also done because any filesystem changes made during this would be lost and could cause the filesystem and its related
in-memory structures to become inconsistent.
Also, creating a hibernation image requires about 50% of memory free, so no tasks should be allocating memory,
which freezing also prevents.&lt;/p&gt;

&lt;h3 id=&quot;standby&quot;&gt;Standby&lt;/h3&gt;
&lt;p&gt;This is equivalent to &lt;a href=&quot;#s1-cpu-stop-and-cache-wipe&quot;&gt;ACPI S1&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;suspend-to-ram&quot;&gt;Suspend-to-RAM&lt;/h3&gt;
&lt;p&gt;This is equivalent to &lt;a href=&quot;#s3-suspendsleep-suspend-to-ram&quot;&gt;ACPI S3&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;hibernation&quot;&gt;Hibernation&lt;/h3&gt;
&lt;p&gt;Hibernation is mostly equivalent to &lt;a href=&quot;#s4-hibernate-suspend-to-disk&quot;&gt;ACPI S4&lt;/a&gt;
but does not require S4, only requiring “low-level code for resuming the system to be present for the underlying CPU architecture”
according to the &lt;a href=&quot;https://www.kernel.org/doc/html/latest/admin-guide/pm/sleep-states.html#hibernation&quot;&gt;Linux sleep state docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To hibernate, everything is stopped and the kernel takes a snapshot of memory.
Then, the system writes out the memory image to disk.
Finally, the system either enters S4 or turns off completely.&lt;/p&gt;

&lt;p&gt;When the system restores power it boots a new kernel, which looks for a hibernation image and loads it into memory.
It then overwrites itself with the hibernation image and jumps to a resume area of the original kernel&lt;sup id=&quot;fnref:lowlevelresume&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:lowlevelresume&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;.
The resumed kernel restores the system to its previous state and resumes all processes.&lt;/p&gt;

&lt;h3 id=&quot;hybrid-suspend&quot;&gt;Hybrid Suspend&lt;/h3&gt;
&lt;p&gt;Hybrid suspend does not correspond to an official ACPI state, but instead is effectively a combination
of S3 and S4.
The system writes out a hibernation image, but then enters suspend-to-RAM. 
If the system wakes up from suspend it will discard the hibernation image,
but if the system loses power it can safely restore from the hibernation image.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:mechoff&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;The difference between soft and mechanical off is that mechanical off is “entered and left by a mechanical means (for example, turning off the system’s power through the movement of a large red switch)” &lt;a href=&quot;#fnref:mechoff&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:gstates&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;It’s unclear to me why G and S states overlap like this. I assume this is a relic of an older spec that only had S states, but I have not as yet found any evidence of this. If someone has any information on this, please &lt;a href=&quot;mailto:hibernate@tookmund.com&quot;&gt;let me know&lt;/a&gt; and I’ll update this footnote. &lt;a href=&quot;#fnref:gstates&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:machibernate&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Of the operating systems I know of that support ACPI sleep states (I checked Windows, Mac, Linux, and the three BSDs&lt;sup id=&quot;fnref:netbsd&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:netbsd&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;), only MacOS does not allow the user to deliberately enable hibernation, instead supporting a &lt;a href=&quot;#hybrid-suspend&quot;&gt;hybrid suspend&lt;/a&gt; it calls &lt;a href=&quot;https://support.apple.com/guide/mac-help/what-is-safe-sleep-mh10328/mac&quot;&gt;safe sleep&lt;/a&gt; &lt;a href=&quot;#fnref:machibernate&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:resetvector&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;“The reset vector of a processor is the default location where, upon a reset, the processor will go to find the first instruction to execute. In other words, the reset vector is a pointer or address where the processor should always begin its execution. This first instruction typically branches to the system initialization code.” &lt;a href=&quot;https://www.sciencedirect.com/topics/engineering/reset-vector&quot;&gt;Xiaocong Fan, Real-Time Embedded Systems, 2015&lt;/a&gt; &lt;a href=&quot;#fnref:resetvector&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:kernelnofreeze&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;All kernel threads are tagged with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PF_NOFREEZE&lt;/code&gt; by default, so they must specifically opt-in to task freezing. &lt;a href=&quot;#fnref:kernelnofreeze&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:freezer&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This is not from the docs, but from &lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/freezer.c?h=v5.15&amp;amp;id=8bb7eca972ad531c9b149c0a51ab43a417385813#n55&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel/freezer.c&lt;/code&gt;&lt;/a&gt; which also notes “Refrigerator is place where frozen processes are stored :-).” &lt;a href=&quot;#fnref:freezer&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:lowlevelresume&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This is the operation that &lt;a href=&quot;https://www.kernel.org/doc/html/latest/admin-guide/pm/sleep-states.html#hibernation&quot;&gt;requires&lt;/a&gt; “special architecture-specific low-level code”. &lt;a href=&quot;#fnref:lowlevelresume&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:netbsd&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Interestingly NetBSD has a setting to enable hibernation, but &lt;a href=&quot;https://www.netbsd.org/docs/guide/en/chap-power.html#chap-power-acpi-sleep-states&quot;&gt;does not actually support hibernation&lt;/a&gt; &lt;a href=&quot;#fnref:netbsd&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Thu, 06 Jan 2022 00:00:00 +0000</pubDate>
        <link>https://tookmund.com/2022/01/hibernate-docs</link>
        <guid isPermaLink="true">https://tookmund.com/2022/01/hibernate-docs</guid>
        
        <category>hibernate</category>
        
        
      </item>
    
      <item>
        <title>SSH Port Forwarding and the Command Cargo Cult</title>
        <description>&lt;h2 id=&quot;someone-is-wrong-on-the-internet&quot;&gt;Someone is Wrong on the Internet&lt;/h2&gt;
&lt;p&gt;If you look up how to only forward ports with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt;, you may come across
solutions like this:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh -nNT -L 8000:example.com:80 user@bastion.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Or perhaps this, if you also wanted to send &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; to the background:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh -NT -L 3306:db.example.com:3306 example.com &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Both of these use at least one option that is entirely redundant,
and the second can cause &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; to fail to connect if you happen to be
using password authentication.
However, they seem to still persist in various articles about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; port forwarding.
I myself was using the first variation until just recently, and I figured
I would write this up to inform others who might be still using these
solutions.&lt;/p&gt;

&lt;p&gt;The correct option for this situation is not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-nNT&lt;/code&gt; but simply
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-N&lt;/code&gt;, as in:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh -N -L 8000:example.com:80 user@bastion.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;If you want to also send &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; to the background,
then you’ll want to add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-f&lt;/code&gt; instead of using your shell’s built-in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;
feature, because you can then input passwords into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; if necessary&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Honestly, that’s the point of this article, so you can stop here
if you want. If you’re looking for a detailed explaination of what
each of these options actually does, or if you have no idea what
I’m talking about, read on!&lt;/p&gt;

&lt;h2 id=&quot;what-is-ssh-port-forwarding&quot;&gt;What is SSH Port Forwarding?&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; is a powerful tool for remote access to servers,
allowing you to execute commands on a remote machine.
It can also forward ports
through a secure tunnel with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-L&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-R&lt;/code&gt; options.
Basically, you can forward a connection to a local port to a remote server
like so:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh -L 8080:other.example.com:80 ssh.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In this example, you connect to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh.example.com&lt;/code&gt; and then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; forwards
any traffic on your local machine port 8080&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;
to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;other.example.com&lt;/code&gt; port 80 via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh.example.com&lt;/code&gt;.
This is a really powerful feature, allowing you to jump&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; inside your firewall
with just an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; server exposed to the world.&lt;/p&gt;

&lt;p&gt;It can work in reverse as well with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-R&lt;/code&gt; option, allowing connections
on a remote host in to a server running on your local machine.
For example, say you were running a website on your local machine on port 8080
but wanted it accessible on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com&lt;/code&gt; port 80&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.
You could use something like:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh -R 8080:example.com:80 example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The trouble with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; port forwarding is that, absent any additional options,
you also open a shell on the remote machine.
If you’re planning to both work on a remote machine and use it to forward
some connection, this is fine, but if you just need to forward a port quickly
and don’t care about a shell at that moment, it can be annoying, especially since
if the shell closes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; will close the forwarding port as well.&lt;/p&gt;

&lt;p&gt;This is where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-N&lt;/code&gt; option comes in.&lt;/p&gt;

&lt;h2 id=&quot;ssh-just-forwarding-ports&quot;&gt;SSH just forwarding ports&lt;/h2&gt;
&lt;p&gt;In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; manual page&lt;sup id=&quot;fnref:5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-N&lt;/code&gt; is explained like so:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Do not execute a remote command.  This is useful for just forwarding ports.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is all we need. It instructs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; to run no commands on the remote server,
just forward the ports specified in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-L&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-R&lt;/code&gt; options.
But people seem to think that there are a bunch of other necessary options,
so what do those do?&lt;/p&gt;

&lt;h2 id=&quot;ssh-and-stdin&quot;&gt;SSH and stdin&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-n&lt;/code&gt; controls how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; interacts with &lt;a href=&quot;https://en.wikipedia.org/wiki/Standard_streams&quot;&gt;standard input&lt;/a&gt;,
specifically telling it not to:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Redirects stdin from /dev/null (actually, prevents reading from stdin).  This must be used when ssh is run in the
background.  A common trick is to use this to run X11 programs on a remote machine.  For example, ssh -n
shadows.cs.hut.fi emacs &amp;amp; will start an emacs on shadows.cs.hut.fi, and the X11 connection will be automatically for‐
warded over an encrypted channel.  The ssh program will be put in the background.  (This does not work if ssh needs to
ask for a password or passphrase; see also the -f option.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;ssh-passwords-and-backgrounding&quot;&gt;SSH passwords and backgrounding&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-f&lt;/code&gt; sends &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; to background, freeing up the terminal in which you ran &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt;
to do other things.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Requests ssh to go to background just before command execution.  This is useful if ssh is going to ask for passwords
or passphrases, but the user wants it in the background.  This implies -n.  The recommended way to start X11 programs
at a remote site is with something like ssh -f host xterm.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As indicated in the description of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-n&lt;/code&gt;, this does the same thing as using
&lt;a href=&quot;https://tldp.org/LDP/abs/html/special-chars.html#BGJOB&quot;&gt;the shell’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt; feature&lt;/a&gt;
with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-n&lt;/code&gt;, but allows you to put in any necessary passwords first.&lt;/p&gt;

&lt;h2 id=&quot;ssh-and-pseudo-terminals&quot;&gt;SSH and pseudo-terminals&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-T&lt;/code&gt; is a little more complicated than the others and has a very short
explanation:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Disable pseudo-terminal allocation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It has a counterpart in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t&lt;/code&gt;, which is explained a little better:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Force pseudo-terminal allocation.  This can be used to execute arbitrary screen-based programs on a remote machine,
which can be very useful, e.g. when implementing menu services.  Multiple -t options force tty allocation, even if ssh
has no local tty.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As the description of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t&lt;/code&gt; indicates, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; is allocating a pseudo-terminal on
the remote machine, not the local one.
However, I have confirmed&lt;sup id=&quot;fnref:6&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-N&lt;/code&gt; doesn’t allocate a pseudo-terminal either,
since it doesn’t run any commands.
Thus this option is entirely unnecessary.&lt;/p&gt;

&lt;h3 id=&quot;whats-a-pseudo-terminal&quot;&gt;What’s a pseudo-terminal?&lt;/h3&gt;

&lt;p&gt;This is a bit complicated, but basically it’s an interface used in UNIX-like
systems, like Linux or BSD, that pretends to be a terminal
(thus pseudo-terminal).
Programs like your shell, or any text-based menu system made in libraries
like ncurses, expect to be connected to one (when used interactively at least).
Basically it fakes as if the input it is given
(over the network, in the case of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt;) was typed on a physical terminal
device and do things like raise an interrupt (SIGINT) if Ctrl+C is pressed.&lt;/p&gt;

&lt;h2 id=&quot;why&quot;&gt;Why?&lt;/h2&gt;

&lt;p&gt;I don’t know why these incorrect uses of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; got passed around as correct,
but I suspect it’s a form of &lt;a href=&quot;https://en.wikipedia.org/wiki/Cargo_cult_programming&quot;&gt;cargo cult&lt;/a&gt;,
where we use example commands others provide and don’t question what they do.
One stack overflow answer I read that provided these options seemed to think
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-T&lt;/code&gt; was disabling the local pseudo-terminal, which might go some way towards
explaining why they thought it was necessary.&lt;/p&gt;

&lt;p&gt;I guess the moral of this story is to question everything and actually read
the manual, instead of just googling it.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Not that you SHOULD be using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; with password authentication anyway, but people do. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Only on your loopback address by default, so that you’re not allowing random people on your network to use your tunnel. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;In fact, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; even supports &lt;a href=&quot;https://man.openbsd.org/OpenBSD-6.9/ssh#J&quot;&gt;Jump Hosts&lt;/a&gt;, allowing you to automatically forward an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; connection through another machine. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I can’t say I recommend a setup like this for anything serious, as you’d need to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; as root to forward ports less than 1024. SSH forwarding is not for permanent solutions, just short-lived connections to machines that would be otherwise inaccessible. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Specifically, my source is the ssh(1) manual page in OpenSSH 8.4, shipped as 1:8.4p1-5 in Debian bullseye. &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I just forwarded ports with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-N&lt;/code&gt; and then logged in to that same machine and looked at psuedo-terminal allocations via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ps ux&lt;/code&gt;. No terminal is associated with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; connections using just the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-N&lt;/code&gt; option. &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sat, 02 Oct 2021 00:00:00 +0000</pubDate>
        <link>https://tookmund.com/2021/10/ssh-port-forwarding</link>
        <guid isPermaLink="true">https://tookmund.com/2021/10/ssh-port-forwarding</guid>
        
        
      </item>
    
      <item>
        <title>Command Line 101</title>
        <description>&lt;p&gt;How to Work in a Text-Only Environment.&lt;/p&gt;

&lt;h2 id=&quot;what-is-this-thing&quot;&gt;What is this thing?&lt;/h2&gt;
&lt;p&gt;When you first open a command-line (note that I use the terms command-line
and shell interchangably here, they’re basically the same, but command-line
is the more general term, and shell is the name for the program that executes
commands for you)
you’ll see something like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/cmd101/thisfolder.png&quot; alt=&quot;thisfolder&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This line is called a “command prompt” and it tells you four pieces of information:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jaadams&lt;/code&gt;: The username of the user that is currently running this shell.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bg7&lt;/code&gt;: The name of the computer that this shell is running on, important
for when you start accessing shells on remote machines.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/thisfolder&lt;/code&gt;: The folder or directory that your shell is currently
running in. Like a file explorer (like Window’s Explorer or Mac’s Finder) a
shell always has a “working directory,” from which all relative paths (see
sidenote below) are resolved.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you first opened a shell, however, you might notice that is looks more
like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/cmd101/home.png&quot; alt=&quot;home&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is a shorthand notation that the shell uses to make this output shorter
when possible. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; stands for your home directory, usually &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/&amp;lt;username&amp;gt;&lt;/code&gt;.
Like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\Users\&amp;lt;username&amp;gt;\&lt;/code&gt; on Windows or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Users/&amp;lt;username&amp;gt;&lt;/code&gt; on Mac,
this directory is where all your files should go by default.&lt;/p&gt;

&lt;p&gt;Thus a command prompt like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/cmd101/downloads.png&quot; alt=&quot;downloads&quot; /&gt;&lt;/p&gt;

&lt;p&gt;actually tells you that you are currently in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/jaadams/Downloads&lt;/code&gt;
directory.&lt;/p&gt;

&lt;h3 id=&quot;sidenote-the-unix-filesystem-and-relative-paths&quot;&gt;Sidenote: The Unix Filesystem and Relative Paths&lt;/h3&gt;

&lt;p&gt;“folders” on Linux and other Unix-derived systems like MacOS are usually
called “directories.”&lt;/p&gt;

&lt;p&gt;These directories are represented by paths, strings that indicate where the
directory is on the filesystem.&lt;/p&gt;

&lt;p&gt;The one unusual part is the so-called “root directory”.
All files are stored in this folder or directories under it.
Its path is just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; and there are no directories above it.&lt;/p&gt;

&lt;p&gt;For example, the directory called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;home&lt;/code&gt; typically contains all user directories.
This is stored in the root directory, and each users specific data
is stored in a directory named after that user under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;home&lt;/code&gt;.
Thus, the home directory of the user &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jacob&lt;/code&gt; is typically &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/jacob&lt;/code&gt;,
the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jacob&lt;/code&gt; under the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;home&lt;/code&gt; directory stored in the root directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you’re interested in more details about what goes in what directory,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man hier&lt;/code&gt; has the basics and the
&lt;a href=&quot;https://refspecs.linuxfoundation.org/FHS_3.0/fhs-3.0.pdf&quot;&gt;Filesystem Hierarchy Standard&lt;/a&gt;
governs the layout of the filesystem on most Linux distributions.&lt;/p&gt;

&lt;p&gt;You don’t always have to use the full path, however.
If the path does not begin with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;, it is assumed that the path actually
begins with the path of the current directory.
So if you use a path like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my/folders/here&lt;/code&gt;, and you’re in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/jacob&lt;/code&gt;
directory, the path will be treated like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/jacob/my/folders/here&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Each folder also contains the symbolic links &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;..&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt;.
Symbolic links are a very powerful kind of
file that is actually a reference to another file.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;..&lt;/code&gt; always represents the parent directory
of the current directory, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/jacob/..&lt;/code&gt; links to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/&lt;/code&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt; always links to the current directory, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/jacob/.&lt;/code&gt; links to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/jacob&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;running-commands&quot;&gt;Running commands&lt;/h2&gt;

&lt;p&gt;To run a command from the command prompt, you type its name and then
usually some arguments to tell it what to do.&lt;/p&gt;

&lt;p&gt;For example, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo&lt;/code&gt; command displays the text passed as arguments.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jacob@lovelace/home/jacob$ echo hello world
hello world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Arguments to commands are space-separated, so in the previous example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt;
is the first argument and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;world&lt;/code&gt; is the second. If you need an argument to
contain spaces, you’ll want to put quotes around it, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo &quot;like so&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Certain arguments are called “flags”, or “options” (options if they take another
argument, flags otherwise) usually prefixed with a hyphen,
and they change the way a program operates.&lt;/p&gt;

&lt;p&gt;For example, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt; command outputs the contents of a directory passed as
an argument, but if you add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-l&lt;/code&gt; before the directory, it will give you more
details on the files in that directory.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jacob@lovelace/tmp/test$ ls /tmp/test
1  2  3  4  5  6
jacob@lovelace/tmp/test$ ls -l /tmp/test
total 0
-rw-r--r-- 1 jacob jacob 0 Aug 26 22:06 1
-rw-r--r-- 1 jacob jacob 0 Aug 26 22:06 2
-rw-r--r-- 1 jacob jacob 0 Aug 26 22:06 3
-rw-r--r-- 1 jacob jacob 0 Aug 26 22:06 4
-rw-r--r-- 1 jacob jacob 0 Aug 26 22:06 5
-rw-r--r-- 1 jacob jacob 0 Aug 26 22:06 6
jacob@lovelace/tmp/test$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Most commands take different flags to change their behavior in various ways.&lt;/p&gt;

&lt;h3 id=&quot;file-management&quot;&gt;File Management&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd &amp;lt;path&amp;gt;&lt;/code&gt;: Change the current directory of the running shell to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;path&amp;gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls &amp;lt;path&amp;gt;&lt;/code&gt;: Output the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;path&amp;gt;&lt;/code&gt;. If no path is passed, it prints
the contents of the current directory.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;touch &amp;lt;filename&amp;gt;&lt;/code&gt;: create an new empty file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;filename&amp;gt;&lt;/code&gt;.
Used on an existing file, it updates the file’s last accessed and modified times.
Most text editors can also create a new file for you, which is probably more useful.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkdir &amp;lt;directory&amp;gt;&lt;/code&gt;: Create a new folder/directory at path &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;directory&amp;gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mv &amp;lt;src&amp;gt; &amp;lt;dest&amp;gt;&lt;/code&gt;: Move a file or directory at path &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;src&amp;gt;&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dest&amp;gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cp &amp;lt;src&amp;gt; &amp;lt;dest&amp;gt;&lt;/code&gt;: Copy a file or directory at path &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;src&amp;gt;&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dest&amp;gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rm &amp;lt;file&amp;gt;&lt;/code&gt;: Remove a file at path &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;file&amp;gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zip -r &amp;lt;zipfile&amp;gt; &amp;lt;contents...&amp;gt;&lt;/code&gt;: Create a zip file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;zipfile&amp;gt;&lt;/code&gt; with contents
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;contents&amp;gt;&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;contents&amp;gt;&lt;/code&gt; can be multiple arguments, and you’ll usually want
to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r&lt;/code&gt; argument when including directories in your zipfile, as otherwise
only the directory will be included and not the files and directories within it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;searching&quot;&gt;Searching&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep &amp;lt;thing&amp;gt; &amp;lt;file&amp;gt;&lt;/code&gt;: Look for the string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;thing&amp;gt;&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;file&amp;gt;&lt;/code&gt;.
If no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;file&amp;gt;&lt;/code&gt; is passed it searches standard input.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find &amp;lt;path&amp;gt; -name &amp;lt;name&amp;gt;&lt;/code&gt;: Find a file or directory called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;name&amp;gt;&lt;/code&gt; somwhere
under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;path&amp;gt;&lt;/code&gt;. This command is actually very powerful, but also very complex.
For example you can delete all files in a directory older than 30 days with:
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;find -mtime +30 -exec rm {}\;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;locate &amp;lt;name&amp;gt;&lt;/code&gt;: A much easier to use command to find a file with a given
name, but it is not usually installed by default.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;outputting-files&quot;&gt;Outputting Files&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat &amp;lt;files...&amp;gt;&lt;/code&gt;: Output (concatenate) all the files passed as arguments.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head &amp;lt;file&amp;gt;&lt;/code&gt;: Output the beginning of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;file&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tail &amp;lt;file&amp;gt;&lt;/code&gt;: Output the end of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;file&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;how-to-find-the-right-command&quot;&gt;How to Find the Right Command&lt;/h2&gt;

&lt;p&gt;All commands (at least on sane Linux distributions like Debian or Ubuntu)
are documented with a manual page, in man section 1 (for more information on
manual sections, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man intro&lt;/code&gt;).
This can be accessed using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man &amp;lt;command&amp;gt;&lt;/code&gt;
You can search for the right command using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-k&lt;/code&gt; flag, as in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man -k &amp;lt;search&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can also view manual pages in your browser, on sites like &lt;a href=&quot;https://manpages.debian.org&quot;&gt;https://manpages.debian.org&lt;/a&gt;
or &lt;a href=&quot;https://linux.die.net/man&quot;&gt;https://linux.die.net/man&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is not always helpful, however, because some command’s descriptions are
not particularly useful, and also there are a lot of manual pages, which can
make searching for a specific one difficult. For example, finding the right
command to search inside text files is quite difficult via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man&lt;/code&gt; (it’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt;).
When you can’t find what you need with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man&lt;/code&gt; I recommend falling back to
searching the Internet. There are lots of bad Linux tutorials out there, but
here are some reputable sources I recommend:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.cyberciti.biz&quot;&gt;https://www.cyberciti.biz&lt;/a&gt;: nixCraft has excellent tutorials on all things Linux&lt;/li&gt;
  &lt;li&gt;Hosting providers like Digital Ocean or Linode: Good intro documentation, but
can sometimes be outdated&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://tldp.org&quot;&gt;https://tldp.org&lt;/a&gt;: The Linux Documentation project is great, but it can also be a little
outdated sometimes.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com&quot;&gt;https://stackoverflow.com&lt;/a&gt;: Oftentimes has great answers, but quality varies wildly
since anyone can answer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are certainly not the only options but they’re the sources I would
recommend when available.&lt;/p&gt;

&lt;h3 id=&quot;how-to-read-a-manual-page&quot;&gt;How to Read a Manual Page&lt;/h3&gt;

&lt;p&gt;Manual pages consist of a series of sections, each with a specific purpose.
Instead of attempting to write my own description here, I’m going to borrow
the excellent one from &lt;a href=&quot;https://tldp.org/HOWTO/Man-Page/q3.html&quot;&gt;The Linux Documentation Project&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;The NAME section&lt;/p&gt;

  &lt;p&gt;…is the only required section. Man pages without a name section are as useful as refrigerators at the north pole. This section also has a standardized format consisting of a comma-separated list of program or function names, followed by a dash, followed by a short (usually one line) description of the functionality the program (or function, or file) is supposed to provide. By means of makewhatis(8), the name sections make it into the whatis database files. Makewhatis is the reason the name section must exist, and why it must adhere to the format I described.
(Formatting explanation cut for brevity)&lt;/p&gt;

  &lt;p&gt;The SYNOPSIS section&lt;/p&gt;

  &lt;p&gt;…is intended to give a short overview on available program options. For functions this sections lists corresponding include files and the prototype so the programmer knows the type and number of arguments as well as the return type.&lt;/p&gt;

  &lt;p&gt;The DESCRIPTION section&lt;/p&gt;

  &lt;p&gt;…eloquently explains why your sequence of 0s and 1s is worth anything at all. Here’s where you write down all your knowledge. This is the Hall Of Fame. Win other programmers’ and users’ admiration by making this section the source of reliable and detailed information. Explain what the arguments are for, the file format, what algorithms do the dirty jobs.&lt;/p&gt;

  &lt;p&gt;The OPTIONS section&lt;/p&gt;

  &lt;p&gt;…gives a description of how each option affects program behaviour. You knew that, didn’t you?&lt;/p&gt;

  &lt;p&gt;The FILES section&lt;/p&gt;

  &lt;p&gt;…lists files the program or function uses. For example, it lists configuration files, startup files, and files the program directly operates on.
(Cut details about installing files)&lt;/p&gt;

  &lt;p&gt;The ENVIRONMENT section&lt;/p&gt;

  &lt;p&gt;…lists all environment variables that affect your program or function and tells how, of course. Most commonly the variables will hold pathnames, filenames or default options.&lt;/p&gt;

  &lt;p&gt;The DIAGNOSTICS section&lt;/p&gt;

  &lt;p&gt;…should give an overview of the most common error messages from your program and how to cope with them. There’s no need to explain system error error messages (from perror(3)) or fatal signals (from psignal(3)) as they can appear during execution of any program.&lt;/p&gt;

  &lt;p&gt;The BUGS section&lt;/p&gt;

  &lt;p&gt;…should ideally be non-existent. If you’re brave, you can describe here the limitations, known inconveniences and features that others may regard as misfeatures. If you’re not so brave, rename it the TO DO section ;-)&lt;/p&gt;

  &lt;p&gt;The AUTHOR section&lt;/p&gt;

  &lt;p&gt;…is nice to have in case there are gross errors in the documentation or program behaviour (Bzzt!) and you want to mail a bug report.&lt;/p&gt;

  &lt;p&gt;The SEE ALSO section&lt;/p&gt;

  &lt;p&gt;…is a list of related man pages in alphabetical order. Conventionally, it is the last section.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;remote-access&quot;&gt;Remote Access&lt;/h2&gt;
&lt;p&gt;One of the more powerful uses of the shell is through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt;, the secure shell.
This allows you to remotely connect to another computer and run a shell on that
machine:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@host:~$ ssh other@example.com
other@example:~$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The prompt changes to reflect the change in user and host,
as you can see in the example above.
This allows you to work in a shell on that machine as if it was right in front
of you.&lt;/p&gt;

&lt;h3 id=&quot;moving-files-between-machines&quot;&gt;Moving Files Between Machines&lt;/h3&gt;
&lt;p&gt;There are several ways you can move files between machines over ssh.
The first and easiest is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scp&lt;/code&gt;, which works much like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cp&lt;/code&gt; command
except that paths can also take a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user@host&lt;/code&gt; argument to move files across
computers. For example, if you wanted to move a file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test.txt&lt;/code&gt; to your
home directory on another machine, the command would look like:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scp test.txt other@example.com:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;(The home directory is the default path)&lt;/p&gt;

&lt;p&gt;Otherwise you can move files by reversing the order of the arguments
and put a path after the colon to move files from another directory on the
remote host. For example, if you wanted to fetch the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/issue.net&lt;/code&gt;
from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scp other@example.com:/etc/issue.net .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Another option is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sftp&lt;/code&gt; command, which gives you a very simple shell-like
interface in which you can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt;, before either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;put&lt;/code&gt;ing files onto
the local machine or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get&lt;/code&gt;ing files off of it.&lt;/p&gt;

&lt;p&gt;The final and most powerful option is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt; which syncs the contents of one
directory to another, and doesn’t copy files that haven’t changed. It’s powerful
and complex, however, so I recommend reading the USAGE section of its man page.&lt;/p&gt;

&lt;h3 id=&quot;long-running-commands&quot;&gt;Long-Running Commands&lt;/h3&gt;
&lt;p&gt;The one problem with ssh is that it will stop any command running in your
shell when you disconnect. If you want to leave something on and come back
later then this can be a problem.&lt;/p&gt;

&lt;p&gt;This is where terminal multiplexers come in. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screen&lt;/code&gt; both allow
you to run a shell in a safe environment where it will continue even if you
disconnect from it. You do this by running the command without any arguments,
i.e. just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux&lt;/code&gt; or just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screen&lt;/code&gt;.
In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux&lt;/code&gt; you can disconnect from the current session by
pressing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+b&lt;/code&gt; then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt;, and reattach with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux attach&lt;/code&gt; command.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screen&lt;/code&gt; works similarly, but with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+a&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screen -r&lt;/code&gt; to
reattach.&lt;/p&gt;

&lt;h2 id=&quot;command-inputs-and-outputs&quot;&gt;Command Inputs and Outputs&lt;/h2&gt;

&lt;p&gt;Arguments are not the only way to pass input to a command. They can also take
input from what’s called “standard input”, which the shell usually connects to
your keyboard.&lt;/p&gt;

&lt;p&gt;Output can go to two places, standard output and standard error, both of which
are directed to the screen by default.&lt;/p&gt;

&lt;h2 id=&quot;redirecting-io&quot;&gt;Redirecting I/O&lt;/h2&gt;
&lt;p&gt;Note that I said above that standard input/output/error are only “usually”
connected to the keyboard and the terminal? This is because you can redirect
them to other places with the shell operators &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; and the very powerful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;file-redirects&quot;&gt;File redirects&lt;/h3&gt;
&lt;p&gt;The operators &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; redirect the input and output of a command to a file.
For example, if you wanted a file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list.txt&lt;/code&gt; that contained a list of
all the files in a directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/this/one/here&lt;/code&gt; you could use:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ls /this/one/here &amp;gt; list.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;pipelines&quot;&gt;Pipelines&lt;/h3&gt;
&lt;p&gt;The pipe character, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt;, allows you to direct the output of one command into
the input of another. This can be very powerful.
For example, the following pipeline lists the contents of the current directory
searches for the string “test”, then counts the number of results.
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wc -l&lt;/code&gt; counts the number of lines in its input)&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ls | grep test | wc -l
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For a better, but even more contrived example, say you have a file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;myfile&lt;/code&gt;,
with a bunch of lines of potentially duplicated and unsorted data&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;test
test
1234
4567
1234
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You can sort it and output only the unique lines with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sort&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uniq&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ uniq &amp;lt; myfile | sort
1234
1234
4567
test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;save-yourself-some-typing-globs-and-tab-completion&quot;&gt;Save Yourself Some Typing: Globs and Tab-Completion&lt;/h2&gt;

&lt;p&gt;Sometimes you don’t want to type out the whole filename when writing out a
command. The shell can help you here by autocompleting when you press the tab
key.&lt;/p&gt;

&lt;p&gt;If you have a whole bunch of files with the same suffix, you can refer to them
when writing arguments as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.suffix&lt;/code&gt;. This also works with prefixes, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prefix*&lt;/code&gt;,
and in fact you can put a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; anywhere, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*middle*&lt;/code&gt;. The shell will “expand” that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; into all the files in that directory that match your criteria
(ending with a specific suffix, starting with a specific prefix, and so on)
and pass each file as a separate argument to the command.&lt;/p&gt;

&lt;p&gt;For example, if I have a series of files called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.txt&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.txt&lt;/code&gt;, and so on
up to 9, each containing just the number for which it’s named, I could use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat&lt;/code&gt; to output all of them like so:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jacob@lovelace/tmp/numbers$ ls
1.txt  2.txt  3.txt  4.txt  5.txt  6.txt  7.txt  8.txt	9.txt
jacob@lovelace/tmp/numbers$ cat *.txt
1
2
3
4
5
6
7
8
9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Also the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; shorthand mentioned above that refers to your home directory
can be used when passing a path as an argument to a command.&lt;/p&gt;

&lt;h2 id=&quot;ifs-and-for-loops&quot;&gt;Ifs and For loops&lt;/h2&gt;

&lt;p&gt;The files in the above example were generated with the following shell
commands:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for i in 1 2 3 4 5 6 7 8 9
do
echo $i &amp;gt; $i.txt
done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But I’ll have to save variables, conditionals and loops for another day because
this is already too long. Needless to say the shell is a full programming
language, although a very ugly and dangerous one.&lt;/p&gt;
</description>
        <pubDate>Mon, 31 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://tookmund.com/2020/08/command-line-101</link>
        <guid isPermaLink="true">https://tookmund.com/2020/08/command-line-101</guid>
        
        <category>ACM@WM</category>
        
        
      </item>
    
  </channel>
</rss>
