<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tech Otaku</title>
	<atom:link href="https://www.tech-otaku.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.tech-otaku.com</link>
	<description></description>
	<lastBuildDate>Sat, 09 Aug 2025 14:38:58 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://www.tech-otaku.com/wp-content/uploads/MiGeek-MiOtaku_400x400-70x70.jpg</url>
	<title>Tech Otaku</title>
	<link>https://www.tech-otaku.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Enable Root Login Over SSH to Multipass Virtual Machines</title>
		<link>https://www.tech-otaku.com/vps/enable-root-login-over-ssh-to-multipass-virtual-machines/</link>
					<comments>https://www.tech-otaku.com/vps/enable-root-login-over-ssh-to-multipass-virtual-machines/#comments</comments>
		
		<dc:creator><![CDATA[Steve]]></dc:creator>
		<pubDate>Thu, 25 Mar 2021 19:55:12 +0000</pubDate>
				<category><![CDATA[VPS]]></category>
		<category><![CDATA[Multipass]]></category>
		<category><![CDATA[SSH]]></category>
		<category><![CDATA[VM]]></category>
		<category><![CDATA[VMware Fusion]]></category>
		<guid isPermaLink="false">https://www.tech-otaku.com/?p=8477</guid>

					<description><![CDATA[I&#8217;ve recently forsaken VMware Fusion in favour of Canonical&#8217;s Multipass to create and manage Ubuntu Server VMs on macOS. There are two things I want to be able to do with Ubuntu Server VMs: establish an SSH connection as root and navigate the file system using applications such as Forklift and FileZilla. Purists and more [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve recently forsaken VMware Fusion in favour of Canonical&#8217;s <a href="https://multipass.run" target="_blank" rel="noopener">Multipass</a> to create and manage Ubuntu Server <abbr title="Virtual Machine">VM</abbr>s on macOS.</p>
<p>There are two things I want to be able to do with Ubuntu Server VMs: establish an <abbr title="Secure Shell">SSH</abbr> connection as <code class="system-font dark">root</code> and navigate the file system using applications such as Forklift and FileZilla. Purists and more security-minded individuals may balk at this, but these VMs are local, non-production servers purely for testing.</p>
<p><span id="more-8477"></span></p>
<p>NOTE: If you have both VMware Fusion and Multipass installed on the same machine, take a look at <a href="#fusion">Possible Conflict between VMware Fusion and Multipass</a> at the foot of this article.</p>
<p>Throughout this article the following terms are used:</p>
<table style="width: 100%;margin-left: auto;margin-right: auto">
<col style="width: 25%">
<col style="width: 75%">
<tr>
<th style="border-right: none;padding-left: 0">Term</th>
<th style="border-right: none;padding-left: 0">Definition</th>
</tr>
<tr>
<td><i>host</i></td>
<td>The machine or OS on which Multipass is installed.</td>
</tr>
<tr>
<td><i>guest instance</i></td>
<td>The Multipass VM.</td>
</tr>
<tr>
<td><i>client</i></td>
<td>The machine initiating a connection to another (virtual) machine.</td>
</tr>
<tr>
<td><i>server</i></td>
<td>The (virtual) machine being connected to by a <i>client</i>.</td>
</tr>
<tr>
<td><i>identity file</i></td>
<td>The file containing the private key necessary to authenticate a user on the <i>guest instance</i> or <i>server</i>. The identity file is stored on the <i>host</i> or <i>client</i>.</td>
</tr>
<tr>
<td><i>host key</i></td>
<td>The public or private key used to authenticate the <i>guest instance</i> or <i>server</i> to the <i>host</i> or <i>client</i>. The public key is stored on the <i>host</i> or <i>client</i> and the private key is stored on the <i>guest instance</i> or <i>server</i>.</td>
</tr>
</table>
<p class="post-image-caption">Glossary of terms</p>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p>To demonstrate, I&#8217;ll be using macOS as the host <abbr title="Operating System">OS</abbr> and a Multipass guest instance named <code class="system-font dark">foo</code> with an <abbr title="Internet Protocol">IP</abbr> address of <code class="system-font dark">172.16.170.4</code> running <code class="system-font dark">Ubuntu 20.04 LTS</code>. A standard user with <code class="system-font dark">sudo</code> privileges named <code class="system-font dark">ubuntu</code> is created by default on every new guest instance:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
multipass list
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
Name                State             IPv4             Image
foo                 Running           172.16.170.4     Ubuntu 20.04 LTS
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>There are two built-in commands to connect with a guest instance. The first is the <code class="system-font boxed">exec</code> command which simply executes a command on the running guest instance. If it isn&#8217;t running, the <code class="system-font boxed">exec</code> command fails:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
multipass exec foo -- whoami
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output (Success)</div>
<pre>
ubuntu
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output (Failure)</div>
<pre>
exec failed: instance "foo" is not running
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>The second is <code class="system-font boxed">shell</code> or <code class="system-font boxed">sh</code> which opens an interactive login shell on the running guest instance. If the guest instance isn&#8217;t running, an attempt is made to first start it:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
multipass shell foo
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Neither of these methods can be used to configure connections in applications like Forklift or FileZilla. These and other file transfer applications typically use <abbr title="SSH File Transfer Protocol">SFTP</abbr> to transfer files to and from the client and server. Using SFTP, an encrypted SSH connection is first established by the client to the server. Files are then transferred using <abbr title="File Transfer Protocol">FTP</abbr> over the SSH connection.</p>
<p>When establishing an SSH connection, we need to be mindful of the authentication method used by the server. Typically this is public key authentication and Multipass guest instances are no exception. Public key authentication requires both a public and private key. Multipass generates this key pair using the RSA algorithm with a 2048-bit key length and uses the same key pair for both the <code class="system-font dark">ubuntu</code> and <code class="system-font dark">root</code> users.</p>
<p>The private key is stored in an identity file on the host. For macOS, this identity file is <code class="system-font boxed">/var/root/Library/Application Support/multipassd/ssh-keys/id_rsa</code><sup><b>1</b></sup> and is created when Multipass is installed. The corresponding public key is included in the <dfn title="cloud-init data provided by the entity i.e. Multipass that launches an instance">vendor-data</dfn> that Multipass gives to <code class="system-font boxed">cloud-init</code> when the guest instance is initialised and is written to <code class="system-font boxed">/home/ubuntu/.ssh/authorized_keys</code> and <code class="system-font boxed">/root/.ssh/authorized_keys</code> on the guest instance.</p>
<p></code><sup><b>1</b></sup> On a Linux host with Multipass installed via Snap the identity file is <code class="system-font boxed">/var/snap/multipass/common/data/multipassd/ssh-keys/id_rsa</code>.</p>
<p>Because of its location on the host, superuser privileges are required to read the identity file. Using <code class="system-font boxed">sudo</code> on the command line is not an issue although by doing so the guest instance&#8217;s public host keys (<code class="system-font dark">ed25519</code>, <code class="system-font dark">rsa</code> and <code class="system-font dark">ecdsa</code>) are added to <code class="system-font boxed">/var/root/.ssh/known_hosts</code> on the host not <code class="system-font boxed">~/.ssh/known_hosts</code>. This is important to remember if attempting to remove public host keys for a given instance from the <code class="system-font boxed">known_hosts</code> file:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
sudo ssh-keygen -R 172.16.170.4 -f /var/root/.ssh/known_hosts
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>However, the requirement for using <code class="system-font boxed">sudo</code> is a problem when configuring SFTP connections in Forklift or FileZilla as it&#8217;s not possible to elevate an admin user&#8217;s privileges to those of the superuser. One way to overcome this is to copy the identity file to a new location accessible to the admin user:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
mkdir -p ~/.ssh/multipass &amp;&amp; sudo cp /var/root/Library/Application\ Support/multipassd/ssh-keys/id_rsa $_
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>This first creates a sub-directory named <code class="system-font boxed">multipass</code> in the admin user&#8217;s <code class="system-font boxed">.ssh</code> directory, then copies the identity file to it. The <code class="system-font boxed">$_</code> at the end of the <code class="system-font boxed">cp</code> command is a special parameter which expands to the last argument &#8211; <code class="system-font boxed">~/.ssh/multipass</code> – passed to the previous command &#8211; <code class="system-font boxed">mkdir</code>.</p>
<p>The duplicate file has the same <code class="system-font dark">root:wheel</code> ownership as the original. This needs to be changed to <code class="system-font boxed">$USER:staff</code>:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
sudo chown $USER:staff ~/.ssh/multipass/id_rsa
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>In addition, the duplicate identity file&#8217;s permissions are read-only (<code class="system-font dark">400</code>), the same as the original. When using FileZilla, you may need to change the format of the private key. See <a href="#filezilla">FileZilla can&#8217;t Read the Private Key</a> at the end of this article. To do so, the permissions must first be changed to read-write (<code class="system-font dark">600</code>):</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
chmod 600 ~/.ssh/multipass/id_rsa
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Now the private key is in the correct location, let&#8217;s try to establish an SSH connection to the guest instance named <code class="system-font dark">foo</code> using the standard user <code class="system-font dark">ubuntu</code>. The location of the identity file is specified using the <code class="system-font boxed">-i</code> option. The instance must first be running or the connection will timeout:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
ssh -i ~/.ssh/multipass/id_rsa ubuntu@172.16.170.4
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The credentials used to successfully establish an SSH connection to the guest instance can now be used to configure an SFTP connection in Forklift or FileZilla by specifying the location of the identity file, but what if we want to connect as the guest instance&#8217;s root user.</p>
<p>It&#8217;s possible to open a non-login shell with <code class="system-font dark">root</code> access on a running guest instance using the built-in <code class="system-font boxed">exec</code> command:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
multipass exec foo -- sudo su
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>This is no different from executing <code class="system-font boxed">sudo su</code> having first logged-in using the standard user account <code class="system-font dark">ubuntu</code> on the guest instance and as such doesn&#8217;t allow for the configuration of SFTP connections in file transfer applications.</p>
<p>Let&#8217;s see if it&#8217;s possible to establish an SSH connection to the guest instance using its <code class="system-font dark">root</code> user. We use the same command syntax as before, but substitute <code class="system-font boxed">root</code> for <code class="system-font boxed">ubuntu</code>:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
ssh -i ~/.ssh/multipass/id_rsa root@172.16.170.4
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
Please login as the user "ubuntu" rather than the user "root".

Connection to 172.16.170.4 closed.
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>It&#8217;s pretty clear from the output that this isn&#8217;t possible. However, let&#8217;s take a look at the <code class="system-font boxed">/root/.ssh/authorized_keys</code> file on the guest instance:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Guest Instance</div>
<pre>
sudo cat /root/.ssh/authorized_keys
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
no-port-forwarding,no-agent-forwarding,no-X11-forwarding,command="echo 'Please login as the user \"ubuntu\" rather than the user \"root\".';echo;sleep 10;exit 142" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCz3PNy+AIaX4jTgvTw0VtrAxnH53kpOjiVnbjM27fMkXFUIZN1Fa16XynrVzg6pGaUrFYUJhK5OCXzZJ6DwcWQG1QYxI1TGytraJa3osTU72EZh71vsD+7EP6+M2MzxK7B7oQDh6GTt17f4dG5GPOHEdueG0qHhRM5A9WhiWvDCYUcFHm/eFfYAGQTEz103faMl7frl5Vq5VdJQBjVEVIKfnEtfP3vRGcuUfi+IRfzYS4L1dxX5blnj5Im39YMh31aBXxl/Fo4Atb6PKOAnoaR4wHBTDik+2q4vHhmfPDXPAcX3gUyWjQ9nyBLqpjptVF6rnPIMv228/WwwnVRB/ED ubuntu@localhost
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>As is evident from the output, the public key is prefixed with:</p>
<pre>
no-port-forwarding,no-agent-forwarding,no-X11-forwarding,<span class="reverse">command="echo 'Please login as the user \"ubuntu\" rather than the user \"root\".';echo;sleep 10;exit 142"</span>
</pre>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>This string is the default value of the <code class="system-font boxed">disable_root_opts</code> configuration key used by cloud-init and the highlighted code is responsible for displaying an error message, waiting 10 seconds and then exiting, effectively denying <code class="system-font dark">root</code> login.</p>
<p>To be able to establish an SSH connection as <code class="system-font dark">root</code>, this code has to be removed either manually by opening the file with <code class="system-font boxed">nano</code> or similar editor or alternatively using <code class="system-font boxed">sed</code>:</p>
<p><span class="meks-dummy-tab">;<br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Guest Instance</div>
<pre>
sudo sed -i.$(date +"%Y%m%d-%H%M%S") 's/,command.*exit 142"//' /root/.ssh/authorized_keys
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Alternatively, if you pass <dfn title="cloud-init data provided by the user when a guest instance is initialised">user-data</dfn> to <code class="system-font boxed">cloud-init</code> to bootstrap Multipass guest instances you could include either the <code class="system-font boxed">disable_root</code> or the <code class="system-font boxed">disable_root_opts</code> configuration keys in your cloud-init configuration file to control the root user&#8217;s access.</p>
<p>The default value for <code class="system-font boxed">disable_root</code> is true which causes the value of <code class="system-font boxed">disable_root_opts</code> to be pre-pended to the public key in the <code class="system-font boxed">authorized_keys</code> file. We&#8217;ve already seen what this default value is, so the first method is to provide a new value for the <code class="system-font boxed">disable_root_opts</code> configuration key in your cloud-init configuration file, omitting the offending code:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">config.yaml</div>
<pre class="brush: yaml;">
#cloud-config
...
disable_root_opts: no-port-forwarding,no-agent-forwarding,no-X11-forwarding
...
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>In the second method, we change the disable_root configuration key to false which effectively ignores the the <code class="system-font boxed">disable_root_opts</code> configuration key and results in nothing being pre-pended to the public key:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">config.yaml</div>
<pre class="brush: yaml;">
#cloud-config
...
disable_root: false
...
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>Multipass guest instances can now be created using:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
multipass launch --name foo --cloud-init config.yaml
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>It should now be possible to establish an SSH connection to the guest instance using its <code class="system-font dark">root</code> user:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
ssh -i ~/.ssh/multipass/id_rsa root@172.16.170.4
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>These same credentials can be used to configure SFTP connections to the guest instance using its <code class="system-font dark">root</code> user in Forklift and FileZilla.</p>
<h4>NOTES</h4>
<h5 id="fusion">Possible Conflict between VMware Fusion and Multipass</h5>
<p>If both Multipass and VMware Fusion are installed on your machine it&#8217;s worth noting that by default VMware Fusion VMs are configured to share the IP address of the Mac on the external network under <i>Settings</i> &gt; <i>Network Adapter</i> &gt; <i>Share with my Mac</i>. Before starting a VMware Fusion VM ensure that no Multipass guest instances are running by executing <code class="system-font boxed">multipass stop --all</code>. If any Multipass guest instances are running, VMware Fusion displays the error <code class="system-font dark">Could not connect 'Ethernet0' to virtual network '/dev/vmnet8'</code>. The VMware Fusion VM will start, but will be unable to connect to the Internet.</p>
<p>A workaround to having both Multipass guest instances and VMware Fusion VMs running at the same time is to reconfigure the VMware Fusion VM&#8217;s network adapter to use Wi-Fi  with <i>Settings</i> &gt; <i>Network Adapter</i> &gt; <i>Wi-Fi</i> before starting the VMware Fusion VM.</p>
<p>However, starting a VMware Fusion VM while a Multipass guest instance is running will most likely cause issues with Multipass as well. If this occurs, first stop and then start the Multipass daemon – <code class="system-font dark">multipassd</code> – before restarting the guest instance:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
sudo launchctl unload /Library/LaunchDaemons/com.canonical.multipassd.plist &amp;&amp; sudo launchctl load /Library/LaunchDaemons/com.canonical.multipassd.plist
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<h5 id="filezilla">FileZilla can&#8217;t Read the Private Key</h5>
<p>FileZilla appears unable to read the private key in the identity file. It displays a <i>Could not load key file</i> error. The header of the private key is <code class="system-font boxed">-----BEGIN PRIVATE KEY-----</code> and the Base64-encoded text begins <code class="system-font boxed">MII...IBADAN</code> which identifies it as an unencrypted private key in Base64-encoded PKCS#8 format.</p>
<p>I couldn&#8217;t find any documentation to confirm if or explain why FileZilla doesn&#8217;t like this format, but FileZilla will accept the private key if it is first converted to the new OpenSSH format. This conversion appears to be as simple as setting a new empty passphrase – the original passphrase is also empty &#8211; using <code class="system-font boxed">ssh-keygen</code>:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Host</div>
<pre>
ssh-keygen -p -N '' -f ~/.ssh/multipass/id_rsa
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The private key remains unencrypted, but its header is now <code class="system-font boxed">-----BEGIN OPENSSH PRIVATE KEY-----</code>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-otaku.com/vps/enable-root-login-over-ssh-to-multipass-virtual-machines/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8477</post-id>	</item>
		<item>
		<title>Using Python to Loop Through JSON-Encoded Data</title>
		<link>https://www.tech-otaku.com/mac/using-python-to-loop-through-json-encoded-data/</link>
					<comments>https://www.tech-otaku.com/mac/using-python-to-loop-through-json-encoded-data/#comments</comments>
		
		<dc:creator><![CDATA[Steve]]></dc:creator>
		<pubDate>Thu, 23 Jul 2020 13:47:16 +0000</pubDate>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[macOS]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://www.tech-otaku.com/?p=7271</guid>

					<description><![CDATA[The popularity of JSON is due in large part to its use of universal data structures such as objects and arrays that are supported in one form or another by the majority of programming languages. This post looks at the basic structure of JSON-encoded data, how that structure relates to Python data structures and using [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The popularity of <abbr title="JavaScript Object Notation">JSON</abbr> is due in large part to its use of universal data structures such as objects and arrays that are supported in one form or another by the majority of programming languages. This post looks at the basic structure of JSON-encoded data, how that structure relates to Python data structures and using Python to reliably access JSON-encoded data.</p>
<p><span id="more-7271"></span></p>
<h4>Using The Python Code Examples</h4>
<p>All the Python code examples in this post were tested using Python 3.8.2 (macOS) and Python 3.6.9 (Ubuntu) and can be run using the Python <a href="https://docs.python.org/3/tutorial/interpreter.html" target="_blank" rel="noopener noreferrer">interpreter</a>.</p>
<p>The examples assume the file <code class="system-font boxed">macos.json</code> is located in your home directory: <code class="system-font boxed">/User/username</code> (macOS) and <code class="system-font boxed">/home/username</code> (Ubuntu).</p>
<p>If pasting code examples containing a <code class="system-font boxed">for</code> loop or <code class="system-font boxed">with</code> statement, press enter twice to execute the code and return to the <code class="system-font boxed">&gt;&gt;&gt;</code> Python interpreter prompt.</p>
<h4>The Structure of JSON-encoded Data</h4>
<p>A more detailed description on the structure of JSON-encoded data can be found <a href="https://www.json.org/json-en.html" target="_blank" rel="noopener noreferrer">here</a>, but for the purposes of this post:</p>
<ul>
<li style="list-style-type: disc">JSON-encoded data consists of <i>arrays</i>, <i>objects</i>, <i>values</i> and <i>name/value pairs</i>.</li>
<li style="list-style-type: disc">An <i>array</i> is surrounded by square brackets <code class="system-font boxed">[...]</code> and contains a comma-separated list of <i>values</i>.</li>
<li style="list-style-type: disc">An <i>object</i> is surrounded by braces <code class="system-font boxed">{...}</code> and contains a comma-separated list of <i>name/value pairs</i>.</li>
<li style="list-style-type: disc">A <i>name/value pair</i> consists of a name in double quotes <code class="system-font boxed">"..."</code>, followed by a colon <code class="system-font boxed">:</code>, followed by a <i>value</i>.</li>
<li style="list-style-type: disc">A <i>value</i> can be a string, a number, a boolean, null, another <i>array</i> or another <i>object</i>.</li>
</ul>
<p>Consider the following file containing JSON-encoded data on two versions of macOS:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">macos.json</div>
<pre class="brush: json; gutter: false;">
{
    "updated": "2020-07-09",
    "versions": [
        {
            "family": "macOS",
            "version": "10.14",
            "codename": "Mojave",
            "announced": "2018-06-04",
            "released": "2018-09-24"
        },
        {
            "family": "macOS",
            "version": "10.15",
            "codename": "Catalina",
            "announced": "2019-06-03",
            "released": "2019-10-07"
        }
    ]
}
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<ul>
<li style="list-style-type: disc">The top-level object defines two name/value pairs.</li>
<li style="list-style-type: disc">The first is <code class="system-font boxed">updated</code> and has a string value of <code class="system-font boxed">2020-07-09</code> representing the date the information in the file was last updated.</li>
<li style="list-style-type: disc">The second is <code class="system-font boxed">versions</code> whose value is an array.</li>
<li style="list-style-type: disc">Each value in the <code class="system-font boxed">versions</code> array is an object representing a single macOS version.</li>
<li style="list-style-type: disc">Each object representing a single macOS version contains information on that version in the form of five name/value pairs: <code class="system-font boxed">family</code>, <code class="system-font boxed">version</code>, <code class="system-font boxed">codename</code>, <code class="system-font boxed">announced</code> and <code class="system-font boxed">released</code>. All values are strings.</li>
</ul>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<h4>Accessing JSON-encoded Data in Python</h4>
<p>To allow Python to access the JSON-encoded data we first need to open the file and then read its contents into memory. The latter is known as decoding or deserializing and in Python is performed using the <code class="system-font boxed">load()</code> method from Python&#8217;s <code class="system-font boxed">json</code> library. As part of this deserializing process a JSON array is converted to a Python <i>list</i> <code class="system-font boxed">[]</code> and a JSON object is converted to a Python <i>dictionary</i> <code class="system-font boxed">{}</code>.</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
import os
import json
f = open(os.environ["HOME"] + "/macos.json", "r", encoding="utf-8")
data = json.load(f)
f.close()
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The deserialized JSON-encoded data is now stored in the variable <code class="system-font boxed">data</code>. The output has been re-formatted for clarity:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data)
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: json; gutter: false;">
{   
	'updated': '2020-07-09',
    'versions': [
        {
            'family': 'macOS',
            'version': '10.14',
            'codename': 'Mojave',
            'announced': '2018-06-04',
            'released': '2018-09-24'
        },
        {   
            'family': 'macOS',
            'version': '10.15',
            'codename': 'Catalina',
            'announced': '2019-06-03',
            'released': '2019-10-07'
        }
    ]
}
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Apart from double-quotes <code class="system-font boxed">"</code> being replaced with single-quotes <code class="system-font boxed">'</code>, this output looks identical to the JSON-encoded data in our file. Remember however, what constitutes an array in the JSON-encoded data is now a Python list <code class="system-font boxed">[]</code> and what are objects in that same data are now Python dictionaries <code class="system-font boxed">{}</code>.</p>
<p>To access a specific piece of data we can use bracket notation. For example, to get the date the information was last updated:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data["updated"])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
2020-07-09
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To get specific information on a particular macOS version is a little more involved:</p>
<ul>
<li style="list-style-type: disc">Information on both macOS versions is contained in the <code class="system-font boxed">versions</code> list.</li>
<li style="list-style-type: disc">Each value of the <code class="system-font boxed">versions</code> list is a dictionary containing information on a single macOS version.</li>
<li style="list-style-type: disc">We can access the information in a specific dictionary by using its position or index in the <code class="system-font boxed">versions</code> list. As Python lists are zero-indexed, the first dictionary has an index of <code class="system-font boxed">0</code>, the second an index of <code class="system-font boxed">1</code>.</li>
</ul>
<p><b>NOTE</b>: <a href="https://jsoneditoronline.org/#left=url.https://raw.githubusercontent.com/tech-otaku/macos-versions/master/json/macos.json" target="_blank" rel="noopener noreferrer">JSON Editor Online</a> is a useful tool that displays JSON-encoded data showing the number of values in a list (JSON array) and each value&#8217;s index within that list. Please note you need to switch to <i>tree</i> view. Also, the code editor <a href="https://code.visualstudio.com" target="_blank" rel="noopener noreferrer">Visual Studio Code</a> has an <i>Outline</i> view that displays JSON-encoded data in a similar way.</p>
<p>So, to get the date macOS Mojave was announced we need to target the first dictionary of the <code class="system-font boxed">versions</code> list:</p>
<p> <span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data["versions"][0]["announced"])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
2018-06-04
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To get the dates both macOS Mojave and macOS Catalina were released we need to target the first dictionary of the <code class="system-font boxed">versions</code> list and then its second dictionary:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data["versions"][0]["released"]); \
print(data["versions"][1]["released"])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
2018-09-24
2019-10-07
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Let&#8217;s make things a little more interesting and add some more information for each macOS version to our JSON-encoded data:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">macos.json</div>
<pre class="brush: json; gutter: false;">
{
    "updated": "2020-07-09",
    "versions": [
        {
            "family": "macOS",
            "version": "10.14",
            "codename": "Mojave",
            "announced":"2018-06-04",
            "released": "2018-09-24",
            "requirements": [
                "iMac (Late 2012 or newer)",
                "iMac Pro (2017)",
                "Mac Mini (Late 2012 or newer)",
                "Mac Pro (Late 2013; Mid 2010 and Mid 2012 models with recommended Metal-capable graphics cards)",
                "MacBook (Early 2015 or newer)",
                "MacBook Air (Mid 2012 or newer)",
                "MacBook Pro (Mid 2012 or newer)",
                "2 GB of memory",
                "12.5 - 18.5 GB of available avaialable disk space",
                "OS X 10.8 or later"
            ],
            "releases": [
                {
                    "version": "10.14",
                    "build": "18A391",
                    "darwin": "18.0.0",
                    "released": "2018-09-24"
                },
                {
                    "version": "10.14.1",
                    "build": "18B75",
                    "darwin": "18.2.0",
                    "released": "2018-10-30"
                },
                {
                    "version": "10.14.2",
                    "build": "18C54",
                    "darwin": "18.2.0",
                    "released": "2018-12-05"
                },
                {
                    "version": "10.14.3",
                    "build": "18D42",
                    "darwin": "18.2.0",
                    "released": "2019-01-22"
                },
                {
                    "version": "10.14.4",
                    "build": "18E226",
                    "darwin": "18.5.0",
                    "released": "2019-03-25"
                },
                {
                    "version": "10.14.5",
                    "build": "18F132",
                    "darwin": "18.6.0",
                    "released": "2019-05-13"
                },
                {
                    "version": "10.14.6",
                    "build": "18G84",
                    "darwin": "18.7.0",
                    "released": "2019-07-22"
                }
            ]
        },
        {
            "family": "macOS",
            "version": "10.15",
            "codename": "Catalina",
            "announced":"2019-06-03",
            "released": "2019-10-07",
            "requirements": [
                "iMac (Late 2012 or newer)",
                "iMac Pro (2017)",
                "Mac Mini (Late 2012 or newer)",
                "Mac Pro (Late 2013)",
                "MacBook (Early 2015 or newer)",
                "MacBook Air (Mid 2012 or newer)",
                "MacBook Pro (Mid 2012 or newer)",
                "4 GB of memory",
                "12.5 GB of available avaialable disk space",
                "OS X 10.11.5 or later"
            ],
            "releases": [
                {
                    "version": "10.15",
                    "build": "19A583",
                    "darwin": "19.0.0",
                    "released": "2019-10-07"
                },
                {
                    "version": "10.15.1",
                    "build": "19B88",
                    "darwin": "19.0.0",
                    "released": "2019-10-29"
                },
                {
                    "version": "10.15.2",
                    "build": "19C57",
                    "darwin": "19.2.0",
                    "released": "2019-12-10"
                },
                {
                    "version": "10.15.3",
                    "build": "19D76",
                    "darwin": "19.3.0",
                    "released": "2020-01-28"
                },
                {
                    "version": "10.15.4",
                    "build": "19E266",
                    "darwin": "19.4.0",
                    "released": "2020-03-24"
                },
                {
                    "version": "10.15.5",
                    "build": "19F96",
                    "darwin": "19.5.0",
                    "released": "2020-05-26"
                }
            ]
        }
    ]
}
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>In Python, the updated JSON-encoded data in the file needs to be deserialized again:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
import os
import json
with open(os.environ["HOME"] + "/macos.json", "r", encoding="utf-8") as f:
    data = json.load(f)
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Here we use a <code class="system-font boxed">with</code> statement with the <code class="system-font boxed">open</code> function. This ensures better exception handling and doesn&#8217;t require the <code class="system-font boxed">close()</code> function to be called explicitly as the <code class="system-font boxed">with</code> statement handles the proper acquisition and release of resources.</p>
<p>The updated deserialized data. The output has been re-formatted for clarity:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data)
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: json; gutter: false;">
{
    'updated': '2020-07-09',
    'versions': [
        {
            'family': 'macOS',
            'version': '10.14',
            'codename': 'Mojave',
            'announced': '2018-06-04',
            'released': '2018-09-24',
            'requirements': [
                'iMac (Late 2012 or newer)',
                'iMac Pro (2017)',
                'Mac Mini (Late 2012 or newer)',
                'Mac Pro (Late 2013; Mid 2010 and '
                'Mid 2012 models with recommended '
                'Metal-capable graphics cards)',
                'MacBook (Early 2015 or newer)',
                'MacBook Air (Mid 2012 or newer)',
                'MacBook Pro (Mid 2012 or newer)',
                '2 GB of memory',
                '12.5 - 18.5 GB of available '
                'avaialable disk space',
                'OS X 10.8 or later'
            ],
            'releases': [
                {
                    'version': '10.14',
                    'build': '18A391',
                    'darwin': '18.0.0',
                    'released': '2018-09-24'
                },
                {
                    'version': '10.14.1',
                    'build': '18B75',
                    'darwin': '18.2.0',
                    'released': '2018-10-30'
                },
                {
                    'version': '10.14.2',
                    'build': '18C54',
                    'darwin': '18.2.0',
                    'released': '2018-12-05'
                },
                {
                    'version': '10.14.3',
                    'build': '18D42',
                    'darwin': '18.2.0',
                    'released': '2019-01-22'
                },
                {
                    'version': '10.14.4',
                    'build': '18E226',
                    'darwin': '18.5.0',
                    'released': '2019-03-25'
                },
                {
                    'version': '10.14.5',
                    'build': '18F132',
                    'darwin': '18.6.0',
                    'released': '2019-05-13'
                },
                {
                    'version': '10.14.6',
                    'build': '18G84',
                    'darwin': '18.7.0',
                    'released': '2019-07-22'
                }
            ]
        },
        {
            'family': 'macOS',
            'version': '10.15',
            'codename': 'Catalina',
            'announced': '2019-06-03',
            'released': '2019-10-07',
            'requirements': [
                'iMac (Late 2012 or newer)',
                'iMac Pro (2017)',
                'Mac Mini (Late 2012 or newer)',
                'Mac Pro (Late 2013)',
                'MacBook (Early 2015 or newer)',
                'MacBook Air (Mid 2012 or newer)',
                'MacBook Pro (Mid 2012 or newer)',
                '4 GB of memory',
                '12.5 GB of available avaialable '
                'disk space',
                'OS X 10.11.5 or later'
            ],
            'releases': [
                {
                    'version': '10.15',
                    'build': '19A583',
                    'darwin': '19.0.0',
                    'released': '2019-10-07'
                },
                {
                    'version': '10.15.1',
                    'build': '19B88',
                    'darwin': '19.0.0',
                    'released': '2019-10-29'
                },
                {
                    'version': '10.15.2',
                    'build': '19C57',
                    'darwin': '19.2.0',
                    'released': '2019-12-10'
                },
                {
                    'version': '10.15.3',
                    'build': '19D76',
                    'darwin': '19.3.0',
                    'released': '2020-01-28'
                },
                {
                    'version': '10.15.4',
                    'build': '19E266',
                    'darwin': '19.4.0',
                    'released': '2020-03-24'
                },
                {
                    'version': '10.15.5',
                    'build': '19F96',
                    'darwin': '19.5.0',
                    'released': '2020-05-26'
                }
            ]
        }
    ]
}
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<ul>
<li style="list-style-type: disc">Each dictionary in the <code class="system-font boxed">versions</code> list now contains two additional name/value pairs: <code class="system-font boxed">requirements</code> and <code class="system-font boxed">releases</code>.</li>
<li style="list-style-type: disc"><code class="system-font boxed">requirements</code> is a list whose values are all strings with each string representing a minimum system requirement to run that particular macOS version.</li>
<li style="list-style-type: disc"><code class="system-font boxed">releases</code> is also a list, but each of its values is a dictionary representing information on each release of a single macOS version provided by four name/value pairs: <code class="system-font boxed">version</code>, <code class="system-font boxed">build</code>, <code class="system-font boxed">darwin</code> and <code class="system-font boxed">released</code>.</li>
</ul>
<p>To get the first minimum system requirement to run macOS Mojave:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data["versions"][0]["requirements"][0])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
iMac (Late 2012 or newer)
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To get the first and second minimum system requirement to run macOS Catalina:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data["versions"][1]["requirements"][0]); \
print(data["versions"][1]["requirements"][1])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
iMac (Late 2012 or newer)
iMac Pro (2017)
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To get the build number of the first release of macOS Catalina:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data["versions"][1]["releases"][0]["build"])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
19A583
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To get the build number of the eighth release of macOS Mojave. Whoops! There have only been seven releases of macOS Mojave:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data["versions"][0]["releases"][7]["build"])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
IndexError: list index out of range
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To get the build number and Darwin version of the first release of macOS Catalina:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data["versions"][1]["releases"][0]["build"] +" "+ data["versions"][1]["releases"][0]["darwin"])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
19A583 19.0.0
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To get the version, build number and Darwin version of the first, second and third release of macOS Mojave:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data["versions"][0]["releases"][0]["version"] +" "+ data["versions"][0]["releases"][0]["build"] +" "+ data["versions"][0]["releases"][0]["darwin"]); \
print(data["versions"][0]["releases"][1]["version"] +" "+ data["versions"][0]["releases"][1]["build"] +" "+ data["versions"][0]["releases"][1]["darwin"]); \
print(data["versions"][0]["releases"][2]["version"] +" "+ data["versions"][0]["releases"][2]["build"] +" "+ data["versions"][0]["releases"][2]["darwin"])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
10.14 18A391 18.0.0
10.14.1 18B75 18.2.0
10.14.2 18C54 18.2.0
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<h4>Looping Through JSON-encoded Data</h4>
<p>As is evident from the examples above, accessing multiple values in lists is cumbersome and error prone. Each value – whether it be a string, a number, boolean, null or a dictionary – has to be explicitly targeted using its position or index in the list. Often, the total number of values in a list is unknown beforehand or the number of values in similarly named lists differ resulting in index out of range errors. For example, the <code class="system-font boxed">releases</code> list for macOS Mojave contains seven values (dictionaries), but for macOS Catalina contains only six.</p>
<p>To overcome this we can use a <code class="system-font boxed">for</code> statement to loop or iterate through every value in the list repeating the same steps during each loop or iteration.</p>
<p>For example, to get the codename of every macOS version without using a <code class="system-font boxed">for</code> loop:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data["versions"][0]["codename"]); \
print(data["versions"][1]["codename"])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
Mojave
Catalina
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Alternatively, to get the codename of every macOS version using a <code class="system-font boxed">for</code> loop:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
for _version in data["versions"]: 
    print(_version["codename"])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
Mojave
Catalina
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The loop repeats for every value (dictionary) in the <code class="system-font boxed">versions</code> list. On each loop, the current list value is written to the variable <code class="system-font boxed">_version</code>. Subsequently, we use <code class="system-font boxed">_version["codename"]</code> to get the codename of that macOS version.</p>
<p>To get the codename of every macOS version together with their minimum system requirements without using a <code class="system-font boxed">for</code> loop:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data["versions"][0]["codename"]); \
print("  " + data["versions"][0]["requirements"][0]); \
print("  " + data["versions"][0]["requirements"][1]); \
print("  " + data["versions"][0]["requirements"][2]); \
print("  " + data["versions"][0]["requirements"][3]); \
print("  " + data["versions"][0]["requirements"][4]); \
print("  " + data["versions"][0]["requirements"][5]); \
print("  " + data["versions"][0]["requirements"][6]); \
print("  " + data["versions"][0]["requirements"][7]); \
print("  " + data["versions"][0]["requirements"][8]); \
print("  " + data["versions"][0]["requirements"][9]); \
print(data["versions"][1]["codename"]); \
print("  " + data["versions"][1]["requirements"][0]); \
print("  " + data["versions"][1]["requirements"][1]); \
print("  " + data["versions"][1]["requirements"][2]); \
print("  " + data["versions"][1]["requirements"][3]); \
print("  " + data["versions"][1]["requirements"][4]); \
print("  " + data["versions"][1]["requirements"][5]); \
print("  " + data["versions"][1]["requirements"][6]); \
print("  " + data["versions"][1]["requirements"][7]); \
print("  " + data["versions"][1]["requirements"][8]); \
print("  " + data["versions"][1]["requirements"][9])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
Mojave
  iMac (Late 2012 or newer)
  iMac Pro (2017)
  Mac Mini (Late 2012 or newer)
  Mac Pro (Late 2013; Mid 2010 and Mid 2012 models with recommended Metal-capable graphics cards)
  MacBook (Early 2015 or newer)
  MacBook Air (Mid 2012 or newer)
  MacBook Pro (Mid 2012 or newer)
  2 GB of memory
  12.5 - 18.5 GB of available avaialable disk space
  OS X 10.8 or later
Catalina
  iMac (Late 2012 or newer)
  iMac Pro (2017)
  Mac Mini (Late 2012 or newer)
  Mac Pro (Late 2013)
  MacBook (Early 2015 or newer)
  MacBook Air (Mid 2012 or newer)
  MacBook Pro (Mid 2012 or newer)
  4 GB of memory
  12.5 GB of available avaialable disk space
  OS X 10.11.5 or later
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Alternatively, to get the same information using a <code class="system-font boxed">for</code> loop:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
for _version in data["versions"]: 
	print(_version["codename"])
	for _requirement in _version["requirements"]: 
		print("  " + _requirement)
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
Mojave
  iMac (Late 2012 or newer)
  iMac Pro (2017)
  Mac Mini (Late 2012 or newer)
  Mac Pro (Late 2013; Mid 2010 and Mid 2012 models with recommended Metal-capable graphics cards)
  MacBook (Early 2015 or newer)
  MacBook Air (Mid 2012 or newer)
  MacBook Pro (Mid 2012 or newer)
  2 GB of memory
  12.5 - 18.5 GB of available avaialable disk space
  OS X 10.8 or later
Catalina
  iMac (Late 2012 or newer)
  iMac Pro (2017)
  Mac Mini (Late 2012 or newer)
  Mac Pro (Late 2013)
  MacBook (Early 2015 or newer)
  MacBook Air (Mid 2012 or newer)
  MacBook Pro (Mid 2012 or newer)
  4 GB of memory
  12.5 GB of available avaialable disk space
  OS X 10.11.5 or later
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>In this instance the <code class="system-font boxed">for</code> loops are nested. The outer <code class="system-font boxed">for</code> loop is the same as in the previous example. The inner<br />
<code class="system-font boxed">for</code> loop repeats for every value (string) in the <code class="system-font boxed">requirements</code> list. On each loop, the current list value is written to the variable  <code class="system-font boxed">_requirement</code>. Subsequently, to get each requirement we simply use <code class="system-font boxed">_requirement</code>.</p>
<p>Because the <code class="system-font boxed">requirements</code> list is contained by the <code class="system-font boxed">versions</code> list we have to nest the <code class="system-font boxed">for</code> loops. Not doing so will give incomplete results where only the <code class="system-font boxed">requirements</code> list of the last value in the <code class="system-font boxed">versions</code> list is targeted:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
for _version in data["versions"]: 
	print(_version["codename"])
for _requirement in _version["requirements"]: 
	print("  " + _requirement)
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
Mojave
Catalina
  iMac (Late 2012 or newer)
  iMac Pro (2017)
  Mac Mini (Late 2012 or newer)
  Mac Pro (Late 2013)
  MacBook (Early 2015 or newer)
  MacBook Air (Mid 2012 or newer)
  MacBook Pro (Mid 2012 or newer)
  4 GB of memory
  12.5 GB of available avaialable disk space
  OS X 10.11.5 or later
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Finally, to additionally include the version of every macOS release without using a <code class="system-font boxed">for</code> loop:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
print(data["versions"][0]["codename"]); \
print("  " + data["versions"][0]["requirements"][0]); \
print("  " + data["versions"][0]["requirements"][1]); \
print("  " + data["versions"][0]["requirements"][2]); \
print("  " + data["versions"][0]["requirements"][3]); \
print("  " + data["versions"][0]["requirements"][4]); \
print("  " + data["versions"][0]["requirements"][5]); \
print("  " + data["versions"][0]["requirements"][6]); \
print("  " + data["versions"][0]["requirements"][7]); \
print("  " + data["versions"][0]["requirements"][8]); \
print("  " + data["versions"][0]["requirements"][9]); \
print("    " + data["versions"][0]["releases"][0]["version"]); \
print("    " + data["versions"][0]["releases"][1]["version"]); \
print("    " + data["versions"][0]["releases"][2]["version"]); \
print("    " + data["versions"][0]["releases"][3]["version"]); \
print("    " + data["versions"][0]["releases"][4]["version"]); \
print("    " + data["versions"][0]["releases"][5]["version"]); \
print("    " + data["versions"][0]["releases"][6]["version"]); \
print(data["versions"][1]["codename"]); \
print("  " + data["versions"][1]["requirements"][0]); \
print("  " + data["versions"][1]["requirements"][1]); \
print("  " + data["versions"][1]["requirements"][2]); \
print("  " + data["versions"][1]["requirements"][3]); \
print("  " + data["versions"][1]["requirements"][4]); \
print("  " + data["versions"][1]["requirements"][5]); \
print("  " + data["versions"][1]["requirements"][6]); \
print("  " + data["versions"][1]["requirements"][7]); \
print("  " + data["versions"][1]["requirements"][8]); \
print("  " + data["versions"][1]["requirements"][9]); \
print("    " + data["versions"][1]["releases"][0]["version"]); \
print("    " + data["versions"][1]["releases"][1]["version"]); \
print("    " + data["versions"][1]["releases"][2]["version"]); \
print("    " + data["versions"][1]["releases"][3]["version"]); \
print("    " + data["versions"][1]["releases"][4]["version"]); \
print("    " + data["versions"][1]["releases"][5]["version"])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
Mojave
  iMac (Late 2012 or newer)
  iMac Pro (2017)
  Mac Mini (Late 2012 or newer)
  Mac Pro (Late 2013; Mid 2010 and Mid 2012 models with recommended Metal-capable graphics cards)
  MacBook (Early 2015 or newer)
  MacBook Air (Mid 2012 or newer)
  MacBook Pro (Mid 2012 or newer)
  2 GB of memory
  12.5 - 18.5 GB of available avaialable disk space
  OS X 10.8 or later
    10.14
    10.14.1
    10.14.2
    10.14.3
    10.14.4
    10.14.5
    10.14.6
Catalina
  iMac (Late 2012 or newer)
  iMac Pro (2017)
  Mac Mini (Late 2012 or newer)
  Mac Pro (Late 2013)
  MacBook (Early 2015 or newer)
  MacBook Air (Mid 2012 or newer)
  MacBook Pro (Mid 2012 or newer)
  4 GB of memory
  12.5 GB of available avaialable disk space
  OS X 10.11.5 or later
    10.15
    10.15.1
    10.15.2
    10.15.3
    10.15.4
    10.15.5
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>Alternatively, using a <code class="system-font boxed">for</code> loop:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre class="brush: python; gutter: false;">
for _version in data["versions"]: 
	print(_version["codename"])
	for _requirement in _version["requirements"]: 
		print("  " + _requirement)
	for _release in _version["releases"]: 
		print("    " + _release["version"])
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: text; gutter: false;">
Mojave
  iMac (Late 2012 or newer)
  iMac Pro (2017)
  Mac Mini (Late 2012 or newer)
  Mac Pro (Late 2013; Mid 2010 and Mid 2012 models with recommended Metal-capable graphics cards)
  MacBook (Early 2015 or newer)
  MacBook Air (Mid 2012 or newer)
  MacBook Pro (Mid 2012 or newer)
  2 GB of memory
  12.5 - 18.5 GB of available avaialable disk space
  OS X 10.8 or later
    10.14
    10.14.1
    10.14.2
    10.14.3
    10.14.4
    10.14.5
    10.14.6
Catalina
  iMac (Late 2012 or newer)
  iMac Pro (2017)
  Mac Mini (Late 2012 or newer)
  Mac Pro (Late 2013)
  MacBook (Early 2015 or newer)
  MacBook Air (Mid 2012 or newer)
  MacBook Pro (Mid 2012 or newer)
  4 GB of memory
  12.5 GB of available avaialable disk space
  OS X 10.11.5 or later
    10.15
    10.15.1
    10.15.2
    10.15.3
    10.15.4
    10.15.5
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The last <code class="system-font boxed">for</code> loop repeats for every value (dictionary) in the <code class="system-font boxed">releases</code> list. On each loop, the current list value is written to the variable  <code class="system-font boxed">_release</code>. Subsequently, we use <code class="system-font boxed">_release["version"]</code> to get the version of each release.</p>
<p>Similar to the <code class="system-font boxed">requirements</code> list, the <code class="system-font boxed">releases</code> list is also contained within the <code class="system-font boxed">versions</code> list, so the <code class="system-font boxed">for</code> loop targeting the <code class="system-font boxed">releases</code> list is also nested within the <code class="system-font boxed">for</code> loop targeting the <code class="system-font boxed">versions</code> list.</p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<h5>Notes</h5>
<ul>
<li style="list-style-type: lower-roman">
<p>The information on macOS (Mac OS X) releases contained in the file <code class="system-font boxed">macos.json</code> is for demonstration purposes only. The version of the file used in this post is a subset of the data contained in the original. The latest, complete version can be found <a href="https://raw.githubusercontent.com/tech-otaku/macos-versions/master/json/macos.json" target="_blank" rel="noopener noreferrer">here</a>. While every attempt has been made to ensure this data is correct, its accuracy is not guaranteed.</p>
</li>
<li style="list-style-type: lower-roman">
<p><a href="https://raw.githubusercontent.com/tech-otaku/macos-versions/master/python/parse-json.py" target="_blank" rel="noopener noreferrer">parse-json.py</a> is a Python script used to parse the JSON-encoded data in the file <code class="system-font boxed">macos.json</code> and is based on the examples in this post. A Node.js application that runs this Python script and displays the results can be found at <a href="https://macos.tech-otaku.com" target="_blank" rel="noopener noreferrer">macos.tech-otaku.com</a></p>
</li>
<li style="list-style-type: lower-roman">
<p>The GitHub repository for the Node.js application can be found at <a href="https://github.com/tech-otaku/macos-versions" target="_blank" rel="noopener noreferrer">macos-versions</a>.</p>
</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-otaku.com/mac/using-python-to-loop-through-json-encoded-data/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7271</post-id>	</item>
		<item>
		<title>Using WP-CLI to Update WordPress Theme Options</title>
		<link>https://www.tech-otaku.com/web-development/using-wp-cli-to-update-wordpress-theme-options/</link>
		
		<dc:creator><![CDATA[Steve]]></dc:creator>
		<pubDate>Wed, 08 Apr 2020 14:14:57 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[macOS]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WP-CLI]]></category>
		<guid isPermaLink="false">https://www.tech-otaku.com/?p=6752</guid>

					<description><![CDATA[WordPress theme&#8217;s can have a multitude of options requiring manual configuration to tailor the theme to your liking. This post looks at using WP-CLI to configure theme options from the macOS command line. To demonstrate, I&#8217;ll use the option that controls the posts appearing in the slider at the top of this site’s home page. [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>WordPress theme&#8217;s can have a multitude of options requiring manual configuration to tailor the theme to your liking. This post looks at using <a href="https://wp-cli.org" target="_blank" rel="noopener noreferrer">WP-CLI</a> to configure theme options from the macOS command line. To demonstrate, I&#8217;ll use the option that controls the posts appearing in the slider at the top of this site’s home page.</p>
<p><span id="more-6752"></span></p>
<p>For information on installing WP-CLI, some basic configuration tips and examples of using aliases please refer to <a href="https://www.tech-otaku.com/mac/installing-configuring-wp-cli-macos" target="_blank" rel="noopener noreferrer">Installing and Configuring WP-CLI on macOS</a>.</p>
<p>This site uses the <a href="https://mekshq.com/theme/typology/" target="_blank" rel="noopener noreferrer">Typology</a> theme by Meks. The theme option that controls which posts appear in the slider is <code class="system-font boxed">front_page_cover_posts_manual</code> and requires a comma-separated string of post IDs.</p>
<p>I can use WP-CLI to get the current value of this option:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
wp @production option pluck typology_settings front_page_cover_posts_manual
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
1789,6090,1860,5524,1282
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The constituent parts of the command string are:</p>
<table style="width: 100%;margin-left: auto;margin-right: auto">
<col style="width: 15%">
<col style="width: 85%">
<tr>
<td><code class="system-font boxed small">wp</code></td>
<td>The WP-CLI binary. Usually located in <code class="system-font boxed small">/usr/local/bin</code>.</td>
</tr>
<tr>
<td><code class="system-font boxed small">@production</code></td>
<td>The alias for the WordPress installation being targeted. Aliases are configured in <code class="system-font boxed small">~/.wp-cli/config.yaml</code>.</td>
</tr>
<tr>
<td><code class="system-font boxed small">option pluck</code></td>
<td>The WP-CLI command to retrieve a nested option.</td>
</tr>
<tr>
<td><code class="system-font boxed small">typology_settings</code></td>
<td>The <code class="system-font boxed small">option_name</code> value in the <code class="system-font boxed small">wp_options</code> table. Contains all the theme options.</td>
</tr>
<tr>
<td><code class="system-font boxed small">front_page_cover_posts_manual</code></td>
<td>The nested option name within the <code class="system-font boxed small">typology_settings</code> option.</td>
</tr>
</table>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To update which posts appear in the slider I replace the WP-CLI command <code class="system-font boxed">option pluck</code> with <code class="system-font boxed">option patch update</code> and provide a new comma-separated list of post IDs:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
wp @production option patch update typology_settings front_page_cover_posts_manual '4825,5232,2163,6090,245'
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
Success: Updated 'typology_settings' option.
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Rather than manually creating a comma-separated list of post IDs, one can be automatically generated using <code class="system-font boxed">post list</code>:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
wp @production post list --posts_per_page=5 --post_status=publish --post_type=post --orderby=rand --format=ids
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
4737 940 6554 250 6473
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The <code class="system-font boxed">post list</code> command uses any argument supported by <a href="https://developer.wordpress.org/reference/classes/wp_query/" target="_blank" rel="noopener noreferrer">WP_Query</a> to return post data. Here I&#8217;m selecting <i>5 published posts</i> in <i>random</i> order. The <code class="system-font boxed">--format=ids</code> argument ensures that only the ID of each post is returned.</p>
<p>The output from this command isn&#8217;t in the correct format. The post IDs are separated by spaces not commas, but by piping the output of the command to <code class="system-font boxed">tr</code> the spaces can be changed to commas:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
wp @production post list --posts_per_page=5 --post_status=publish --post_type=post --orderby=rand --format=ids | tr ' ' ,
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
4737,940,6554,250,6473
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>By passing the command string that generates random post IDs as an argument to the command string that updates the theme option I can change what appears in the slider with a set of randomly selected posts:</p>
<p> <span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
wp @production option patch update typology_settings front_page_cover_posts_manual $(wp @production post list --posts_per_page=5 --post_status=publish --post_type=post --orderby=rand --format=ids | tr ' ' ,)
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
Success: Updated 'typology_settings' option.
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>For convenience the command can be placed in a script:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">slider-posts.sh</div>
<pre class="brush: bash;">
#!/bin/bash

# USAGE [/bin/bash] /path/to/slider-posts.sh &lt;number-of-posts&gt; &lt;alias&gt;
# $1 = Number of posts to include in the slider
# $2 = The alias to the WordPress installation

if [ $# -ne 2 ]; then
	printf "ERROR: 2 arguments are required: &lt;number-of-posts&gt; &lt;alias&gt;"
	exit 1
elif [[ ! $(/usr/local/bin/wp cli alias get @"${2}" 2&gt;/dev/null) ]]; then 
	printf "ERROR: The alias \"@${2}\" doesn't exist."
	exit 1
fi

/usr/local/bin/wp @"${2}" option patch update typology_settings front_page_cover_posts_manual $(/usr/local/bin/wp @"${2}" post list --posts_per_page="${1}" --post_status=publish --post_type=post --orderby=rand --format=ids | tr ' ' ,)
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p><u>NOTE</u>: The script explicitly uses the full path to the WP-CLI binary: <code class="system-font boxed">/usr/local/bin/wp</code>. This is to allow the script to be executed by <a href="https://www.launchd.info" target="_blank" rel="noopener noreferrer"><span style="font-family;'Source Code Pro'">launchd</span></a>. When the script is executed from the command-line, it searches the directories defined in the user&#8217;s <code class="system-font boxed">$PATH</code> environment variable for the WP-CLI binary. The <code class="system-font boxed">$PATH</code> environment variable will invariably contain the <code class="system-font boxed">/usr/local/bin</code> directory. However, <code class="system-font dark">launchd</code> has a default search path limited to <code class="system-font boxed">/usr/bin:/bin:/usr/sbin:/sbin</code>. Consequently, if <code class="system-font dark">launchd</code> attempted to run this script without the script using the full path to the WP-CLI binary it would fail.</p>
<p>The script requires two arguments: the number of posts to include in the slider and the alias to the WordPress install being targeted. In addition, the script uses WP-CLI to check the alias and exit with an error if the alias doesn&#8217;t exist.</p>
<p>Make the script executable:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
chmod +x /path/to/slider-posts.sh
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>Run the script passing the number of posts and alias as arguments:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
/path/to/slider-posts.sh 5 production
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
Updated 'typology_settings' option.
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Now I have a working script I can use <code class="system-font dark">launchd</code> to execute the script at a regular interval by first creating a job definition file. This file should have a <code class="system-font boxed">.plist</code> extension and be located in the <code class="system-font boxed">~/Library/LaunchAgents</code> directory:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">com.tech-otaku.slider.posts.plist</div>
<pre class="brush: xml;">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
    &lt;key&gt;Label&lt;/key&gt;
    &lt;string&gt;com.tech-otaku.slider.posts&lt;/string&gt;
    &lt;key&gt;ProgramArguments&lt;/key&gt;
    &lt;array&gt;
        &lt;string&gt;/path/to/slider-posts.sh&lt;/string&gt;
        &lt;string&gt;5&lt;/string&gt;
        &lt;string&gt;production&lt;/string&gt;
    &lt;/array&gt;
    &lt;key&gt;StandardErrorPath&lt;/key&gt;
    &lt;string&gt;/tmp/com.tech-otaku.slider.posts.stderr&lt;/string&gt;
    &lt;key&gt;StandardOutPath&lt;/key&gt;
    &lt;string&gt;/tmp/com.tech-otaku.slider.posts.stdout&lt;/string&gt;
    &lt;key&gt;StartCalendarInterval&lt;/key&gt;
    &lt;array&gt;
        &lt;dict&gt;
            &lt;key&gt;Hour&lt;/key&gt;
            &lt;integer&gt;23&lt;/integer&gt;
            &lt;key&gt;Minute&lt;/key&gt;
            &lt;integer&gt;0&lt;/integer&gt;
        &lt;/dict&gt;
    &lt;/array&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>When active, this job definition will execute <code class="system-font boxed">/path/to/slider-posts.sh 5 production</code> at <code class="system-font boxed">23:00</code> everyday.</p>
<p>To activate a job definition, it needs to be loaded. All enabled job definitions are loaded automatically when your Mac powers-on or you login, but to load it explicitly:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
launchctl load "${HOME}/Library/LaunchAgents/com.tech-otaku.slider.posts"
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6752</post-id>	</item>
		<item>
		<title>Manually Granting Applications Full Disk Access in macOS Catalina</title>
		<link>https://www.tech-otaku.com/mac/manually-granting-applications-full-disk-access-macos-catalina/</link>
					<comments>https://www.tech-otaku.com/mac/manually-granting-applications-full-disk-access-macos-catalina/#comments</comments>
		
		<dc:creator><![CDATA[Steve]]></dc:creator>
		<pubDate>Thu, 12 Mar 2020 16:26:13 +0000</pubDate>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[Full Disk Access]]></category>
		<category><![CDATA[macOS]]></category>
		<category><![CDATA[System Preferences]]></category>
		<guid isPermaLink="false">https://www.tech-otaku.com/?p=6554</guid>

					<description><![CDATA[Since the release of macOS Mojave, applications have required authorisation to access your personal data and locations including the ~/Documents and ~/Downloads directories. Authorisation requests are routinely handled by macOS when an application requiring access is first launched. Occasionally, an application may need to be authorised by manually granting it access. Before looking at how [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Since the release of macOS Mojave, applications have required authorisation to access your personal data and locations including the <code class="system-font boxed">~/Documents</code> and <code class="system-font boxed">~/Downloads</code> directories.</p>
<p>Authorisation requests are routinely handled by macOS when an application requiring access is first launched. Occasionally, an application may need to be authorised by manually granting it access.</p>
<p><span id="more-6554"></span></p>
<p>Before looking at how an application can be manually authorised, we need to configure <code class="system-font dark">Finder</code> windows to display hard disks in the sidebar. Select <code class="system-font dark">Finder</code> &gt; <code class="system-font dark">Preferences</code> &gt; <code class="system-font dark">Sidebar</code> and ensure that under <code class="system-font dark">Locations</code> the <code class="system-font dark">Hard disk</code> option is checked:</p>
<p><!-- START: Markup generated by http://html.patchpeters.com/index.php on Thursday, March 12th 2020 08:58:46 +0000
     Source: /home/radon/www/html.patchpeters.com/public_html/index.php
     Image: https://www.tech-otaku.com/wp-content/uploads/6554-01-sidebar-preferences-for-finder-windows.png
     Original image dimensions are w742 x h1282. Reduced to 35% (w259 x h448) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
        <a href="https://www.tech-otaku.com/wp-content/uploads/6554-01-sidebar-preferences-for-finder-windows.png" title="'Sidebar preferences for Finder windows' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-0" data-rl_title="" data-rl_caption=""><img fetchpriority="high" decoding="async" src="/wp-content/uploads/6554-01-sidebar-preferences-for-finder-windows.png" alt="Sidebar preferences for Finder windows" width="259" height="448" /></a>
    </div><figcaption class="post-image-caption">Sidebar preferences for Finder windows</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<p>To manually authorise an application it needs to be given full disk access. Select <code class="system-font dark">System Preferences</code> &gt; <code class="system-font dark">Security &amp; Privacy</code> &gt; <code class="system-font dark">Privacy</code> &gt; <code class="system-font dark">Full Disk Access</code> and click the <code class="system-font dark">+</code> button:</p>
<p><!-- START: Markup generated by http://html.patchpeters.com/index.php on Thursday, March 12th 2020 09:00:46 +0000
     Source: /home/radon/www/html.patchpeters.com/public_html/index.php
     Image: https://www.tech-otaku.com/wp-content/uploads/6554-02-full-disk-access-pane-of-the-privacy-tab.png
     Original image dimensions are w1336 x h1146. Reduced to 35% (w467 x h401) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
        <a href="https://www.tech-otaku.com/wp-content/uploads/6554-02-full-disk-access-pane-of-the-privacy-tab.png" title="'Full Disk Access pane of the Privacy tab' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-1" data-rl_title="" data-rl_caption=""><img decoding="async" src="/wp-content/uploads/6554-02-full-disk-access-pane-of-the-privacy-tab.png" alt="Full Disk Access pane of the Privacy tab" width="467" height="401" /></a>
    </div><figcaption class="post-image-caption">Full Disk Access pane of the Privacy tab</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<p>To give, say, the <code class="system-font dark">GitHub Desktop</code> application full disk access, navigate to the <code class="system-font boxed">/Applications</code> directory, select <code class="system-font boxed">GitHub Desktop.app</code> and click <code class="system-font dark">Open</code>:</p>
<p><!-- START: Markup generated by http://html.patchpeters.com/index.php on Thursday, March 12th 2020 10:20:47 +0000
     Source: /home/radon/www/html.patchpeters.com/public_html/index.php
     Image: https://www.tech-otaku.com/wp-content/uploads/6554-03-manually-granting-full-disk-access-to-the-github-desktop-application.png
     Original image dimensions are w1598 x h1146. Reduced to 35% (w559 x h401) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
        <a href="https://www.tech-otaku.com/wp-content/uploads/6554-03-manually-granting-full-disk-access-to-the-github-desktop-application.png" title="'Manually granting Full Disk Access to the GitHub Desktop application' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-2" data-rl_title="" data-rl_caption=""><img decoding="async" src="/wp-content/uploads/6554-03-manually-granting-full-disk-access-to-the-github-desktop-application.png" alt="Manually granting Full Disk Access to the GitHub Desktop application" width="559" height="401" /></a>
    </div><figcaption class="post-image-caption">Manually granting Full Disk Access to the GitHub Desktop application</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<p>With macOS Catalina, full disk access may need to be given to a program not located in the <code class="system-font boxed">/Applications</code> directory. An example is the <code class="system-font dark">bash</code> interpreter that currently ships with macOS and whose binary is in the <code class="system-font boxed">/bin</code> directory.</p>
<p>To grant <code class="system-font dark">/bin/bash</code> full disk access, first click <code class="system-font dark">Macintosh HD</code> in the sidebar of the <code class="system-font dark">Open</code> dialog:</p>
<p><!-- START: Markup generated by http://html.patchpeters.com/index.php on Wednesday, March 11th 2020 10:26:43 +0000
     Source: /home/radon/www/html.patchpeters.com/public_html/index.php
     Image: https://www.tech-otaku.com/wp-content/uploads/6554-04-open-dialog-showing-the-macintosh-hd-volume.png
     Original image dimensions are w1598 x h1146. Reduced to 35% (w559 x h401) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
        <a href="https://www.tech-otaku.com/wp-content/uploads/6554-04-open-dialog-showing-the-macintosh-hd-volume.png" title="'Open dialog showing the MacIntosh HD volume' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-3" data-rl_title="" data-rl_caption=""><img loading="lazy" decoding="async" src="/wp-content/uploads/6554-04-open-dialog-showing-the-macintosh-hd-volume.png" alt="Open dialog showing the MacIntosh HD volume" width="559" height="401" /></a>
    </div><figcaption class="post-image-caption">Open dialog showing the MacIntosh HD volume</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<p>The <code class="system-font boxed">/bin</code> directory – amongst others – isn&#8217;t shown until the <kbd class="apple-key">⇧</kbd>+<kbd class="apple-key">⌘</kbd>+<kbd class="period-key">.</kbd> keys are pressed simultaneously:</p>
<p><!-- START: Markup generated by http://html.patchpeters.com/index.php on Wednesday, March 11th 2020 10:27:37 +0000
     Source: /home/radon/www/html.patchpeters.com/public_html/index.php
     Image: https://www.tech-otaku.com/wp-content/uploads/6554-05-open-dialog-showing-the-macintosh-hd-volume-including-hidden-items.png
     Original image dimensions are w1598 x h1146. Reduced to 35% (w559 x h401) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
        <a href="https://www.tech-otaku.com/wp-content/uploads/6554-05-open-dialog-showing-the-macintosh-hd-volume-including-hidden-items.png" title="'Open dialog showing the MacIntosh HD volume including hidden items' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-4" data-rl_title="" data-rl_caption=""><img loading="lazy" decoding="async" src="/wp-content/uploads/6554-05-open-dialog-showing-the-macintosh-hd-volume-including-hidden-items.png" alt="Open dialog showing the MacIntosh HD volume including hidden items" width="559" height="401" /></a>
    </div><figcaption class="post-image-caption">Open dialog showing the MacIntosh HD volume including hidden items</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<p>Navigate to the <code class="system-font boxed">/bin</code> directory, select <code class="system-font boxed">bash</code> then click <code class="system-font dark">Open</code> to grant the <code class="system-font dark">bash</code> binary full disk access:</p>
<p><!-- START: Markup generated by http://html.patchpeters.com/index.php on Wednesday, March 11th 2020 10:28:56 +0000
     Source: /home/radon/www/html.patchpeters.com/public_html/index.php
     Image: https://www.tech-otaku.com/wp-content/uploads/6554-06-using-the-open-dialog-to-add-the-bin-bash-binary.png
     Original image dimensions are w1598 x h1146. Reduced to 35% (w559 x h401) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
        <a href="https://www.tech-otaku.com/wp-content/uploads/6554-06-using-the-open-dialog-to-add-the-bin-bash-binary.png" title="'Using the open dialog to add the /bin/bash binary' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-5" data-rl_title="" data-rl_caption=""><img loading="lazy" decoding="async" src="/wp-content/uploads/6554-06-using-the-open-dialog-to-add-the-bin-bash-binary.png" alt="Using the open dialog to add the /bin/bash binary" width="559" height="401" /></a>
    </div><figcaption class="post-image-caption">Using the open dialog to add the /bin/bash binary</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<p>This <i>Open dialog</i> method can also be used to grant full disk access to an application by selecting a symbolic link that points to that application. An example is <code class="system-font boxed">/usr/local/bin/bash</code> which is a symbolic link to the <code class="system-font dark">bash</code> binary <code class="system-font boxed">/usr/local/Cellar/bash/5.0.16/bin/bash</code> installed through Homebrew:</p>
<p><!-- START: Markup generated by http://html.patchpeters.com/index.php on Thursday, March 12th 2020 03:16:12 +0000
     Source: /home/radon/www/html.patchpeters.com/public_html/index.php
     Image: https://www.tech-otaku.com/wp-content/uploads/6554-09-using-the-open-dialog-to-select-the-usr-local-bin-bash-binary-symbolic-link.png
     Original image dimensions are w1598 x h1146. Reduced to 35% (w559 x h401) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
        <a href="https://www.tech-otaku.com/wp-content/uploads/6554-09-using-the-open-dialog-to-select-the-usr-local-bin-bash-binary-symbolic-link.png" title="'Using the open dialog to select the /usr/local/bin/bash symlink' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-6" data-rl_title="" data-rl_caption=""><img loading="lazy" decoding="async" src="/wp-content/uploads/6554-09-using-the-open-dialog-to-select-the-usr-local-bin-bash-binary-symbolic-link.png" alt="Using the open dialog to select the /usr/local/bin/bash symlink" width="559" height="401" /></a>
    </div><figcaption class="post-image-caption">Using the open dialog to select the /usr/local/bin/bash symlink</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<p>An alternative to the <i>Open dialog</i> method is to first navigate to the application in the <code class="system-font dark">Finder</code>, then drag and drop the application icon onto the <code class="system-font dark">Full Disk Access</code> pane of <code class="system-font dark">System Preferences</code>:</p>
<p><!-- START: Markup generated by http://html.patchpeters.com/index.php on Wednesday, March 11th 2020 10:30:01 +0000
     Source: /home/radon/www/html.patchpeters.com/public_html/index.php
     Image: https://www.tech-otaku.com/wp-content/uploads/6554-07-adding-the-bin-bash-binary-using-the-finder.png
     Original image dimensions are w1766 x h1320. Reduced to 35% (w618 x h462) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
        <a href="https://www.tech-otaku.com/wp-content/uploads/6554-07-adding-the-bin-bash-binary-using-the-finder.png" title="'Adding the /bin/bash binary using the Finder' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-7" data-rl_title="" data-rl_caption=""><img loading="lazy" decoding="async" src="/wp-content/uploads/6554-07-adding-the-bin-bash-binary-using-the-finder.png" alt="Adding the /bin/bash binary using the Finder" width="618" height="462" /></a>
    </div><figcaption class="post-image-caption">Adding the /bin/bash binary using the Finder</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<p>This <i>drag and drop</i> method doesn&#8217;t work with symbolic links in macOS Catalina. While it is possible to drag and drop the symbolic link icon onto the <code class="system-font dark">Full Disk Access</code> pane of <code class="system-font dark">System Preferences</code>, the application the symbolic link points to doesn&#8217;t appear to be granted full disk access. Consequently, only the <i>Open dialog</i> method described above should be used with symbolic links.</p>
<p><!-- START: Markup generated by http://html.patchpeters.com/index.php on Thursday, March 12th 2020 04:21:19 +0000
     Source: /home/radon/www/html.patchpeters.com/public_html/index.php
     Image: https://www.tech-otaku.com/wp-content/uploads/6554-08-adding-the-usr-local-bin-bash-binary-using-the-finder.png
     Original image dimensions are w1766 x h1320. Reduced to 35% (w618 x h462) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
        <a href="https://www.tech-otaku.com/wp-content/uploads/6554-08-adding-the-usr-local-bin-bash-binary-using-the-finder.png" title="'Avoid adding the /usr/local/bin/bash symbolic link using the Finder' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-8" data-rl_title="" data-rl_caption=""><img loading="lazy" decoding="async" src="/wp-content/uploads/6554-08-adding-the-usr-local-bin-bash-binary-using-the-finder.png" alt="Avoid adding the /usr/local/bin/bash symbolic link using the Finder" width="618" height="462" /></a>
    </div><figcaption class="post-image-caption">Avoid adding the /usr/local/bin/bash symbolic link using the Finder</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-otaku.com/mac/manually-granting-applications-full-disk-access-macos-catalina/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6554</post-id>	</item>
		<item>
		<title>Temporarily Disabling the WordPress Google Authenticator Plugin from the Command Line</title>
		<link>https://www.tech-otaku.com/web-development/temporarily-disabling-the-wordpress-google-authenticator-plugin-from-the-command-line/</link>
		
		<dc:creator><![CDATA[Steve]]></dc:creator>
		<pubDate>Thu, 20 Feb 2020 16:03:46 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[2FA]]></category>
		<category><![CDATA[Shell]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WP-CLI]]></category>
		<guid isPermaLink="false">https://www.tech-otaku.com/?p=6473</guid>

					<description><![CDATA[This WordPress site uses the Google Authenticator plugin to provide two-factor authentication (2FA) when logging-in to the administration area. Occasionally I need to temporarily disable 2FA in order to publish posts from the blogging software I use. Traditionally toggling 2FA is achieved from the WordPress backend. This post looks at two alternative methods of doing [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>This WordPress site uses the <a href="https://en-gb.wordpress.org/plugins/google-authenticator/" target="_blank" rel="noopener noreferrer">Google Authenticator</a> plugin to provide two-factor authentication (2FA) when logging-in to the administration area. Occasionally I need to temporarily disable 2FA in order to publish posts from the blogging software I use. Traditionally toggling 2FA is achieved from the WordPress backend. This post looks at two alternative methods of doing this locally from the command line.</p>
<p><span id="more-6473"></span></p>
<h3 id="method-1">Method 1 &#8211; Using the MySQL Command Line Client</h3>
<p>The Google Authenticator plugin settings are stored on a per-user basis in the <code class="system-font boxed">*_usermeta</code> table. Before taking a look at these settings from the command prompt of your server&#8217;s remote shell you&#8217;ll need the following information from your site&#8217;s <code class="system-font boxed">wp-config.php</code> file:</p>
<p><code class="system-font dark"><span class="text-red"><b>mysql-user-name</b></span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="system-font boxed">DB_USER</code><br />
<code class="system-font dark"><span class="text-red"><b>mysql-user-password</b></span>:&nbsp;</code><code class="system-font boxed">DB_PASSWORD</code><br />
<code class="system-font dark "><span class="text-red"><b>database-name</b></span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="system-font boxed">DB_NAME</code><br />
<code class="system-font dark"><span class="text-red"><b>table-prefix_</b></span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="system-font boxed">$table_prefix</code></p>
<p>To get the appropriate <code class="system-font dark"><span class="text-red"><b>wp-user-id</b></span></code> take a look at <a href="https://wpsmackdown.com/find-wordpress-user-id/#one-time" target="_blank" rel="noopener noreferrer">How to Find a WordPress User ID</a> but instead of <i>username</i>, hover over the <i>number of posts</i> and look for <code class="system-font boxed">author=</code></p>
<p>Armed with this information, use the following command to interrogate the database (you&#8217;ll be prompted for the <code class="system-font dark"><span class="text-red"><b>mysql-user-name</b></span></code> password):</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
mysql -u <span class="text-red"><b>mysql-user-name</b></span> -p -e "USE <span class="text-red"><b>database-name</b></span>; SELECT user_id, meta_key, meta_value FROM <span class="text-red"><b>table-prefix_</b></span>usermeta WHERE user_id=<span class="text-red"><b>wp-user-id</b></span> AND meta_key LIKE 'googleauthenticator_%';"
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: plain; gutter: false; highlight: 5;">
+---------+----------------------------------+-----------------------------------------------------------------------+
| user_id | meta_key                         | meta_value                                                            |
+---------+----------------------------------+-----------------------------------------------------------------------+
|       2 | googleauthenticator_description  | My Site                                                               |
|       2 | googleauthenticator_enabled      | enabled                                                               |
|       2 | googleauthenticator_lasttimeslot | 52734943                                                              |
|       2 | googleauthenticator_passwords    | {"appname":"Default","password":"HCACyh@eH-XnL*ALCJJ3-yrKVBVw2m62jm"} |
|       2 | googleauthenticator_pwdenabled   | disabled                                                              |
|       2 | googleauthenticator_relaxedmode  | disabled                                                              |
|       2 | googleauthenticator_secret       | 2TXZUABQROZJAH2E                                                      |
+---------+----------------------------------+-----------------------------------------------------------------------+
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The option we&#8217;re interested in is <code class="system-font boxed">googleauthenticator_enabled</code> which can either have a value of <code class="system-font boxed">enabled</code> (active) or <code class="system-font boxed">disabled</code> (inactive). To change the value to <code class="system-font boxed">disabled</code> use the following command:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
mysql -u <span class="text-red"><b>mysql-user-name</b></span> -p -e "USE <span class="text-red"><b>database-name</b></span>; UPDATE <span class="text-red"><b>table-prefix_</b></span>usermeta SET meta_value='disabled' WHERE user_id=<span class="text-red"><b>wp-user-id</b></span> AND meta_key='googleauthenticator_enabled';"
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To confirm the change is successful and the value is now <code class="system-font boxed">disabled</code>:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
mysql -u <span class="text-red"><b>mysql-user-name</b></span> -p -e "USE <span class="text-red"><b>database-name</b></span>; SELECT user_id, meta_key, meta_value FROM <span class="text-red"><b>table-prefix_</b></span>usermeta WHERE user_id=<span class="text-red"><b>wp-user-id</b></span> AND meta_key='googleauthenticator_enabled';"
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: plain; gutter: false;">
+---------+----------------------------------+-----------------------------------------------------------------------+
| user_id | meta_key                         | meta_value                                                            |
+---------+----------------------------------+-----------------------------------------------------------------------+
|       2 | googleauthenticator_enabled      | disabled                                                              |
+---------+----------------------------------+-----------------------------------------------------------------------+
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>We could combine the command to update the option with the command to confirm the update was successful, but the resulting command is a little lengthy so we could place the necessary <abbr title="Structured Query Language">SQL</abbr> statements into a file named say <code class="system-font boxed">disable-ga.sql</code>:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">disable-ga.sql</div>
<pre>
USE <span class="text-red"><b>database-name</b></span>;
UPDATE <span class="text-red"><b>table-prefix_</b></span>usermeta SET meta_value='disabled' WHERE user_id=<span class="text-red"><b>wp-user-id</b></span> AND meta_key='googleauthenticator_enabled';
SELECT user_id, meta_key, meta_value FROM <span class="text-red"><b>table-prefix_</b></span>usermeta WHERE user_id=<span class="text-red"><b>wp-user-id</b></span> AND meta_key='googleauthenticator_enabled';
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The command to disable 2FA and confirm the change is now:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
mysql <span class="text-blue">--table</span> -u <span class="text-red"><b>mysql-user-name</b></span> -p &lt; /path/to/disable-ga.sql
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: plain; gutter: false;">
+---------+----------------------------------+-----------------------------------------------------------------------+
| user_id | meta_key                         | meta_value                                                            |
+---------+----------------------------------+-----------------------------------------------------------------------+
|       2 | googleauthenticator_enabled      | disabled                                                              |
+---------+----------------------------------+-----------------------------------------------------------------------+
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Note the addition of the <code class="system-font boxed">mysql</code> command line option <code class="system-font boxed">--table</code> which is necessary when running <code class="system-font boxed">mysql</code> in batch mode to ensure results are displayed in a tabular format.</p>
<p>Similarly, we could create another file named say <code class="system-font boxed">enable-ga.sql</code> in order to enable 2FA:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">enable-ga.sql</div>
<pre>
USE <span class="text-red"><b>database-name</b></span>;
UPDATE <span class="text-red"><b>table-prefix_</b></span>usermeta SET meta_value='enabled' WHERE user_id=<span class="text-red"><b>wp-user-id</b></span> AND meta_key='googleauthenticator_enabled';
SELECT user_id, meta_key, meta_value FROM <span class="text-red"><b>table-prefix_</b></span>usermeta WHERE user_id=<span class="text-red"><b>wp-user-id</b></span> AND meta_key='googleauthenticator_enabled';
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Now, to enable 2FA:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
mysql --table -u <span class="text-red"><b>mysql-user-name</b></span> -p &lt; /path/to/enable-ga.sql
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
+---------+----------------------------------+-----------------------------------------------------------------------+
| user_id | meta_key                         | meta_value                                                            |
+---------+----------------------------------+-----------------------------------------------------------------------+
|       2 | googleauthenticator_enabled      | enabled                                                               |
+---------+----------------------------------+-----------------------------------------------------------------------+
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>We now have a way of disabling/enabling 2FA from the command line, but this is being actioned server-side remotely. On a Unix-like <abbr title="Operating System">OS</abbr> such as Linux or macOS the same can be achieved from a local shell:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
<span class="text-blue">ssh -p 22 user@12.34.56.789 "</span>mysql --table -u <span class="text-red"><b>mysql-user-name</b></span> -p &lt; /path/to/disable-ga.sql<span class="text-blue">"</span>
</div>
<div class="mks_tab_item"><div class="nav">Error</div>
<pre>
Enter password: ERROR 1045 (28000): Access denied for user '<span class="text-red"><b>mysql-user-name</b></span>'@'localhost' (using password: YES)
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>We're simply placing our command in double-quotes and prefixing it with the <abbr title="Secure Shell">SSH</abbr> credentials required to login to the server. However, this will cause an error as we're unable to enter the password for <code class="system-font dark"><span class="text-red"><b>mysql-user-name</b></span></code>. To avoid this error amend or create the file <code class="system-font boxed">.my.cnf</code> in your home directory on the server:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">.my.cnf</div>
<pre>
[client<b>-database-name</b>]
user=<span class="text-red"><b>mysql-user-name</b></span>
password='<span class="text-red"><b>mysql-user-password</b></span>'
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>This provides <code class="system-font boxed">mysql</code> with the password for the MySQL user <code class="system-font dark"><span class="text-red"><b>mysql-user-name</b></span></code>. Note the group name in square brackets: <code class="system-font boxed">client<b>-database-name</b></code>. It must begin with the word <code class="system-font boxed">client</code>, but can be followed with any string. I chose <code class="system-font dark"></b>-</b></code> followed by the <code class="system-font dark"><span class="text-red"><b>database-name</b></span></code>.</p>
<p><p>Now, to disable 2FA from a local shell:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
ssh -p 22 user@12.34.56.789 "mysql <span class="text-blue">--defaults-group-suffix=<b>-database-name</b></span> --table -u <span class="text-red"><b>mysql-user-name</b></span> &lt; /path/to/disable-ga.sql&quot;
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
+---------+----------------------------------+-----------------------------------------------------------------------+
| user_id | meta_key                         | meta_value                                                            |
+---------+----------------------------------+-----------------------------------------------------------------------+
|       2 | googleauthenticator_enabled      | disabled                                                              |
+---------+----------------------------------+-----------------------------------------------------------------------+
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Note the addition of the <code class="system-font boxed">mysql</code> command line option <code class="system-font boxed">--defaults-group-suffix=</code> and its value <code class="system-font boxed">-database-name</code> which instructs <code class="system-font boxed">mysql</code> to use the settings associated with the group named <code class="system-font boxed">client-database-name</code> in the <code class="system-font boxed">~/.my.cnf</code> file.</p>
<p>Optionally, create shell aliases to each of these commands by adding the following code to your user profile. For <code class="system-font dark">bash</code>, this file is either <code class="system-font boxed">~/.bashrc</code> or <code class="system-font boxed">~/.bash_profile</code>. For <code class="system-font dark">zsh</code> this is <code class="system-font boxed">~/.zshrc</code>.</p>
<p>To create an alias named <code class="system-font boxed">disga</code>:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
alias disga='ssh -p 22 user@12.34.56.789 "mysql --defaults-group-suffix=-<span class="text-red"><b>database-name</b></span> --table -u <span class="text-red"><b>mysql-user-name</b></span> &lt; /path/to/disable-ga.sql&quot;&#039;
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>To create an alias named <code class="system-font boxed">enga</code>:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
alias enga='ssh -p 22 user@12.34.56.789 "mysql --defaults-group-suffix=-<span class="text-red"><b>database-name</b></span> --table -u <span class="text-red"><b>mysql-user-name</b></span> &lt; /path/to/enable-ga.sql&quot;&#039;
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Now, to disable or enable 2FA simply type <code class="system-font boxed">disga</code> or <code class="system-font boxed">enga</code> respectively at the local command prompt:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
enga
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
+---------+----------------------------------+-----------------------------------------------------------------------+
| user_id | meta_key                         | meta_value                                                            |
+---------+----------------------------------+-----------------------------------------------------------------------+
|       2 | googleauthenticator_enabled      | enabled                                                               |
+---------+----------------------------------+-----------------------------------------------------------------------+
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. -->   </p>
<h3 id="method-2">Method 2 - Using WP-CLI</h3>
<p>The second method uses WP-CLI, the command line interface for WordPress and requires WP-CLI to be installed both locally and remotely with some configuration required for the local install. However, once installed it can be used for not only toggling 2FA. See <a href="https://www.tech-otaku.com/mac/installing-configuring-wp-cli-macos/" target="_blank" rel="noopener noreferrer">Installing and Configuring WP-CLI on macOS</a> for details.</p>
<p>The following commands use the WP-CLI <a href="https://developer.wordpress.org/cli/commands/user/meta/get/" target="_blank" rel="noopener noreferrer">user meta get</a> and <a href="https://developer.wordpress.org/cli/commands/user/meta/update/" target="_blank" rel="noopener noreferrer">user meta update</a> commands.</p>
<p>To check the status of 2FA provided by the Google Authenticator plugin using WP-CLI locally:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
wp @production user meta get "<span class="text-red"><b>wp-user-id</b></span>" googleauthenticator_enabled
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
enabled
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To disable 2FA using WP-CLI locally:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
wp @production user meta update "<span class="text-red"><b>wp-user-id</b></span>" googleauthenticator_enabled "disabled"
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
Success: Updated custom field 'googleauthenticator_enabled'.
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To enable 2FA using WP-CLI locally:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
wp @production user meta update "<span class="text-red"><b>wp-user-id</b></span>" googleauthenticator_enabled "enabled"
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
Success: Updated custom field 'googleauthenticator_enabled'.
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>These commands can also be aliased. To create an alias named <code class="system-font boxed">disgawp</code>:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
alias disgawp='wp @production user meta update "<span class="text-red"><b>wp-user-id</b></span>" googleauthenticator_enabled "disabled"'
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>To create an alias named <code class="system-font boxed">engawp</code>:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
alias engawp='wp @production user meta update "<span class="text-red"><b>wp-user-id</b></span>" googleauthenticator_enabled "enabled"'
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6473</post-id>	</item>
		<item>
		<title>Determining which Interpreter Parses a Shell Script in macOS</title>
		<link>https://www.tech-otaku.com/mac/determining-which-interpreter-parses-a-shell-script-in-macos/</link>
		
		<dc:creator><![CDATA[Steve]]></dc:creator>
		<pubDate>Sun, 16 Feb 2020 07:18:23 +0000</pubDate>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[launchd]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Shell]]></category>
		<category><![CDATA[zsh]]></category>
		<guid isPermaLink="false">https://www.tech-otaku.com/?p=6451</guid>

					<description><![CDATA[The first line of a shell script – beginning #! – is called a shebang and typically determines which interpreter parses the script&#8217;s contents. This is not always the case and on occasion it may be helpful to know which interpreter is being used. Paste the following at a command prompt to create a script [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The first line of a shell script – beginning <code class="system-font boxed">#!</code> – is called a shebang and typically determines which interpreter parses the script&#8217;s contents. This is not always the case and on occasion it may be helpful to know which interpreter is being used.</p>
<p><span id="more-6451"></span></p>
<p>Paste the following at a command prompt to create a script that demonstrates this:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
cat &lt;&lt; 'EOF' &gt; "${HOME}/which-interpreter.sh"
<span class="text-blue"><b>#!/bin/bash</b></span>
ps -p "$$" | tail -1 | awk '{print $4}'
EOF
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>This script simply displays the interpreter that parses it, but before running the script let&#8217;s look at what the line <code class="system-font boxed">ps -p "$$" | tail -1 | awk '{print $4}'</code> does.</p>
<p>The <code class="system-font boxed">ps</code> command with the <code class="system-font boxed">-p</code> flag outputs information about the process matching the process ID (PID). The <code class="system-font boxed">$$</code> represents the PID of the script. The output of <code class="system-font boxed">ps -p "$$"</code> is:</p>
<pre>
 PID TTY           TIME CMD
3740 ttys000    0:00.01 /bin/bash /Users/steve/which-interpreter.sh
</pre>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>This output is piped to <code class="system-font boxed">tail</code> to remove the header:</p>
<pre>
3740 ttys000    0:00.01 /bin/bash /Users/steve/which-interpreter.sh
</pre>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>The CMD portion of the output shows the command that launched the script: <code class="system-font boxed">/bin/bash</code> and the parameter passed to it <code class="system-font boxed">/Users/steve/which-interpreter.sh</code>. Only the command is of interest so the output is piped to <code class="system-font boxed">awk</code> to print the fourth field:</p>
<pre>
/bin/bash
</pre>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>Make the script executable:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
chmod +x "${HOME}/which-interpreter.sh"
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Now let&#8217;s run the script:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
"${HOME}/which-interpreter.sh"
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
/bin/bash
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>It doesn&#8217;t matter if the shell being used to run the script is a different version of <code class="system-font dark">bash</code> or even another shell like <code class="system-font dark">zsh</code>. The shebang will still be honoured and the script parsed by the <code class="system-font boxed">/bin/bash</code> interpreter unless another interpreter is explicitly used to execute the script at the command prompt.</p>
<p>Here are some examples:</p>
<p>NOTE: I have two <code class="system-font dark">bash</code> interpeters on my system. The one shipped with macOS: <code class="system-font boxed">/bin/bash</code> and the one installed via Homebrew: <code class="system-font boxed">/usr/local/bin/bash</code>. The latter is a symbolic link to <code class="system-font boxed">/usr/local/Cellar/bash/5.0.16/bin/bash</code>.</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
/usr/local/bin/bash "${HOME}/which-interpreter.sh"
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
/usr/local/bin/bash
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
/bin/zsh "${HOME}/which-interpreter.sh"
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
/bin/zsh
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
/usr/bin/env bash "${HOME}/which-interpreter.sh"
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
bash
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>This last example only shows that the script is being parsed by a <code class="system-font dark">bash</code> interpeter, but not which one. It could be <code class="system-font boxed">/bin/bash</code> or <code class="system-font boxed">/usr/local/bin/bash</code> or another <code class="system-font dark">bash</code> interpreter. </p>
<p>To see which interpreter is being used, overwrite the existing script to include the <code class="system-font boxed">which</code> command:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
cat &lt;&lt; 'EOF' &gt; "${HOME}/which-interpreter.sh"
<span class="text-blue"><b>#!/bin/bash</b></span>
<span class="text-red">which $(</span>ps -p "$$" | tail -1 | awk '{print $4}'<span class="text-red">)</span>
EOF
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Now run the amended script:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
/usr/bin/env bash "${HOME}/which-interpreter.sh"
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
/usr/local/bin/bash
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Using <code class="system-font boxed">/usr/bin/env bash</code> from the command prompt or as part of a shebang instructs the script to use a <code class="system-font dark">bash</code> interpreter to parse its contents, but doesn&#8217;t explicitly state which one. That is determined by the user&#8217;s search path which is stored in the <code class="system-font boxed">PATH</code> environmental variable:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
echo $PATH
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The script is parsed by the first instance of <code class="system-font dark">bash</code> found in the search path. In my case this is <code class="system-font boxed">/usr/local/bin/bash</code>, not <code class="system-font boxed">/bin/bash</code>.</p>
<p>Overwrite the existing script changing the shebang to <code class="system-font boxed">#!/usr/bin/env bash</code>:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
cat &lt;&lt; 'EOF' &gt; "${HOME}/which-interpreter.sh"
<span class="text-blue"><b>#!/usr/bin/env bash</b></span>
<span class="text-red">which $(</span>ps -p "$$" | tail -1 | awk '{print $4}'<span class="text-red">)</span>
EOF
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Run the amended script:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
"${HOME}/which-interpreter.sh"
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
/usr/local/bin/bash
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Care should be taken when using <code class="system-font dark">launchd</code> to execute scripts with this type of shebang as <code class="system-font dark">launchd</code> has a default search path limited to <code class="system-font boxed">/usr/bin:/bin:/usr/sbin:/sbin</code>. Consequently, if this script were run by <code class="system-font dark">launchd</code> it would be parsed by the only available <code class="system-font dark">bash</code> interpeter in that search path: <code class="system-font boxed">/bin/bash</code>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6451</post-id>	</item>
		<item>
		<title>iRedMail Configuration Tips and Time-Savers</title>
		<link>https://www.tech-otaku.com/vps/iredmail-configuration-tips-and-time-savers/</link>
					<comments>https://www.tech-otaku.com/vps/iredmail-configuration-tips-and-time-savers/#comments</comments>
		
		<dc:creator><![CDATA[Steve]]></dc:creator>
		<pubDate>Sat, 07 Dec 2019 07:42:26 +0000</pubDate>
				<category><![CDATA[VPS]]></category>
		<category><![CDATA[iRedMail]]></category>
		<category><![CDATA[Mail Server]]></category>
		<guid isPermaLink="false">https://www.tech-otaku.com/?p=6090</guid>

					<description><![CDATA[By all accounts setting-up your own mail server can be a complex task and one I&#8217;ve always shied away from until recently when I thought I&#8217;d give iRedMail a go. Thanks to this open-source mail server solution I now have my own fully-functioning, well-configured mail server handling mail for numerous mail accounts on several domains. [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>By all accounts setting-up your own mail server can be a complex task and one I&#8217;ve always shied away from until recently when I thought I&#8217;d give <a href="https://www.iredmail.org" target="_blank" rel="noopener noreferrer">iRedMail</a> a go. Thanks to this open-source mail server solution I now have my own fully-functioning, well-configured mail server handling mail for numerous mail accounts on several domains.</p>
<p><span id="more-6090"></span></p>
<p>Getting to this stage wasn&#8217;t easy, but not the nightmare it is often portrayed as. I relied heavily on these excellent guides to get the mail server up-and-running: <a href="https://www.linuxbabe.com/mail-server/ubuntu-18-04-iredmail-email-server" target="_blank" rel="noopener noreferrer">How to Easily Set Up a Full-Featured Mail Server on Ubuntu 18.04 with iRedMail</a> and <a href="https://www.linuxbabe.com/mail-server/set-up-iredmail-multiple-domains-nginx" target="_blank" rel="noopener noreferrer">How to Host Multiple Mail Domains in iRedMail with Nginx</a> and then the <a href="https://docs.iredmail.org/index.html" target="_blank" rel="noopener noreferrer">official iRedMail documentation</a> to fine tune the components.</p>
<p>During testing I re-provisioned the mail server many, many, many times and developed my own way of doing things, some of which may be useful to others.</p>
<p><span class="text-red">Please note that the following were tested using iRedMail version 1.3.1.</span></p>
<div>
<h3 id="toc" class="content-heading-text">Table of Contents</h3>
<ul class="arrow_list">
<li><a rel="bookmark nofollow" href="#1">1. Create New Mail Domains from the Command Line</a></li>
<li><a rel="bookmark nofollow" href="#2">2. Create New Mail Accounts from the Command Line</a></li>
<li><a rel="bookmark nofollow" href="#3">3. SOGo and Memcached</a></li>
<li><a rel="bookmark nofollow" href="#4">4. Fail2ban Log File</a></li>
</ul>
</div>
<div id="1" class="container">
<div class="divider"></div>
<p><a class="top" href="#toc">TOC</a></div>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<h3>1. Create New Mail Domains from the Command Line</h3>
<p>During installation iRedMail configures a single mail domain. Additional mail domains can be added using iRedAdmin &#8211; the iRedMail web admin panel. During testing a more efficient, consistent and convenient way for me to create new mail domains was from the MySQL command-line client.</p>
<p>To invoke the MySQL client as root:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
sudo mysql -u root
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>To create the new mail domain:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
SET @DOMAIN:='domain.com';
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
INSERT INTO `vmail`.`domain` (`domain`, `transport`, `settings`, `created`, `active`) VALUES (@DOMAIN, 'dovecot', 'default_user_quota:512;', NOW(), '1');
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>To display the newly created mail domain record:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
SELECT `domain`, `transport`, `settings`, `created`, `active` FROM `vmail`.`domain` WHERE `domain`=@DOMAIN;
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<div id="2" class="container">
<div class="divider"></div>
<p><a class="top" href="#toc">TOC</a></div>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<h3>2. Create New Mail Accounts from the Command Line</h3>
<p>iRedMail ships with a script &#8211; <code class="system-font boxed">create_mail_user_SQL.sh</code> – to create mail accounts from the command line. The script requires two parameters &#8211; email address and password:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
<span class="text-blue">ADDRESS</span>='steve@example.com'; \
<span class="text-blue">PASSWORD</span>='pAss71woRd'; \
cd ${HOME}/iRedMail-1.3.1/tools; \
bash create_mail_user_SQL.sh <span class="text-blue">$ADDRESS $PASSWORD</span> &gt; user.sql; \
sudo mysql -u root -p -D vmail -e "SOURCE user.sql"; \
rm -f user.sql
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>The script does not allow the user&#8217;s quota to be set on an individual basis without amending the hard-coded value in the script file each time nor does it capitalise the first letter of the user&#8217;s name – <code class="system-font boxed">steve</code> instead of <code class="system-font boxed">Steve</code> – which is derived from the user&#8217;s email address.</p>
<p>Using <code class="system-font boxed">sed</code> the original script can be amended so that it accepts the user&#8217;s quota as a third parameter and automatically capitalises the user&#8217;s first name. The differences between the original and amended script are detailed <a href="https://www.diffchecker.com/PQR0St0R" target="_blank" rel="noopener noreferrer">here</a>:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
sed -i.$(date +"%Y%m%d-%H%M%S") -e "s/^DEFAULT_QUOTA='1024'/DEFAULT_QUOTA=\$3/" -e "s/X'2'/X'3'/" -e "s/ltd plain_password/ltd plain_password mail_quota/" -e "s/'\${username}'/\"\$(echo \${username} | awk '{print toupper(substr(\$0,0,1))tolower(substr(\$0,2))}')\"/" $HOME/iRedMail-1.3.1/tools/create_mail_user_SQL.sh
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>The script can now be run with with a value for the user&#8217;s quota. Note that a value of <code class="system-font boxed">0</code> means there is no restriction on the size of the mailbox:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
<span class="text-blue">ADDRESS</span>='steve@example.com'; \
<span class="text-blue">PASSWORD</span>='pAss71woRd'; \
<span class="text-blue">QUOTA</span>='0'; \
cd ${HOME}/iRedMail-1.3.1/tools; \
bash create_mail_user_SQL.sh <span class="text-blue">$ADDRESS $PASSWORD $QUOTA</span> &gt; user.sql; \
sudo mysql -u root -p -D vmail -e "SOURCE user.sql"; \
rm -f user.sql
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. -->  </p>
<div id="3" class="container">
<div class="divider"></div>
<p><a class="top" href="#toc">TOC</a></div>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<h3>3. SOGo and Memcached</h3>
<p>If you opted to have SOGo installed by the iRedMail installer you may see a lot of errors afterward containing <code class="system-font boxed">SERVER HAS FAILED AND IS DISABLED UNTIL TIMED RETRY</code> in <code class="system-font boxed">/var/log/sogo/sogo.log</code> and when the script <code class="system-font boxed">/var/vmail/backup/backup_sogo.sh</code> is executed (usually as a daily cronjob). This is due to Memcached either not being installed or the Memcached server not running.</p>
<p>On Ubuntu, to check if Memcached is installed:</p>
<p> <span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
dpkg -L memcached
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output (Not Installed)</div>
<pre>
dpkg-query: package 'memcached' is not installed
Use dpkg --info (= dpkg-deb --info) to examine archive files,
and dpkg --contents (= dpkg-deb --contents) to list their contents.
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output (Installed)</div>
<pre>
/.
/etc
/etc/default
/etc/default/memcached
/etc/init.d
/etc/init.d/memcached
/lib
/lib/systemd
/lib/systemd/system
/lib/systemd/system/memcached.service
/usr
/usr/bin
/usr/bin/memcached
/usr/include
/usr/include/memcached
/usr/include/memcached/protocol_binary.h
/usr/lib
/usr/lib/tmpfiles.d
/usr/lib/tmpfiles.d/memcached.conf
/usr/share
/usr/share/doc
/usr/share/doc/memcached
/usr/share/doc/memcached/NEWS.Debian.gz
/usr/share/doc/memcached/NEWS.gz
/usr/share/doc/memcached/README.Debian
/usr/share/doc/memcached/README.md
/usr/share/doc/memcached/changelog.Debian.gz
/usr/share/doc/memcached/copyright
/usr/share/doc/memcached/protocol.txt.gz
/usr/share/man
/usr/share/man/man1
/usr/share/man/man1/memcached.1.gz
/usr/share/memcached
/usr/share/memcached/memcached.conf.default
/usr/share/memcached/scripts
/usr/share/memcached/scripts/README.damemtop
/usr/share/memcached/scripts/damemtop
/usr/share/memcached/scripts/damemtop.yaml
/usr/share/memcached/scripts/memcached-tool
/usr/share/memcached/scripts/start-memcached
/usr/share/memcached/scripts/systemd-memcached-wrapper
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To install Memcached:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
sudo apt-get install -y memcached
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>After installing Memcached you&#8217;d be forgiven for thinking the Memcached server has started and is running without issue. To check the status of Memcached:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
sudo systemctl status memcached
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output (Server Started)</div>
<pre>
<span class="text-green">●</span> memcached.service - memcached daemon
   Loaded: loaded (/lib/systemd/system/memcached.service; enabled; vendor preset: enabled)
   Active: <span class="text-green">active (running)</span> since Sun 2019-12-29 07:32:50 GMT; 2s ago
     Docs: man:memcached(1)
 Main PID: 19952 (memcached)
    Tasks: 10 (limit: 4583)
   CGroup: /system.slice/memcached.service
           └─19952 /usr/bin/memcached -u memcache -l 127.0.0.1
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output (Server Failed To Start)</div>
<pre>
<span class="text-red">●</span> memcached.service - memcached daemon
   Loaded: loaded (/lib/systemd/system/memcached.service; enabled; vendor preset: enabled)
   Active: <span class="text-red">failed</span> (Result: exit-code) since Sun 2019-12-29 07:20:23 GMT; 7min ago
     Docs: man:memcached(1)
  Process: 19857 ExecStart=/usr/share/memcached/scripts/systemd-memcached-wrapper /etc/memcached.conf <span class="text-red">(code=exited, status=64)</span>
 Main PID: 19857 (code=exited, status=64)

Dec 29 07:20:23 mail.example.com systemd[1]: memcached.service: Service hold-off time over, scheduling restart.
Dec 29 07:20:23 mail.example.com systemd[1]: memcached.service: Scheduled restart job, restart counter is at 5.
Dec 29 07:20:23 mail.example.com systemd[1]: Stopped memcached daemon.
Dec 29 07:20:23 mail.example.com systemd[1]: memcached.service: Start request repeated too quickly.
Dec 29 07:20:23 mail.example.com systemd[1]: memcached.service: Failed with result 'exit-code'.
Dec 29 07:20:23 mail.example.com systemd[1]: <span class="text-red">Failed to start memcached daemon.</span>
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>When failing to start, the status messages don&#8217;t really give any clues as to why, but looking at <code class="system-font boxed">/var/log/syslog</code> specifically for the <code class="system-font dark">Failed to start memcached daemon</code> message gives a clue: <code class="system-font dark">can't run as root without the -u switch</code></p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
sudo grep -B 8 'Failed to start memcached daemon' /var/log/syslog
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
Dec 29 07:20:22 mail systemd-memcached-wrapper[19857]: <span class="text-red">can't run as root without the -u switch</span>
Dec 29 07:20:22 mail systemd[1]: memcached.service: Main process exited, code=exited, status=64/n/a
Dec 29 07:20:22 mail systemd[1]: memcached.service: Failed with result 'exit-code'.
Dec 29 07:20:23 mail systemd[1]: memcached.service: Service hold-off time over, scheduling restart.
Dec 29 07:20:23 mail systemd[1]: memcached.service: Scheduled restart job, restart counter is at 5.
Dec 29 07:20:23 mail systemd[1]: Stopped memcached daemon.
Dec 29 07:20:23 mail systemd[1]: memcached.service: Start request repeated too quickly.
Dec 29 07:20:23 mail systemd[1]: memcached.service: Failed with result 'exit-code'.
Dec 29 07:20:23 mail systemd[1]: Failed to start memcached daemon.
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To start the Memcached server &#8211; not as <code class="system-font boxed">root</code>, but as user <code class="system-font boxed">memcache</code> &#8211; add the following line to the file <code class="system-font boxed">/etc/memcached.conf</code>:</p>
<pre class="brush: conf;gutter: true;first-line: 1;highlight: 1;">
-u memcache
-l 127.0.0.1
</pre>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Start the Memcached server:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
sudo systemctl start memcached
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<div id="4" class="container">
<div class="divider"></div>
<p><a class="top" href="#toc">TOC</a></div>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<h3>4. Fail2ban Log File</h3>
<p>The Fail2ban log file at <code class="system-font boxed">/var/log/fail2ban.log</code> contains notifications of IP addresses first banned and subsequently unbanned from accessing your mail server.</p>
<p>The log file is initially created as owned by user <code class="system-font boxed">syslog</code> with <code class="system-font boxed">read/write</code> permissions and group <code class="system-font boxed">adm</code> with <code class="system-font boxed">read-only</code> permissions:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
ls -lah /var/log/fail2ban.log
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
-rw-r----- 1 syslog adm 13K Sep 15 14:15 /var/log/fail2ban.log
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The Faile2ban log file is rotated on a weekly basis when <code class="system-font boxed">/var/log/fail2ban.log</code> becomes <code class="system-font boxed">/var/log/fail2ban.log.1</code> and a new <code class="system-font boxed">/var/log/fail2ban.log</code> is created. However, the newly created file is now owned by <code class="system-font boxed">root</code> and consequently notifications will no longer be written to the new Fail2ban log file and it will remain empty:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
ls -lah /var/log/fail2ban.log
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
-rw-r----- 1 <span class="text-red">root</span> adm 0K Sep 20 06:25 /var/log/fail2ban.log
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The reason for this change in ownership is due to the Logrotate configuration file for Fail2ban:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
cat /etc/logrotate.d/fail2ban
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
/var/log/fail2ban.log {

    ...

    # If fail2ban runs as non-root it still needs to have write access
    # to logfiles.
    # create 640 fail2ban adm
    create 640 <span class="text-red">root</span> adm
}
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The line responsible for the Fail2ban log&#8217;s change in ownership is <code class="system-font boxed">create 640 root adm</code>. Change this to <code class="system-font boxed">create 640 syslog adm</code> and in future and any <code class="system-font boxed">/var/log/fail2ban.log</code> will be writable:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
sudo sed -i.$(date +"%Y%m%d-%H%M%S") 's/create 640 root adm/create 640 syslog adm/' /etc/logrotate.d/fail2ban &amp;&amp; cat /etc/logrotate.d/fail2ban
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
/var/log/fail2ban.log {

    ...

    # If fail2ban runs as non-root it still needs to have write access
    # to logfiles.
    # create 640 fail2ban adm
    create 640 syslog adm
}
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>If you have an existing <code class="system-font boxed">/var/log/fail2ban.log</code> owned by root, change its ownership:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
sudo chown syslog /var/log/fail2ban.log
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-otaku.com/vps/iredmail-configuration-tips-and-time-savers/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6090</post-id>	</item>
		<item>
		<title>Securing Access to Webmin through an SSH Tunnel</title>
		<link>https://www.tech-otaku.com/networking/securing-access-to-webmin-through-an-ssh-tunnel/</link>
					<comments>https://www.tech-otaku.com/networking/securing-access-to-webmin-through-an-ssh-tunnel/#comments</comments>
		
		<dc:creator><![CDATA[Steve]]></dc:creator>
		<pubDate>Sun, 01 Sep 2019 16:03:27 +0000</pubDate>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[Port Forwading]]></category>
		<category><![CDATA[SSH]]></category>
		<category><![CDATA[Webmin]]></category>
		<guid isPermaLink="false">https://www.tech-otaku.com/?p=5567</guid>

					<description><![CDATA[Webmin is installed on the server that hosts this site and for the longest time I&#8217;ve been accessing it remotely through its default port at https://tech-otaku.com:10000. Despite connections being encrypted through SSL and having two-factor authentication enabled in Webmin this still presents a security risk. Changing the port Webmin listens on or using Webmin&#8217;s IP [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><a href="http://www.webmin.com" target="_blank" rel="noopener noreferrer">Webmin</a> is installed on the server that hosts this site and for the longest time I&#8217;ve been accessing it remotely through its default port at <code class="system-font boxed">https://tech-otaku.com:10000</code>. Despite connections being encrypted through <abbr title="Secure Sockets Layer">SSL</abbr> and having two-factor authentication enabled in Webmin this still presents a security risk.</p>
<p><span id="more-5567"></span></p>
<p>Changing the port Webmin listens on or using Webmin&#8217;s <abbr title="Internet Protocol">IP</abbr> Access Control to allow access to a limited number of IP addresses may reduce the risk, but not eliminate it. As I&#8217;m the only one who requires access to Webmin, it makes more sense to block remote access entirely and allow only limited local access using local port forwarding through an <abbr title="Secure Shell">SSH</abbr> tunnel.</p>
<p class="line-break">&nbsp;</p>
<h4>Remote Access to Webmin</h4>
<p><!-- START: Markup generated by ~/Dropbox/Scripts/Applications/Finder/Generate Post Image HTML.scpt on Saturday, 31 August 2019 at 14:48:19 --><br />
<!-- Original image dimensions are w2900 x h1470. Reduced to 25% (w725 x h368) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
		<a href="http://www.tech-otaku.com/wp-content/uploads/5567-01-remote-access-to-webmin.png" title="'Remote access to webmin' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-0" data-rl_title="" data-rl_caption=""><img loading="lazy" decoding="async" src="/wp-content/uploads/5567-01-remote-access-to-webmin.png" alt="Remote access to webmin" width="725" height="368" /></a>
	</div><figcaption class="post-image-caption">Fig. 1 &#8211; Remote access to webmin</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<p>Figure 1 shows applications on a local computer – <i>client</i> – sending requests to a remote host – <i>server</i> – and the appropriate applications on the <i>server</i> handling those requests and sending data back to the <i>client</i> applications. The <i>server&#8217;s</i> firewall blocks all incoming requests except to those ports that have been explicitly opened.</p>
<p> On the <i>server</i>, <a href="https://help.ubuntu.com/community/UFW" target="_blank" rel="noopener noreferrer">ufw</a> will show which ports are open:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
sudo ufw status 
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
To                         Action      From
--                         ------      ----
10000/tcp                  ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
22/tcp                     LIMIT       Anywhere
10000/tcp (v6)             ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
22/tcp (v6)                LIMIT       Anywhere (v6)
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. -->  </p>
<p>The Webmin server – Miniserv &#8211; is listening for requests on port 10000. As port 10000 is open in the server&#8217;s firewall, any <i>client</i> requests on port 10000 will reach and be handled by the Webmin server rendering the Webmin login page accessible to anyone with Internet access.</p>
<p class="line-break">&nbsp;</p>
<h4>Blocking Access to Webmin</h4>
<p>The first step in securing access to Webmin is to close the port in the <i>server</i> firewall that the Webmin server listens on for <i>client</i> requests. We do this with <code class="system-font boxed">ufw</code> by deleting the rule that explicitly opens port 10000:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
sudo ufw delete allow 10000/tcp
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
Rule deleted
Rule deleted (v6)
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p><!-- START: Markup generated by ~/Dropbox/Scripts/Applications/Finder/Generate Post Image HTML.scpt on Saturday, 31 August 2019 at 14:53:52 --><br />
<!-- Original image dimensions are w2900 x h1473. Reduced to 25% (w725 x h368) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
		<a href="http://www.tech-otaku.com/wp-content/uploads/5567-02-blocking-remote-access-to-webmin-through-port-10000.png" title="'Closing port 10000 to block remote access to Webmin' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-1" data-rl_title="" data-rl_caption=""><img loading="lazy" decoding="async" src="/wp-content/uploads/5567-02-blocking-remote-access-to-webmin-through-port-10000.png" alt="Closing port 10000 to block remote access to Webmin" width="725" height="368" /></a>
	</div><figcaption class="post-image-caption">Fig. 2 &#8211; Closing port 10000 to block remote access to Webmin</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<p>Figure 2 shows the <i>client</i> browser still sending requests on port 10000 to the Webmin server and the Webmin server still listening for requests on that same port. However, as port 10000 is no longer open in the <i>server</i> firewall, the Webmin server will never receive the <i>client</i> requests.</p>
<p>Webmin is – for now – inaccessible to everyone.</p>
<p class="line-break">&nbsp;</p>
<h4>Accessing Webmin Through an SSH Tunnel</h4>
<p>I&#8217;m going to provide access to Webmin by routing browser requests for it through an encrypted SSH connection between the <i>client</i> and the <i>server</i> and have these requests forwarded to Webmin. Figure 3 demonstrates this process:</p>
<p><!-- START: Markup generated by ~/Dropbox/Scripts/Applications/Finder/Generate Post Image HTML.scpt on Saturday, 31 August 2019 at 14:55:21 --><br />
<!-- Original image dimensions are w2900 x h1470. Reduced to 25% (w725 x h368) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
		<a href="http://www.tech-otaku.com/wp-content/uploads/5567-03-securing-access-to-webmin-through-an-ssh-tunnel.png" title="'Securing access to Webmin through an SSH tunnel' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-2" data-rl_title="" data-rl_caption=""><img loading="lazy" decoding="async" src="/wp-content/uploads/5567-03-securing-access-to-webmin-through-an-ssh-tunnel.png" alt="Securing access to Webmin through an SSH tunnel" width="725" height="368" /></a>
	</div><figcaption class="post-image-caption">Fig. 3 &#8211; Securing access to Webmin through an SSH tunnel</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<ol>
<li>
<p>The <i>client</i> establishes an encrypted SSH connection to the <i>server</i> on port 22&#8230;</p>
</li>
<li>
<p>&#8230;simultaneously opening local port 10005 on the <i>client</i>.</p>
</li>
<li>
<p>The browser no longer sends requests directly to Webmin on the <i>server</i>, but to local port 10005 instead.</p>
</li>
<li>
<p>All requests received on local port 10005 are then forwarded or tunnelled through the encrypted SSH connection to the <i>server</i>.</p>
</li>
<li>
<p>The <i>server</i> forwards the requests onward to the Webmin server on port 10000.</p>
</li>
</ol>
<p>The advantage of this approach is the ability to limit Webmin access to only those users who can connect to the <i>server</i> via SSH. In addition, SSH provides an encrypted connection. Any plain text data being tunneled through it will benefit from that secure connection. This means that Webmin can be accessed over <abbr title="Hypertext Transfer Protocol">HTTP</abbr> as the plain text data being sent to and from the Webmin server doesn&#8217;t need the encryption of <abbr title="Transport Layer Security">TLS</abbr>/<abbr title="Secure Sockets Layer">SSL</abbr> that <abbr title="Hypertext Transfer Protocol Secure">HTTPS</abbr> provides.</p>
<p>In general, on a macOS or Ubuntu Desktop <i>client</i> the command to establish local port forwarding through an SSH tunnel is:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
ssh -p 22 user@host -L &#x3C;local-port&#x3E;:&#x3C;remote-host&#x3E;:&#x3C;remote-port&#x3E; -N &#x26;
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>More specifically, for the example in figure 3 the command is:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
ssh -p 22 penny@203.0.113.5 -L 10005:127.0.0.1:10000 -N &#x26;
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
[1] 5907
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Please note the following:</p>
<ul>
<li style="list-style-type: circle">
<p><code class="system-font boxed">-p 22</code> does not need to be included in the command if the SSH server is listening on the default port 22. However, if it&#8217;s listening on say port 5522, <code class="system-font boxed">-p 5522</code> would have to be part of the command.</p>
</li>
<li style="list-style-type: circle">
<p>Thinking that <code class="system-font boxed">127.0.0.1</code> refers to a localhost on a <code class="system-font boxed">client</code>, it took me a while to understand why it is being used for the <code class="system-font boxed">&#x3C;remote-host&#x3E;</code> until I realised it&#8217;s viewed from the perspective of the <i>server</i> not the <i>client</i>.</p>
</li>
<li style="list-style-type: circle">
<p><code class="system-font boxed">&amp;</code> puts SSH into the background which is useful if you want to continue using the same Terminal window. I prefer this to the <code class="system-font boxed">-f</code> option which is part of <code class="system-font boxed">ssh</code> as I find it easier to terminate the SSH tunnel having used the former option. On a Ubuntu Desktop <i>client</i> you may need to press enter to drop back to the command prompt after using <code class="system-font boxed">&amp;</code>.</p>
</li>
</ul>
<p>Having established the SSH tunnel and forwarded the local <i>client</i> port 10005 to the remote <i>server</i> port 10000, Webmin can be accessed from a browser using:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">URL</div>
<pre>
http://localhost:10005
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>You may receive an error that Webmin should be accessed using <code class="system-font boxed">https://</code> instead of <code class="system-font boxed">http://</code>. This is more than likely because SSL is enabled in the Webmin server configuration. You can continue by using <code class="system-font boxed">https://localhost:10005</code>, but your browser will warn you that the connection is not private.</p>
</p>
<p>We know that any plain text data bound for the Webmin server will be sent through the encrypted SSH tunnel, so my preferred method is to disable SSL on the Webmin server and access Webmin through <code class="system-font boxed">http://localhost:10005</code>.</p>
<p>To disable SSL on the Webmin server we need to change <code class="system-font boxed">ssl=1</code> to <code class="system-font boxed">ssl=0</code> in the file <code class="system-font boxed">/etc/webmin/miniserv.conf</code> on the <i>server</i>. To do this, on the <i>server</i> type:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
sudo sed -i.$(date +"%Y%m%d-%H%M%S") 's/^ssl=1$/ssl=0/' /etc/webmin/miniserv.conf
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>Then restart the Webmin server:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
sudo systemctl restart webmin
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p class="line-break">&nbsp;</p>
<h4>Terminating the SSH Tunnel</h4>
<p>When you&#8217;ve finished your Webmin session, it&#8217;s good practice to terminate the SSH tunnel. If you used the <code class="system-font boxed">&amp;</code> option when creating the SSH tunnel, from the same Terminal window type:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
jobs
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
[1]+  Running                 ssh -p 22 penny@203.0.113.5 -L 10005:127.0.0.1:10000 -N &#x26;
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>This will display any process running in the background each of which will start with a number in square brackets. Bring the relevant process to the foreground by typing:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
fg 1
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
ssh -p 22 penny@203.0.113.5 -L 10005:127.0.0.1:10000 -N
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To end the process type <kbd>Ctrl</kbd>+<kbd>C</kbd> and the SSH tunnel is no more.</p>
<p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.tech-otaku.com/networking/securing-access-to-webmin-through-an-ssh-tunnel/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5567</post-id>	</item>
		<item>
		<title>Installing and Configuring WP-CLI on macOS</title>
		<link>https://www.tech-otaku.com/mac/installing-configuring-wp-cli-macos/</link>
		
		<dc:creator><![CDATA[Steve]]></dc:creator>
		<pubDate>Thu, 27 Jun 2019 16:28:32 +0000</pubDate>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[macOS]]></category>
		<category><![CDATA[Terminal]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://www.tech-otaku.com/?p=5524</guid>

					<description><![CDATA[WP-CLI is the command-line interface for WordPress. It allows you to manage your WordPress site from the command line without using a web browser. I currently use WP-CLI to temporarily disable the WordPress Google Authenticator plugin, create and configure a version of this site to run in a local AMP environment on my Mac and [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><a href="https://wp-cli.org" target="_blank" rel="noopener noreferrer">WP-CLI</a> is the command-line interface for WordPress. It allows you to manage your WordPress site from the command line without using a web browser. I currently use WP-CLI to <a href="https://www.tech-otaku.com/web-development/temporarily-disabling-the-wordpress-google-authenticator-plugin-from-the-command-line/#method-2" target="_blank" rel="noopener noreferrer">temporarily disable the WordPress Google Authenticator plugin</a>, create and configure a version of this site to run in a local AMP environment on my Mac and <a href="https://www.tech-otaku.com/web-development/using-wp-cli-to-update-wordpress-theme-options/" target="_blank" rel="noopener noreferrer">periodically change the posts that appear in the slider on this site&#8217;s home page</a>.</p>
<p><span id="more-5524"></span></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<h4>Installing WP-CLI</h4>
<p>There are several ways of <a href="https://make.wordpress.org/cli/handbook/installing" target="_blank" rel="noopener noreferrer">installing</a> WP-CLI. I chose the Homebrew <a href="https://make.wordpress.org/cli/handbook/installing/#installing-via-homebrew" target="_blank" rel="noopener noreferrer">method</a> as <a href="https://brew.sh" target="_blank" rel="noopener noreferrer">Homebrew</a> is already installed on my Mac. In <code class="system-font dark">Terminal</code> or similar terminal emulator type:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
brew install wp-cli
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>The Homebrew method creates the following directory structure:</p>
<pre>
/usr/local/bin/wp <span class="text-blue">-&gt; /usr/local/Cellar/wp-cli/2.2.0/bin/wp</span>
/usr/local/Cellar/wp-cli
/usr/local/Cellar/wp-cli/2.2.0
/usr/local/Cellar/wp-cli/2.2.0/.brew
/usr/local/Cellar/wp-cli/2.2.0/.brew/wp-cli.rb
/usr/local/Cellar/wp-cli/2.2.0/bin
/usr/local/Cellar/wp-cli/2.2.0/bin/wp
/usr/local/Cellar/wp-cli/2.2.0/INSTALL_RECEIPT.json
/usr/local/opt/wp-cli <span class="text-blue">-&gt; /usr/local/Cellar/wp-cli/2.2.0</span>
/usr/local/var/homebrew/linked/wp-cli <span class="text-blue">-&gt; /usr/local/Cellar/wp-cli/2.2.0</span>
</pre>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To show information on WP-CLI, in <code class="system-font dark">Terminal</code> type:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
wp cli info
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
OS:	Darwin 18.6.0 Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDT 2019; root:xnu-4903.261.4~2/RELEASE_X86_64 x86_64
Shell:	/bin/bash
PHP binary:	/usr/bin/php
PHP version:	7.1.23
php.ini used:
WP-CLI root dir:	phar://wp-cli.phar/vendor/wp-cli/wp-cli
WP-CLI vendor dir:	phar://wp-cli.phar/vendor
WP_CLI phar path:	/Users/steve
WP-CLI packages dir:
WP-CLI global config:
WP-CLI project config:
WP-CLI version:	2.2.0
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<h4>A WP-CLI Command Example</h4>
<p>The basic format for using WP-CLI is <code class="system-font boxed">wp &lt;command&gt; &lt;sub-command&gt; &lt;options&gt;</code>. For example, to get a site&#8217;s url, in <code class="system-font dark">Terminal</code> type:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
wp option get siteurl
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
Error: This does not seem to be a WordPress installation.
Pass --path=`path/to/wordpress` or run `wp core download`.
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>However – as can be seen from the output – this throws an error as <code class="system-font boxed">wp</code> is looking for a non-existent WordPress installation in the current directory. To remedy this we need to supply the path to the WordPress installation to <code class="system-font boxed">wp</code>. This will most likely be the same as the site&#8217;s <code class="system-font boxed">DocumentRoot</code> as defined in the Apache configuration files.</p>
<p>To get the url for a site running in a local AMP environment, in <code class="system-font dark">Terminal</code> type:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
wp option get siteurl --path=/local/path/to/wordpress/install
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
http://local.tech-otaku
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>When getting a url for a remote site we need to pass <abbr title="Secure Shell">SSH</abbr> login details in the form of name, address and port to <code class="system-font boxed">wp</code> along with the remote path to the WordPress installation:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
wp option get siteurl --ssh=ben@12.34.56.789:2222 --path=/remote/path/to/wordpress/install
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
https&#058;&#047;&#047;www.tech-otaku.com
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>NOTE: When accessing WordPress data on a remote host, WP-CLI must also be installed on that remote host. For a Linux host use the <a href="https://make.wordpress.org/cli/handbook/installing/#recommended-installation" target="_blank" rel="noopener noreferrer">recommended install</a> method.</p>
<p>In the examples above, <code class="system-font boxed">--ssh</code> and <code class="system-font boxed">--path</code> are two of WP-CLI&#8217;s <a href="https://make.wordpress.org/cli/handbook/config/#global-parameters" target="_blank" rel="noopener noreferrer">global parameters</a>. When used on the command line they should be placed at the end of the command string or immediately after <code class="system-font boxed">wp</code>.</p>
<p>For a complete list of WP-CLI commands see <a href="https://developer.wordpress.org/cli/commands/" target="_blank" rel="noopener noreferrer">WP-CLI Commands</a>.</p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<h4>Creating an Alias to a WordPress Installation</h4>
<p>Passing global parameters on the command line can prove cumbersome. Fortunately, we can create a one-word alias to each site we want to access and use that alias on the command line instead of passing global parameters. Each alias along with its relevant information is stored in the WP-CLI global configuration file: <code class="system-font boxed">~/.wp-cli/config.yml</code>.</p>
<p>On a fresh WP-CLI installation this global configuration file doesn&#8217;t exist. You can create and edit it using a text editor or – as I prefer – create it from the command line and then use WP-CLI to create each alias. In <code class="system-font dark">Terminal</code> type:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
mkdir ~/.wp-cli &amp;&amp; touch ~/.wp-cli/config.yml
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>An alternative to creating this global configuration file in your home directory is to create the structure in a directory of a file sharing service like iCloud Drive or Dropbox, then create a symbolic link to the directory containing the configuration file in your home directory. This way you&#8217;re able to share a single global configuration with more than one Mac.</p>
</p>
<p>In this instance I name the directory <code class="system-font boxed">.wp-cli_shared</code> and the symbolic link <code class="system-font boxed">.wp-cli</code>.</p>
<p>To create the global configuration file in iCloud Drive, in <code class="system-font dark">Terminal</code> type:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
mkdir ~/Library/Mobile\ Documents/com~apple~CloudDocs/.wp-cli_shared &amp;&amp; touch ~/Library/Mobile\ Documents/com~apple~CloudDocs/.wp-cli_shared/config.yml
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To create the the symbolic link in your home drectory, in <code class="system-font dark">Terminal</code> type:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
ln -s ~/Library/Mobile\ Documents/com~apple~CloudDocs/.wp-cli_shared .wp-cli
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Having created the global configuration file, we can now create each alias. To create an alias named <code class="system-font boxed">@local</code> for a local WordPress installation, in <code class="system-font dark">Terminal</code> type:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
wp cli alias add @local --set-path=/local/path/to/wordpress/install --set-user=emily
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p>To create an alias named <code class="system-font boxed">@production</code> for a remote WordPress installation, in <code class="system-font dark">Terminal</code> type:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
wp cli alias add @production --ssh=ben@12.34.56.789:2222 --path=/remote/path/to/wordpress/install --set-user=chikako
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To view the contents of the global configuration file, in <code class="system-font dark">Terminal</code> type:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
cat ~/.wp-cli/config.yml
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
---
@local:
  path: /local/path/to/wordpress/install
  user: emily
@production:
  ssh: ben@12.34.56.789:2222
  path: /remote/path/to/wordpress/install
  user: chikako
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>To get either the local or remote site&#8217;s url I can now use the appropriate alias:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
wp @local option get siteurl
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
http://local.tech-otaku
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --> </p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Code</div>
<pre>
wp @production option get siteurl
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre>
https&#058;&#047;&#047;www.tech-otaku.com
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>NOTE: When using an alias on the command line it can only be placed immediately after <code class="system-font boxed">wp</code>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5524</post-id>	</item>
		<item>
		<title>Checking if a File Exists in iCloud from the Command Line</title>
		<link>https://www.tech-otaku.com/mac/checking-if-a-file-exists-in-icloud-from-the-command-line/</link>
		
		<dc:creator><![CDATA[Steve]]></dc:creator>
		<pubDate>Wed, 15 May 2019 14:09:41 +0000</pubDate>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[iCloud]]></category>
		<category><![CDATA[macOS]]></category>
		<category><![CDATA[Terminal]]></category>
		<guid isPermaLink="false">https://www.tech-otaku.com/?p=5472</guid>

					<description><![CDATA[While moving selected local files and folders to iCloud I came across a folder on my Mac containing a large number of documents some of which appeared to be duplicates of those on iCloud. Before deciding which ones to move, I wanted to check each one to see if it already existed on iCloud. Documents [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>While moving selected local files and folders to iCloud I came across a folder on my Mac containing a large number of documents some of which appeared to be duplicates of those on iCloud. Before deciding which ones to move, I wanted to check each one to see if it already existed on iCloud.</p>
<p><span id="more-5472"></span><!-- START: Markup generated by ~/Dropbox/Scripts/Applications/Finder/Generate Post Image HTML.scpt on Wednesday, 15 May 2019 at 10:06:44 --><br />
<!-- Original image dimensions are w1200 x h310. Reduced to 46% (w552 x h143) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
		<a href="http://www.tech-otaku.com/wp-content/uploads/5472-02-icloud-documents-folder.png" title="'Documents folder on iCloud Drive' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-0" data-rl_title="" data-rl_caption=""><img loading="lazy" decoding="async" src="/wp-content/uploads/5472-02-icloud-documents-folder.png" alt="Documents folder on iCloud Drive" width="552" height="143" /></a>
	</div><figcaption class="post-image-caption">Documents folder on iCloud Drive</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<p><!-- START: Markup generated by ~/Dropbox/Scripts/Applications/Finder/Generate Post Image HTML.scpt on Wednesday, 15 May 2019 at 10:10:20 --><br />
<!-- Original image dimensions are w1200 x h310. Reduced to 46% (w552 x h143) of the original size. --></p>
<figure class="post-image-frame">
<div class="frame">
		<a href="http://www.tech-otaku.com/wp-content/uploads/5472-01-temp-folder.png" title="'Local temp folder' in Lightbox" target="_blank" rel="lightbox noopener noreferrer" data-rel="lightbox-image-1" data-rl_title="" data-rl_caption=""><img loading="lazy" decoding="async" src="/wp-content/uploads/5472-01-temp-folder.png" alt="Local temp folder" width="552" height="143" /></a>
	</div><figcaption class="post-image-caption">Local temp folder</figcaption></figure>
<p class="line-break">&nbsp;</p>
<p class="line-break">&nbsp;</p>
<p><!-- // END --></p>
<p>A comparison of the two folders shows that of the four entries in the <code class="system-font boxed">temp</code> folder, the file named <code class="system-font boxed">file.txt</code> and the folder named <code class="system-font boxed">folder</code> don&#8217;t exist on iCloud.</p>
<p>This example only shows a fraction of the contents of each folder and so having written the Bash script below to loop through the contents of the <code class="system-font boxed">temp</code> folder checking for the existence of each entry on iCloud, I assumed the results would confirm the visual comparison.</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Script</div>
<pre class="brush: shell;">
#!/usr/bin/env bash

shopt -s nullglob
shopt -u dotglob

src="/Users/steve/temp"
trg="/Users/steve/Documents"

for entry in "$src"/{..?,.[!.],}*; do
	name=$(basename -- "$entry")
	if [ ! -e "$trg/$name" ]; then	# file doesn't exist on target
		echo "'$name' DOESN'T EXIST in $trg"
	else
		echo "'$name' already exists in $trg"
	fi
done

shopt -u nullglob
shopt -s dotglob
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: plain;  gutter: false; highlight: &#091;4&#093;;">
'file.txt' DOESN'T EXIST in /Users/steve/Documents
'folder' DOESN'T EXIST in /Users/steve/Documents
'Wordpress Plugins.docx' already exists in /Users/steve/Documents
'world_cup_2018.xlsx' DOESN'T EXIST in /Users/steve/Documents
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Not so. Clicking the <code class="system-font">OUTPUT</code> tab above shows the results are as expected except for the file <code class="system-font boxed">world_cup_2018.xlsx</code> which the script has determined as not being on iCloud when the <code class="system-font dark">Finder</code> clearly shows it is.</p>
<p>The clue to the script&#8217;s unexpected result is the <img loading="lazy" decoding="async" src="/wp-content/uploads/itunes-icloud-status-available-for-download-icon.png" alt="Documents folder on iCloud Drive" width="17" height="15" /> icon next to the <code class="system-font boxed">world_cup_2018.xlsx</code> file on iCloud which denotes the file has yet to be downloaded to the local drive.</p>
<p>Listing the <code class="system-font boxed">Document</code> folder&#8217;s contents on iCloud from the command line shows that such files are subject to a different naming convention not evident in the <code class="system-font dark">Finder</code> where the file name is prefixed with <code class="system-font boxed">.</code> – traditionally denoting a hidden file – and ends with <code class="system-font boxed">.icloud</code>.</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Command</div>
<pre>
ls -a /Users/steve/Documents
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: plain; gutter: false; highlight: &#091;1&#093;;">
.world_cup_2018.xlsx.icloud
Wordpress Plugins.docx
workout.xlsx
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p>Ammending the script to include an additional test for this other naming convention gives the expected results:</p>
<p><span class="meks-dummy-tab"><br />
<!-- This span element whose class has a `display:` property of `none;` contains a dummy Meks Horizontal Tab to overcome an issue where the first Meks Horizontal Tab after an anchor tag does not display correctly. --><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Dummy Tab</div>
Dummy Content<br />
</div>
</div>
</span><br />
<div class="mks_tabs horizontal"><div class="mks_tabs_nav"></div>
<div class="mks_tab_item"><div class="nav">Script</div>
<pre class="brush: shell; highlight: &#091;11&#093;;">
#!/usr/bin/env bash

shopt -s nullglob
shopt -u dotglob

src="/Users/steve/temp"
trg="/Users/steve/Documents"

for entry in "$src"/{..?,.[!.],}*; do
	name=$(basename -- "$entry")
	if [ ! -e "$trg/$name" ] &amp;&amp; [ ! -e "$trg/.$name.icloud" ]; then	# file doesn't exist on target
		echo "'$name' DOESN'T EXIST in $trg"
	else
		echo "'$name' already exists in $trg"
	fi
done

shopt -u nullglob
shopt -s dotglob
</pre>
</div>
<div class="mks_tab_item"><div class="nav">Output</div>
<pre class="brush: plain;  gutter: false; highlight: &#091;4&#093;;">
'file.txt' DOESN'T EXIST in /Users/steve/Documents
'folder' DOESN'T EXIST in /Users/steve/Documents
'Wordpress Plugins.docx' already exists in /Users/steve/Documents
'world_cup_2018.xlsx' already exists in /Users/steve/Documents
</pre>
</div>
</div>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
<p class="line-break">&nbsp;</p>
<p><!-- This is a line break. --></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5472</post-id>	</item>
	</channel>
</rss>
